Skip to content

docs: fix contribution link#12189

Merged
BeryJu merged 15 commits intomainfrom
root/fix-contribution-link
Nov 26, 2024
Merged

docs: fix contribution link#12189
BeryJu merged 15 commits intomainfrom
root/fix-contribution-link

Conversation

@kensternberg-authentik
Copy link
Contributor

@kensternberg-authentik kensternberg-authentik commented Nov 25, 2024

When the documentation was updated, the symbolic link between the root's CONTRIBUTING.md and the actual file was broken. (This isn't great behavior on the Github project page, whether it's working or not, because to Git all this does is record where the link goes and that it is a "soft" link. It's up to the local client to decide if it should replace the file with a link or not. Unix and Mac clients work correctly; I'm not sure if Windows ever caught up. Probably.)

  • The documentation has been updated

## What

- Bugfix: adds the InvalidationFlow to the Radius Provider dialogues
  - Repairs: `{"invalidation_flow":["This field is required."]}` message, which was *not* propagated
    to the Notification.
- Nitpick: Pretties `?foo=${true}` expressions: `s/\?([^=]+)=\$\{true\}/\1/`

## Note

Yes, I know I'm going to have to do more magic when we harmonize the forms, and no, I didn't add the
Property Mappings to the wizard, and yes, I know I'm going to have pain with the *new* version of
the wizard. But this is a serious bug; you can't make Radius servers with *either* of the current
dialogues at the moment.
* main: (43 commits)
  core, web: update translations (#11858)
  web/admin: fix code-based MFA toggle not working in wizard (#11854)
  sources/kerberos: add kiprop to ignored system principals (#11852)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#11846)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in it (#11845)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#11847)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#11848)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#11849)
  translate: Updates for file web/xliff/en.xlf in it (#11850)
  website: 2024.10 Release Notes (#11839)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#11814)
  core, web: update translations (#11821)
  core: bump goauthentik.io/api/v3 from 3.2024083.13 to 3.2024083.14 (#11830)
  core: bump service-identity from 24.1.0 to 24.2.0 (#11831)
  core: bump twilio from 9.3.5 to 9.3.6 (#11832)
  core: bump pytest-randomly from 3.15.0 to 3.16.0 (#11833)
  website/docs: Update social-logins github (#11822)
  website/docs: remove � (#11823)
  lifecycle: fix kdc5-config missing (#11826)
  website/docs: update preview status of different features (#11817)
  ...
* main:
  website: bump elliptic from 6.5.7 to 6.6.0 in /website (#11869)
  core: bump selenium from 4.25.0 to 4.26.0 (#11875)
  core: bump goauthentik.io/api/v3 from 3.2024083.14 to 3.2024100.1 (#11876)
  website/docs: add info about invalidation flow, default flows in general (#11800)
  website: fix docs redirect (#11873)
  website: remove RC disclaimer for version 2024.10 (#11871)
  website: update supported versions (#11841)
  web: bump API Client version (#11870)
  root: backport version bump 2024.10.0 (#11868)
  website/docs: 2024.8.4 release notes (#11862)
  web/admin: provide default invalidation flows for LDAP and Radius (#11861)
* main:
  core: add `None` check to a device's `extra_description` (#11904)
  providers/oauth2: fix size limited index for tokens (#11879)
  web: fix missing status code on failed build (#11903)
  website: bump docusaurus-theme-openapi-docs from 4.1.0 to 4.2.0 in /website (#11897)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#11891)
  stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#11884)
  translate: Updates for file web/xliff/en.xlf in tr (#11878)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in tr (#11866)
  core: bump google-api-python-client from 2.149.0 to 2.151.0 (#11885)
  core: bump selenium from 4.26.0 to 4.26.1 (#11886)
  core, web: update translations (#11896)
  website: bump docusaurus-plugin-openapi-docs from 4.1.0 to 4.2.0 in /website (#11898)
  core: bump watchdog from 5.0.3 to 6.0.0 (#11899)
  core: bump ruff from 0.7.1 to 0.7.2 (#11900)
  core: bump django-pglock from 1.6.2 to 1.7.0 (#11901)
  website/docs: fix release notes to say Federation (#11889)
* main:
  web: bump API Client version (#11909)
  enterprise/rac: fix API Schema for invalidation_flow (#11907)
* main:
  website/docs: fix slug matching redirect URI causing broken refresh (#11950)
  website/integrations: jellyfin: update plugin catalog location (#11948)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#11942)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#11946)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#11947)
  website/docs: clarify traefik ingress setup (#11938)
  core: bump importlib-metadata from 8.4.0 to 8.5.0 (#11934)
  web: bump API Client version (#11930)
  root: backport version bump `2024.10.1` (#11929)
  website/docs: `2024.10.1` Release Notes (#11926)
  website: bump path-to-regexp from 1.8.0 to 1.9.0 in /website (#11924)
  core: bump sentry-sdk from 2.17.0 to 2.18.0 (#11918)
  website: bump the docusaurus group in /website with 9 updates (#11917)
  core: bump goauthentik.io/api/v3 from 3.2024100.1 to 3.2024100.2 (#11915)
  core, web: update translations (#11914)
* main:
  ci: fix dockerfile warning (#11956)
* main: (21 commits)
  web: bump API Client version (#11997)
  sources/kerberos: use new python-kadmin implementation (#11932)
  core: add ability to provide reason for impersonation (#11951)
  website/integrations:  update vcenter integration docs (#11768)
  core, web: update translations (#11995)
  website: bump postcss from 8.4.48 to 8.4.49 in /website (#11996)
  web: bump API Client version (#11992)
  blueprints: add default Password policy (#11793)
  stages/captcha: Run interactive captcha in Frame (#11857)
  core, web: update translations (#11979)
  core: bump packaging from 24.1 to 24.2 (#11985)
  core: bump ruff from 0.7.2 to 0.7.3 (#11986)
  core: bump msgraph-sdk from 1.11.0 to 1.12.0 (#11987)
  website: bump the docusaurus group in /website with 9 updates (#11988)
  website: bump postcss from 8.4.47 to 8.4.48 in /website (#11989)
  stages/password: use recovery flow from brand (#11953)
  core: bump golang.org/x/sync from 0.8.0 to 0.9.0 (#11962)
  web: bump cookie, swagger-client and express in /web (#11966)
  core, web: update translations (#11959)
  core: bump debugpy from 1.8.7 to 1.8.8 (#11961)
  ...
* main:
  providers/ldap: fix global search_full_directory permission not being sufficient (#12028)
  website/docs: 2024.10.2 release notes (#12025)
  lifecycle: fix ak exit status not being passed (#12024)
  core: use versioned_script for path only (#12003)
  core, web: update translations (#12020)
  core: bump google-api-python-client from 2.152.0 to 2.153.0 (#12021)
  providers/oauth2: fix manual device code entry (#12017)
  crypto: validate that generated certificate's name is unique (#12015)
  core, web: update translations (#12006)
  core: bump google-api-python-client from 2.151.0 to 2.152.0 (#12007)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#12011)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#12010)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#12012)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#12013)
  providers/proxy: fix Issuer when AUTHENTIK_HOST_BROWSER is set (#11968)
  website/docs: move S3 ad GeoIP to System Management/Operations (#11998)
  website/integrations: nextcloud: add SSE warning (#11976)
* main:
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#12045)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#12047)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#12044)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#12046)
  web/flows: fix invisible captcha call (#12048)
  rbac: fix incorrect object_description for object-level permissions (#12029)
  stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#12036)
  core: bump coverage from 7.6.4 to 7.6.5 (#12037)
  ci: bump codecov/codecov-action from 4 to 5 (#12038)
  release: 2024.10.2 (#12031)
* main: (28 commits)
  providers/scim: accept string and int for SCIM IDs (#12093)
  website: bump the docusaurus group in /website with 9 updates (#12086)
  core: fix source_flow_manager throwing error when authenticated user attempts to re-authenticate with existing link (#12080)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#12079)
  scripts: remove read_replicas from generated dev config (#12078)
  core: bump geoip2 from 4.8.0 to 4.8.1 (#12071)
  core: bump goauthentik.io/api/v3 from 3.2024100.2 to 3.2024102.2 (#12072)
  core: bump maxmind/geoipupdate from v7.0.1 to v7.1.0 (#12073)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#12074)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#12075)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#12076)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#12077)
  web/admin: auto-prefill user path for new users based on selected path (#12070)
  core: bump aiohttp from 3.10.2 to 3.10.11 (#12069)
  web/admin: fix brand title not respected in application list (#12068)
  core: bump pyjwt from 2.9.0 to 2.10.0 (#12063)
  web: add italian locale (#11958)
  web/admin: better footer links (#12004)
  core, web: update translations (#12052)
  core: bump twilio from 9.3.6 to 9.3.7 (#12061)
  ...
* main: (33 commits)
  ci: mirror repo to internal repo (#12160)
  core: bump goauthentik.io/api/v3 from 3.2024102.2 to 3.2024104.1 (#12149)
  core: bump debugpy from 1.8.8 to 1.8.9 (#12150)
  core: bump webauthn from 2.2.0 to 2.3.0 (#12151)
  core: bump pydantic from 2.10.0 to 2.10.1 (#12152)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#12156)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#12157)
  core: bump sentry-sdk from 2.18.0 to 2.19.0 (#12153)
  web: bump API Client version (#12147)
  root: Backport version change (#12146)
  website/docs: update info about footer links to match new UI (#12120)
  website/docs: prepare release notes (#12142)
  providers/oauth2: fix migration (#12138)
  providers/oauth2: fix migration dependencies (#12123)
  web: bump API Client version (#12129)
  providers/oauth2: fix redirect uri input (#12122)
  providers/proxy: fix redirect_uri (#12121)
  website/docs: prepare release notes (#12119)
  web: bump API Client version (#12118)
  security: fix CVE 2024 52289 (#12113)
  ...
* main:
  ci: only mirror if secret is available (#12181)
  root: fix database ssl options not set correctly (#12180)
  core, web: update translations (#12145)
  core: bump tornado from 6.4.1 to 6.4.2 (#12165)
  website: bump the docusaurus group in /website with 9 updates (#12172)
  website: bump typescript from 5.6.3 to 5.7.2 in /website (#12173)
  ci: bump actions/checkout from 3 to 4 (#12174)
  core: bump github.com/stretchr/testify from 1.9.0 to 1.10.0 (#12175)
  core: bump coverage from 7.6.7 to 7.6.8 (#12176)
  core: bump ruff from 0.7.4 to 0.8.0 (#12177)
* main:
  website/docs: Fix CSP syntax (#12124)
@netlify
Copy link

netlify bot commented Nov 25, 2024

Deploy Preview for authentik-docs canceled.

Name Link
🔨 Latest commit 986c35a
🔍 Latest deploy log https://app.netlify.com/sites/authentik-docs/deploys/6745063990587a00084a0376

@netlify
Copy link

netlify bot commented Nov 25, 2024

Deploy Preview for authentik-storybook canceled.

Name Link
🔨 Latest commit 986c35a
🔍 Latest deploy log https://app.netlify.com/sites/authentik-storybook/deploys/674506392838c90008fb9be2

@kensternberg-authentik kensternberg-authentik marked this pull request as ready for review November 25, 2024 23:24
@codecov
Copy link

codecov bot commented Nov 25, 2024

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
1601 1 1600 1
View the full list of 1 ❄️ flaky tests
tests.e2e.test_provider_proxy_forward.TestProviderProxyForward::test_nginx

Flake rate in main: 36.78% (Passed 55 times, Failed 32 times)

Stack Traces | 223s run time
self = <asgiref.sync.AsyncToSync object at 0x7f9866de3f50>
call_result = <Future at 0x7f9866bab830 state=finished returned NoneType>
exc_info = (<class 'selenium.common.exceptions.NoSuchElementException'>, NoSuchElementException(), <traceback object at 0x7f985c440400>)
task_context = None, context = [<_contextvars.Context object at 0x7f98672f2780>]
args = ('group_outpost_0d07e006-2dcd-48ec-b809-36fe95a11b0c', {'type': 'event.update'})
kwargs = {}, __traceback_hide__ = True
current_task = <Task finished name='Task-26' coro=<AsyncToSync.main_wrap() done, defined at ............/home/runner/.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12......................../site-packages/asgiref/sync.py:299> result=None>
result = None

    async def main_wrap(
        self,
        call_result: "Future[_R]",
        exc_info: "OptExcInfo",
        task_context: "Optional[List[asyncio.Task[Any]]]",
        context: List[contextvars.Context],
        *args: _P.args,
        **kwargs: _P.kwargs,
    ) -> None:
        """
        Wraps the awaitable with something that puts the result into the
        result/exception future.
        """
    
        __traceback_hide__ = True  # noqa: F841
    
        if context is not None:
            _restore_context(context[0])
    
        current_task = asyncio.current_task()
        if current_task is not None and task_context is not None:
            task_context.append(current_task)
    
        try:
            # If we have an exception, run the function inside the except block
            # after raising it so exc_info is correctly populated.
            if exc_info[1]:
                try:
>                   raise exc_info[1]

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12......................../site-packages/asgiref/sync.py:327: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <asgiref.sync.AsyncToSync object at 0x7f985c7694f0>
call_result = <Future at 0x7f985c89b0b0 state=finished returned NoneType>
exc_info = (<class 'selenium.common.exceptions.NoSuchElementException'>, NoSuchElementException(), <traceback object at 0x7f98682bf280>)
task_context = None, context = [<_contextvars.Context object at 0x7f985c109640>]
args = ('group_outpost_0d07e006-2dcd-48ec-b809-36fe95a11b0c', {'type': 'event.update'})
kwargs = {}, __traceback_hide__ = True
current_task = <Task finished name='Task-21' coro=<AsyncToSync.main_wrap() done, defined at ............/home/runner/.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12......................../site-packages/asgiref/sync.py:299> result=None>
result = None

    async def main_wrap(
        self,
        call_result: "Future[_R]",
        exc_info: "OptExcInfo",
        task_context: "Optional[List[asyncio.Task[Any]]]",
        context: List[contextvars.Context],
        *args: _P.args,
        **kwargs: _P.kwargs,
    ) -> None:
        """
        Wraps the awaitable with something that puts the result into the
        result/exception future.
        """
    
        __traceback_hide__ = True  # noqa: F841
    
        if context is not None:
            _restore_context(context[0])
    
        current_task = asyncio.current_task()
        if current_task is not None and task_context is not None:
            task_context.append(current_task)
    
        try:
            # If we have an exception, run the function inside the except block
            # after raising it so exc_info is correctly populated.
            if exc_info[1]:
                try:
>                   raise exc_info[1]

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12......................../site-packages/asgiref/sync.py:327: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
>           return func(self, *args, **kwargs)

tests/e2e/utils.py:287: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>

    @retry()
    def test_nginx(self):
        """Test nginx"""
        self.prepare()
    
        # Start nginx last so all hosts are resolvable, otherwise nginx exits
        self.run_container(
            image="docker.io/library/nginx:1.27",
            ports={
                "80": "80",
            },
            volumes={
                f"{Path(__file__).parent / "proxy_forward_auth" / "nginx_single" / "nginx.conf"}": {
                    "bind": "........./etc/nginx/conf.d/default.conf",
                }
            },
        )
    
        self.driver.get("http:.../localhost/api")
>       self.login()

tests/e2e/test_provider_proxy_forward.py:145: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>

    def login(self):
        """Do entire login flow and check user afterwards"""
>       flow_executor = self.get_shadow_root("ak-flow-executor")

tests/e2e/utils.py:232: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
selector = 'ak-flow-executor'
container = <selenium.webdriver.remote.webdriver.WebDriver (session="22784a9f57a4ecd0fb06fd5cce9a1439")>

    def get_shadow_root(
        self, selector: str, container: WebElement | WebDriver | None = None
    ) -> WebElement:
        """Get shadow root element's inner shadowRoot"""
        if not container:
            container = self.driver
>       shadow_root = container.find_element(By.CSS_SELECTOR, selector)

tests/e2e/utils.py:226: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="22784a9f57a4ecd0fb06fd5cce9a1439")>
by = 'css selector', value = 'ak-flow-executor'

    def find_element(self, by=By.ID, value: Optional[str] = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        :Usage:
            ::
    
                element = driver.find_element(By.ID, 'foo')
    
        :rtype: WebElement
        """
        by, value = self.locator_converter.convert(by, value)
    
        if isinstance(by, RelativeBy):
            elements = self.find_elements(by=by, value=value)
            if not elements:
                raise NoSuchElementException(f"Cannot locate relative element with: {by.root}")
            return elements[0]
    
>       return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"]

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../webdriver/remote/webdriver.py:766: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="22784a9f57a4ecd0fb06fd5cce9a1439")>
driver_command = 'findElement'
params = {'using': 'css selector', 'value': 'ak-flow-executor'}

    def execute(self, driver_command: str, params: dict = None) -> dict:
        """Sends a command to be executed by a command.CommandExecutor.
    
        :Args:
         - driver_command: The name of the command to execute as a string.
         - params: A dictionary of named parameters to send with the command.
    
        :Returns:
          The command's JSON response loaded into a dictionary object.
        """
        params = self._wrap_value(params)
    
        if self.session_id:
            if not params:
                params = {"sessionId": self.session_id}
            elif "sessionId" not in params:
                params["sessionId"] = self.session_id
    
        response = self.command_executor.execute(driver_command, params)
        if response:
>           self.error_handler.check_response(response)

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../webdriver/remote/webdriver.py:380: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f98671af290>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#16 0x55fba6ac0fc3 \\u003Cunknown>\\n#17 0x55fba6ad1944 \\u003Cunknown>\\n#18 0x7f6e7e8ebac3 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: Dict[str, Any]) -> None:
        """Checks that a JSON response from the WebDriver does not have an
        error.
    
        :Args:
         - response - The JSON response from the WebDriver server as a dictionary
           object.
    
        :Raises: If the response contains an error message.
        """
        status = response.get("status", None)
        if not status or status == ErrorCode.SUCCESS:
            return
        value = None
        message = response.get("message", "")
        screen: str = response.get("screen", "")
        stacktrace = None
        if isinstance(status, int):
            value_json = response.get("value", None)
            if value_json and isinstance(value_json, str):
                import json
    
                try:
                    value = json.loads(value_json)
                    if len(value) == 1:
                        value = value["value"]
                    status = value.get("error", None)
                    if not status:
                        status = value.get("status", ErrorCode.UNKNOWN_ERROR)
                        message = value.get("value") or value.get("message")
                        if not isinstance(message, str):
                            value = message
                            message = message.get("message")
                    else:
                        message = value.get("message", None)
                except ValueError:
                    pass
    
        exception_class: Type[WebDriverException]
        e = ErrorCode()
        error_codes = [item for item in dir(e) if not item.startswith("__")]
        for error_code in error_codes:
            error_info = getattr(ErrorCode, error_code)
            if isinstance(error_info, list) and status in error_info:
                exception_class = getattr(ExceptionMapping, error_code, WebDriverException)
                break
        else:
            exception_class = WebDriverException
    
        if not value:
            value = response["value"]
        if isinstance(value, str):
            raise exception_class(value)
        if message == "" and "message" in value:
            message = value["message"]
    
        screen = None  # type: ignore[assignment]
        if "screen" in value:
            screen = value["screen"]
    
        stacktrace = None
        st_value = value.get("stackTrace") or value.get("stacktrace")
        if st_value:
            if isinstance(st_value, str):
                stacktrace = st_value.split("\n")
            else:
                stacktrace = []
                try:
                    for frame in st_value:
                        line = frame.get("lineNumber", "")
                        file = frame.get("fileName", "<anonymous>")
                        if line:
                            file = f"{file}:{line}"
                        meth = frame.get("methodName", "<anonymous>")
                        if "className" in frame:
                            meth = f"{frame['className']}.{meth}"
                        msg = "    at %s (%s)"
                        msg = msg % (meth, file)
                        stacktrace.append(msg)
                except TypeError:
                    pass
        if exception_class == UnexpectedAlertPresentException:
            alert_text = None
            if "data" in value:
                alert_text = value["data"].get("text")
            elif "alert" in value:
                alert_text = value["alert"].get("text")
            raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"ak-flow-executor"}
E         (Session info: chrome=122.0.6261.69); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#no-such-element-exception
E       Stacktrace:
E       #0 0x55fba6ad2793 <unknown>
E       #1 0x55fba67c61c6 <unknown>
E       #2 0x55fba6811358 <unknown>
E       #3 0x55fba6811411 <unknown>
E       #4 0x55fba6854934 <unknown>
E       #5 0x55fba68333fd <unknown>
E       #6 0x55fba6851dd9 <unknown>
E       #7 0x55fba6833173 <unknown>
E       #8 0x55fba68042d3 <unknown>
E       #9 0x55fba6804c9e <unknown>
E       #10 0x55fba6a968cb <unknown>
E       #11 0x55fba6a9a745 <unknown>
E       #12 0x55fba6a832e1 <unknown>
E       #13 0x55fba6a9b2d2 <unknown>
E       #14 0x55fba6a6717f <unknown>
E       #15 0x55fba6ac0dc8 <unknown>
E       #16 0x55fba6ac0fc3 <unknown>
E       #17 0x55fba6ad1944 <unknown>
E       #18 0x7f6e7e8ebac3 <unknown>

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../webdriver/remote/errorhandler.py:229: NoSuchElementException

During handling of the above exception, another exception occurred:

self = <asgiref.sync.AsyncToSync object at 0x7f985c31b0e0>
call_result = <Future at 0x7f985c293ad0 state=finished returned NoneType>
exc_info = (<class 'selenium.common.exceptions.NoSuchElementException'>, NoSuchElementException(), <traceback object at 0x7f985c106480>)
task_context = None, context = [<_contextvars.Context object at 0x7f985c27aa00>]
args = ('group_outpost_3ce280c6-18da-489f-8822-3d36b27f5e45', {'type': 'event.update'})
kwargs = {}, __traceback_hide__ = True
current_task = <Task finished name='Task-36' coro=<AsyncToSync.main_wrap() done, defined at ............/home/runner/.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12......................../site-packages/asgiref/sync.py:299> result=None>
result = None

    async def main_wrap(
        self,
        call_result: "Future[_R]",
        exc_info: "OptExcInfo",
        task_context: "Optional[List[asyncio.Task[Any]]]",
        context: List[contextvars.Context],
        *args: _P.args,
        **kwargs: _P.kwargs,
    ) -> None:
        """
        Wraps the awaitable with something that puts the result into the
        result/exception future.
        """
    
        __traceback_hide__ = True  # noqa: F841
    
        if context is not None:
            _restore_context(context[0])
    
        current_task = asyncio.current_task()
        if current_task is not None and task_context is not None:
            task_context.append(current_task)
    
        try:
            # If we have an exception, run the function inside the except block
            # after raising it so exc_info is correctly populated.
            if exc_info[1]:
                try:
>                   raise exc_info[1]

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12......................../site-packages/asgiref/sync.py:327: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <asgiref.sync.AsyncToSync object at 0x7f985c214890>
call_result = <Future at 0x7f9866e41670 state=finished returned NoneType>
exc_info = (<class 'selenium.common.exceptions.NoSuchElementException'>, NoSuchElementException(), <traceback object at 0x7f985c3a1b40>)
task_context = None, context = [<_contextvars.Context object at 0x7f985c3d2e40>]
args = ('group_outpost_3ce280c6-18da-489f-8822-3d36b27f5e45', {'type': 'event.update'})
kwargs = {}, __traceback_hide__ = True
current_task = <Task finished name='Task-31' coro=<AsyncToSync.main_wrap() done, defined at ............/home/runner/.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12......................../site-packages/asgiref/sync.py:299> result=None>
result = None

    async def main_wrap(
        self,
        call_result: "Future[_R]",
        exc_info: "OptExcInfo",
        task_context: "Optional[List[asyncio.Task[Any]]]",
        context: List[contextvars.Context],
        *args: _P.args,
        **kwargs: _P.kwargs,
    ) -> None:
        """
        Wraps the awaitable with something that puts the result into the
        result/exception future.
        """
    
        __traceback_hide__ = True  # noqa: F841
    
        if context is not None:
            _restore_context(context[0])
    
        current_task = asyncio.current_task()
        if current_task is not None and task_context is not None:
            task_context.append(current_task)
    
        try:
            # If we have an exception, run the function inside the except block
            # after raising it so exc_info is correctly populated.
            if exc_info[1]:
                try:
>                   raise exc_info[1]

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12......................../site-packages/asgiref/sync.py:327: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
>           return func(self, *args, **kwargs)

tests/e2e/utils.py:287: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>

    @retry()
    def test_nginx(self):
        """Test nginx"""
        self.prepare()
    
        # Start nginx last so all hosts are resolvable, otherwise nginx exits
        self.run_container(
            image="docker.io/library/nginx:1.27",
            ports={
                "80": "80",
            },
            volumes={
                f"{Path(__file__).parent / "proxy_forward_auth" / "nginx_single" / "nginx.conf"}": {
                    "bind": "........./etc/nginx/conf.d/default.conf",
                }
            },
        )
    
        self.driver.get("http:.../localhost/api")
>       self.login()

tests/e2e/test_provider_proxy_forward.py:145: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>

    def login(self):
        """Do entire login flow and check user afterwards"""
>       flow_executor = self.get_shadow_root("ak-flow-executor")

tests/e2e/utils.py:232: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
selector = 'ak-flow-executor'
container = <selenium.webdriver.remote.webdriver.WebDriver (session="c64cfd55afe58b3b71bf0a4a0063bf3b")>

    def get_shadow_root(
        self, selector: str, container: WebElement | WebDriver | None = None
    ) -> WebElement:
        """Get shadow root element's inner shadowRoot"""
        if not container:
            container = self.driver
>       shadow_root = container.find_element(By.CSS_SELECTOR, selector)

tests/e2e/utils.py:226: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="c64cfd55afe58b3b71bf0a4a0063bf3b")>
by = 'css selector', value = 'ak-flow-executor'

    def find_element(self, by=By.ID, value: Optional[str] = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        :Usage:
            ::
    
                element = driver.find_element(By.ID, 'foo')
    
        :rtype: WebElement
        """
        by, value = self.locator_converter.convert(by, value)
    
        if isinstance(by, RelativeBy):
            elements = self.find_elements(by=by, value=value)
            if not elements:
                raise NoSuchElementException(f"Cannot locate relative element with: {by.root}")
            return elements[0]
    
>       return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"]

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../webdriver/remote/webdriver.py:766: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="c64cfd55afe58b3b71bf0a4a0063bf3b")>
driver_command = 'findElement'
params = {'using': 'css selector', 'value': 'ak-flow-executor'}

    def execute(self, driver_command: str, params: dict = None) -> dict:
        """Sends a command to be executed by a command.CommandExecutor.
    
        :Args:
         - driver_command: The name of the command to execute as a string.
         - params: A dictionary of named parameters to send with the command.
    
        :Returns:
          The command's JSON response loaded into a dictionary object.
        """
        params = self._wrap_value(params)
    
        if self.session_id:
            if not params:
                params = {"sessionId": self.session_id}
            elif "sessionId" not in params:
                params["sessionId"] = self.session_id
    
        response = self.command_executor.execute(driver_command, params)
        if response:
>           self.error_handler.check_response(response)

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../webdriver/remote/webdriver.py:380: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f985c89b560>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#16 0x5634e15d7fc3 \\u003Cunknown>\\n#17 0x5634e15e8944 \\u003Cunknown>\\n#18 0x7faec676cac3 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: Dict[str, Any]) -> None:
        """Checks that a JSON response from the WebDriver does not have an
        error.
    
        :Args:
         - response - The JSON response from the WebDriver server as a dictionary
           object.
    
        :Raises: If the response contains an error message.
        """
        status = response.get("status", None)
        if not status or status == ErrorCode.SUCCESS:
            return
        value = None
        message = response.get("message", "")
        screen: str = response.get("screen", "")
        stacktrace = None
        if isinstance(status, int):
            value_json = response.get("value", None)
            if value_json and isinstance(value_json, str):
                import json
    
                try:
                    value = json.loads(value_json)
                    if len(value) == 1:
                        value = value["value"]
                    status = value.get("error", None)
                    if not status:
                        status = value.get("status", ErrorCode.UNKNOWN_ERROR)
                        message = value.get("value") or value.get("message")
                        if not isinstance(message, str):
                            value = message
                            message = message.get("message")
                    else:
                        message = value.get("message", None)
                except ValueError:
                    pass
    
        exception_class: Type[WebDriverException]
        e = ErrorCode()
        error_codes = [item for item in dir(e) if not item.startswith("__")]
        for error_code in error_codes:
            error_info = getattr(ErrorCode, error_code)
            if isinstance(error_info, list) and status in error_info:
                exception_class = getattr(ExceptionMapping, error_code, WebDriverException)
                break
        else:
            exception_class = WebDriverException
    
        if not value:
            value = response["value"]
        if isinstance(value, str):
            raise exception_class(value)
        if message == "" and "message" in value:
            message = value["message"]
    
        screen = None  # type: ignore[assignment]
        if "screen" in value:
            screen = value["screen"]
    
        stacktrace = None
        st_value = value.get("stackTrace") or value.get("stacktrace")
        if st_value:
            if isinstance(st_value, str):
                stacktrace = st_value.split("\n")
            else:
                stacktrace = []
                try:
                    for frame in st_value:
                        line = frame.get("lineNumber", "")
                        file = frame.get("fileName", "<anonymous>")
                        if line:
                            file = f"{file}:{line}"
                        meth = frame.get("methodName", "<anonymous>")
                        if "className" in frame:
                            meth = f"{frame['className']}.{meth}"
                        msg = "    at %s (%s)"
                        msg = msg % (meth, file)
                        stacktrace.append(msg)
                except TypeError:
                    pass
        if exception_class == UnexpectedAlertPresentException:
            alert_text = None
            if "data" in value:
                alert_text = value["data"].get("text")
            elif "alert" in value:
                alert_text = value["alert"].get("text")
            raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"ak-flow-executor"}
E         (Session info: chrome=122.0.6261.69); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#no-such-element-exception
E       Stacktrace:
E       #0 0x5634e15e9793 <unknown>
E       #1 0x5634e12dd1c6 <unknown>
E       #2 0x5634e1328358 <unknown>
E       #3 0x5634e1328411 <unknown>
E       #4 0x5634e136b934 <unknown>
E       #5 0x5634e134a3fd <unknown>
E       #6 0x5634e1368dd9 <unknown>
E       #7 0x5634e134a173 <unknown>
E       #8 0x5634e131b2d3 <unknown>
E       #9 0x5634e131bc9e <unknown>
E       #10 0x5634e15ad8cb <unknown>
E       #11 0x5634e15b1745 <unknown>
E       #12 0x5634e159a2e1 <unknown>
E       #13 0x5634e15b22d2 <unknown>
E       #14 0x5634e157e17f <unknown>
E       #15 0x5634e15d7dc8 <unknown>
E       #16 0x5634e15d7fc3 <unknown>
E       #17 0x5634e15e8944 <unknown>
E       #18 0x7faec676cac3 <unknown>

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../webdriver/remote/errorhandler.py:229: NoSuchElementException

During handling of the above exception, another exception occurred:

self = <unittest.case._Outcome object at 0x7f985c878950>
test_case = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.12.7........./x64/lib/python3.12/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
result = <TestCaseFunction test_nginx>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.12.7........./x64/lib/python3.12/unittest/case.py:634: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
method = <bound method TestProviderProxyForward.test_nginx of <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.12.7........./x64/lib/python3.12/unittest/case.py:589: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
            return func(self, *args, **kwargs)
    
        except tuple(exceptions) as exc:
            count += 1
            if count > max_retires:
                logger.debug("Exceeded retry count", exc=exc, test=self)
    
                raise exc
            logger.debug("Retrying on error", exc=exc, test=self)
            self.tearDown()
            self._post_teardown()
            self._pre_setup()
            self.setUp()
>           return wrapper(self, *args, **kwargs)

tests/e2e/utils.py:300: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
            return func(self, *args, **kwargs)
    
        except tuple(exceptions) as exc:
            count += 1
            if count > max_retires:
                logger.debug("Exceeded retry count", exc=exc, test=self)
    
                raise exc
            logger.debug("Retrying on error", exc=exc, test=self)
            self.tearDown()
            self._post_teardown()
            self._pre_setup()
            self.setUp()
>           return wrapper(self, *args, **kwargs)

tests/e2e/utils.py:300: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
            return func(self, *args, **kwargs)
    
        except tuple(exceptions) as exc:
            count += 1
            if count > max_retires:
                logger.debug("Exceeded retry count", exc=exc, test=self)
    
>               raise exc

tests/e2e/utils.py:294: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
>           return func(self, *args, **kwargs)

tests/e2e/utils.py:287: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>

    @retry()
    def test_nginx(self):
        """Test nginx"""
        self.prepare()
    
        # Start nginx last so all hosts are resolvable, otherwise nginx exits
        self.run_container(
            image="docker.io/library/nginx:1.27",
            ports={
                "80": "80",
            },
            volumes={
                f"{Path(__file__).parent / "proxy_forward_auth" / "nginx_single" / "nginx.conf"}": {
                    "bind": "........./etc/nginx/conf.d/default.conf",
                }
            },
        )
    
        self.driver.get("http:.../localhost/api")
>       self.login()

tests/e2e/test_provider_proxy_forward.py:145: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>

    def login(self):
        """Do entire login flow and check user afterwards"""
>       flow_executor = self.get_shadow_root("ak-flow-executor")

tests/e2e/utils.py:232: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_provider_proxy_forward.TestProviderProxyForward testMethod=test_nginx>
selector = 'ak-flow-executor'
container = <selenium.webdriver.remote.webdriver.WebDriver (session="ca2175856d4464412ba76079c110e366")>

    def get_shadow_root(
        self, selector: str, container: WebElement | WebDriver | None = None
    ) -> WebElement:
        """Get shadow root element's inner shadowRoot"""
        if not container:
            container = self.driver
>       shadow_root = container.find_element(By.CSS_SELECTOR, selector)

tests/e2e/utils.py:226: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="ca2175856d4464412ba76079c110e366")>
by = 'css selector', value = 'ak-flow-executor'

    def find_element(self, by=By.ID, value: Optional[str] = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        :Usage:
            ::
    
                element = driver.find_element(By.ID, 'foo')
    
        :rtype: WebElement
        """
        by, value = self.locator_converter.convert(by, value)
    
        if isinstance(by, RelativeBy):
            elements = self.find_elements(by=by, value=value)
            if not elements:
                raise NoSuchElementException(f"Cannot locate relative element with: {by.root}")
            return elements[0]
    
>       return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"]

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../webdriver/remote/webdriver.py:766: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="ca2175856d4464412ba76079c110e366")>
driver_command = 'findElement'
params = {'using': 'css selector', 'value': 'ak-flow-executor'}

    def execute(self, driver_command: str, params: dict = None) -> dict:
        """Sends a command to be executed by a command.CommandExecutor.
    
        :Args:
         - driver_command: The name of the command to execute as a string.
         - params: A dictionary of named parameters to send with the command.
    
        :Returns:
          The command's JSON response loaded into a dictionary object.
        """
        params = self._wrap_value(params)
    
        if self.session_id:
            if not params:
                params = {"sessionId": self.session_id}
            elif "sessionId" not in params:
                params["sessionId"] = self.session_id
    
        response = self.command_executor.execute(driver_command, params)
        if response:
>           self.error_handler.check_response(response)

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../webdriver/remote/webdriver.py:380: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f985c88bad0>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#16 0x562085ab4fc3 \\u003Cunknown>\\n#17 0x562085ac5944 \\u003Cunknown>\\n#18 0x7f2e75c1cac3 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: Dict[str, Any]) -> None:
        """Checks that a JSON response from the WebDriver does not have an
        error.
    
        :Args:
         - response - The JSON response from the WebDriver server as a dictionary
           object.
    
        :Raises: If the response contains an error message.
        """
        status = response.get("status", None)
        if not status or status == ErrorCode.SUCCESS:
            return
        value = None
        message = response.get("message", "")
        screen: str = response.get("screen", "")
        stacktrace = None
        if isinstance(status, int):
            value_json = response.get("value", None)
            if value_json and isinstance(value_json, str):
                import json
    
                try:
                    value = json.loads(value_json)
                    if len(value) == 1:
                        value = value["value"]
                    status = value.get("error", None)
                    if not status:
                        status = value.get("status", ErrorCode.UNKNOWN_ERROR)
                        message = value.get("value") or value.get("message")
                        if not isinstance(message, str):
                            value = message
                            message = message.get("message")
                    else:
                        message = value.get("message", None)
                except ValueError:
                    pass
    
        exception_class: Type[WebDriverException]
        e = ErrorCode()
        error_codes = [item for item in dir(e) if not item.startswith("__")]
        for error_code in error_codes:
            error_info = getattr(ErrorCode, error_code)
            if isinstance(error_info, list) and status in error_info:
                exception_class = getattr(ExceptionMapping, error_code, WebDriverException)
                break
        else:
            exception_class = WebDriverException
    
        if not value:
            value = response["value"]
        if isinstance(value, str):
            raise exception_class(value)
        if message == "" and "message" in value:
            message = value["message"]
    
        screen = None  # type: ignore[assignment]
        if "screen" in value:
            screen = value["screen"]
    
        stacktrace = None
        st_value = value.get("stackTrace") or value.get("stacktrace")
        if st_value:
            if isinstance(st_value, str):
                stacktrace = st_value.split("\n")
            else:
                stacktrace = []
                try:
                    for frame in st_value:
                        line = frame.get("lineNumber", "")
                        file = frame.get("fileName", "<anonymous>")
                        if line:
                            file = f"{file}:{line}"
                        meth = frame.get("methodName", "<anonymous>")
                        if "className" in frame:
                            meth = f"{frame['className']}.{meth}"
                        msg = "    at %s (%s)"
                        msg = msg % (meth, file)
                        stacktrace.append(msg)
                except TypeError:
                    pass
        if exception_class == UnexpectedAlertPresentException:
            alert_text = None
            if "data" in value:
                alert_text = value["data"].get("text")
            elif "alert" in value:
                alert_text = value["alert"].get("text")
            raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"ak-flow-executor"}
E         (Session info: chrome=122.0.6261.69); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#no-such-element-exception
E       Stacktrace:
E       #0 0x562085ac6793 <unknown>
E       #1 0x5620857ba1c6 <unknown>
E       #2 0x562085805358 <unknown>
E       #3 0x562085805411 <unknown>
E       #4 0x562085848934 <unknown>
E       #5 0x5620858273fd <unknown>
E       #6 0x562085845dd9 <unknown>
E       #7 0x562085827173 <unknown>
E       #8 0x5620857f82d3 <unknown>
E       #9 0x5620857f8c9e <unknown>
E       #10 0x562085a8a8cb <unknown>
E       #11 0x562085a8e745 <unknown>
E       #12 0x562085a772e1 <unknown>
E       #13 0x562085a8f2d2 <unknown>
E       #14 0x562085a5b17f <unknown>
E       #15 0x562085ab4dc8 <unknown>
E       #16 0x562085ab4fc3 <unknown>
E       #17 0x562085ac5944 <unknown>
E       #18 0x7f2e75c1cac3 <unknown>

../../../.cache............/pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../webdriver/remote/errorhandler.py:229: NoSuchElementException

To view more test analytics, go to the Test Analytics Dashboard
📢 Thoughts on this report? Let us know!

@BeryJu BeryJu merged commit ee15dbf into main Nov 26, 2024
@BeryJu BeryJu deleted the root/fix-contribution-link branch November 26, 2024 13:11
kensternberg-authentik added a commit that referenced this pull request Nov 26, 2024
* main:
  website/docs: Add note about single group per role (#12169)
  website/docs: Fix documentation about attribute merging for indirect membership (#12168)
  root: support running authentik in subpath (#8675)
  docs: fix contribution link (#12189)
  core, web: update translations (#12190)
  core: Bump msgraph-sdk from 1.12.0 to 1.13.0 (#12191)
  core: Bump selenium from 4.26.1 to 4.27.0 (#12192)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants