Skip to content

web: initial CSP - #18070

Draft
BeryJu wants to merge 3 commits into
mainfrom
web/csp
Draft

web: initial CSP#18070
BeryJu wants to merge 3 commits into
mainfrom
web/csp

Conversation

@BeryJu

@BeryJu BeryJu commented Nov 11, 2025

Copy link
Copy Markdown
Member

more CSP friendly by adding JS/CSS nonces

ref #17863

@netlify

netlify Bot commented Nov 11, 2025

Copy link
Copy Markdown

Deploy Preview for authentik-integrations ready!

Name Link
🔨 Latest commit 64e7fa6
🔍 Latest deploy log https://app.netlify.com/projects/authentik-integrations/deploys/69f0e84749dca000089873e9
😎 Deploy Preview https://deploy-preview-18070--authentik-integrations.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Nov 11, 2025

Copy link
Copy Markdown

Deploy Preview for authentik-docs ready!

Name Link
🔨 Latest commit 64e7fa6
🔍 Latest deploy log https://app.netlify.com/projects/authentik-docs/deploys/69f0e84758c1ad00089363be
😎 Deploy Preview https://deploy-preview-18070--authentik-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Nov 11, 2025

Copy link
Copy Markdown

Deploy Preview for authentik-storybook ready!

Name Link
🔨 Latest commit 64e7fa6
🔍 Latest deploy log https://app.netlify.com/projects/authentik-storybook/deploys/69f0e8474913a600081001fd
😎 Deploy Preview https://deploy-preview-18070--authentik-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov

codecov Bot commented Nov 11, 2025

Copy link
Copy Markdown

❌ 4 Tests Failed:

Tests completed Failed Passed Skipped
3194 4 3190 1
View the top 3 failed test(s) by shortest run time
tests.e2e.test_flows_login.TestFlowsLogin::test_login_compatibility_mode
Stack Traces | 17.1s run time
self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    def test_login_compatibility_mode(self):
        """test default login flow with compatibility mode enabled"""
        Flow.objects.filter(slug="default-authentication-flow").update(compatibility_mode=True)
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
            )
        )
>       self.login(shadow_dom=False)

tests/e2e/test_flows_login.py:49: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
shadow_dom = False, skip_stages = []

    def login(self, shadow_dom=True, skip_stages: list[str] | None = None):
        """Perform the entire authentik login flow."""
        skip_stages = skip_stages or []
    
        if "ak-stage-identification" not in skip_stages:
            if shadow_dom:
                flow_executor = self.get_shadow_root("ak-flow-executor")
                identification_stage = self.get_shadow_root(
                    "ak-stage-identification", flow_executor
                )
            else:
                flow_executor = self.shady_dom()
                identification_stage = self.shady_dom()
    
            wait = WebDriverWait(identification_stage, self.wait_timeout)
>           wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "input[name=uidField]")))

tests/selenium.py:311: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[AttributeError("'wrapper' object has no attribute 'session_id'") raised in repr()] WebDriverWait object at 0x7f74d85f7050>
method = <function presence_of_element_located.<locals>._predicate at 0x7f74d18f6400>
message = ''

    def until(self, method: Callable[[D], Literal[False] | T], message: str = "") -> T:
        """Wait until the method returns a value that is not False.
    
        Calls the method provided with the driver as an argument until the
        return value does not evaluate to ``False``.
    
        Args:
            method: A callable object that takes a WebDriver instance as an
                argument.
            message: Optional message for TimeoutException.
    
        Returns:
            The result of the last call to `method`.
    
        Raises:
            TimeoutException: If 'method' does not return a truthy value within
                the WebDriverWait object's timeout.
    
        Example:
            >>> from selenium.webdriver.common.by import By
            >>> from selenium.webdriver.support.ui import WebDriverWait
            >>> from selenium.webdriver.support import expected_conditions as EC
            >>>
            >>> # Wait until an element is visible on the page
            >>> wait = WebDriverWait(driver, 10)
            >>> element = wait.until(EC.visibility_of_element_located((By.ID, "exampleId")))
            >>> print(element.text)
        """
        screen = None
        stacktrace = None
    
        end_time = time.monotonic() + self._timeout
        while True:
            try:
>               value = method(self._driver)
                        ^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/support/wait.py:112: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <tests.selenium.SeleniumTestMixin.shady_dom.<locals>.wrapper object at 0x7f74da4bd400>

    def _predicate(driver: WebDriverOrWebElement):
>       return driver.find_element(*locator)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/support/expected_conditions.py:92: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.selenium.SeleniumTestMixin.shady_dom.<locals>.wrapper object at 0x7f74da4bd400>
by = 'css selector', selector = 'input[name=uidField]'

    def find_element(self, by: str, selector: str) -> WebElement:
>       return self.container.execute_script(
            "return document.__shady_native_querySelector(arguments[0])", selector
        )

tests/selenium.py:290: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="bbd870d8e7d59db2f486604e2df914f2")>
script = 'return document.__shady_native_querySelector(arguments[0])'
args = ('input[name=uidField]',), converted_args = ['input[name=uidField]']
command = 'w3cExecuteScript'

    def execute_script(self, script: str, *args) -> Any:
        """Synchronously Executes JavaScript in the current window/frame.
    
        Args:
            script: The javascript to execute.
            *args: Any applicable arguments for your JavaScript.
    
        Example:
            ```
            id = "username"
            value = "test_user"
            driver.execute_script("document.getElementById(arguments[0]).value = arguments[1];", id, value)
            ```
        """
        if isinstance(script, ScriptKey):
            try:
                script = self.pinned_scripts[script.id]
            except KeyError:
                raise JavascriptException("Pinned script could not be found")
    
        converted_args = list(args)
        command = Command.W3C_EXECUTE_SCRIPT
    
>       return self.execute(command, {"script": script, "args": converted_args})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webdriver.py:536: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="bbd870d8e7d59db2f486604e2df914f2")>
driver_command = 'w3cExecuteScript'
params = {'args': ['input[name=uidField]'], 'script': 'return document.__shady_native_querySelector(arguments[0])'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d1f03020>
response = {'status': 500, 'value': '{"value":{"error":"javascript error","message":"javascript error: document.__shady_native_qu...\\n#18 0x556d552f9d6d \\u003Cunknown>\\n#19 0x556d5530b903 \\u003Cunknown>\\n#20 0x7f3f0b1b2469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.JavascriptException: Message: javascript error: document.__shady_native_querySelector is not a function
E         (Session info: chrome=145.0.7632.109)
E       Stacktrace:
E       #0 0x556d5530d302 <unknown>
E       #1 0x556d54ce20c6 <unknown>
E       #2 0x556d54ce9684 <unknown>
E       #3 0x556d54cebf4c <unknown>
E       #4 0x556d54d7cc06 <unknown>
E       #5 0x556d54d59836 <unknown>
E       #6 0x556d54d7bd7d <unknown>
E       #7 0x556d54d595d7 <unknown>
E       #8 0x556d54d268b2 <unknown>
E       #9 0x556d54d27725 <unknown>
E       #10 0x556d552d0d44 <unknown>
E       #11 0x556d552d4086 <unknown>
E       #12 0x556d552d3b3e <unknown>
E       #13 0x556d552d44f9 <unknown>
E       #14 0x556d552c06fa <unknown>
E       #15 0x556d552d487a <unknown>
E       #16 0x556d552a8e49 <unknown>
E       #17 0x556d552f9b79 <unknown>
E       #18 0x556d552f9d6d <unknown>
E       #19 0x556d5530b903 <unknown>
E       #20 0x7f3f0b1b2469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: JavascriptException

During handling of the above exception, another exception occurred:

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    def test_login_compatibility_mode(self):
        """test default login flow with compatibility mode enabled"""
        Flow.objects.filter(slug="default-authentication-flow").update(compatibility_mode=True)
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
            )
        )
>       self.login(shadow_dom=False)

tests/e2e/test_flows_login.py:49: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
shadow_dom = False, skip_stages = []

    def login(self, shadow_dom=True, skip_stages: list[str] | None = None):
        """Perform the entire authentik login flow."""
        skip_stages = skip_stages or []
    
        if "ak-stage-identification" not in skip_stages:
            if shadow_dom:
                flow_executor = self.get_shadow_root("ak-flow-executor")
                identification_stage = self.get_shadow_root(
                    "ak-stage-identification", flow_executor
                )
            else:
                flow_executor = self.shady_dom()
                identification_stage = self.shady_dom()
    
            wait = WebDriverWait(identification_stage, self.wait_timeout)
>           wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "input[name=uidField]")))

tests/selenium.py:311: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[AttributeError("'wrapper' object has no attribute 'session_id'") raised in repr()] WebDriverWait object at 0x7f74d91fd650>
method = <function presence_of_element_located.<locals>._predicate at 0x7f74d27a7c10>
message = ''

    def until(self, method: Callable[[D], Literal[False] | T], message: str = "") -> T:
        """Wait until the method returns a value that is not False.
    
        Calls the method provided with the driver as an argument until the
        return value does not evaluate to ``False``.
    
        Args:
            method: A callable object that takes a WebDriver instance as an
                argument.
            message: Optional message for TimeoutException.
    
        Returns:
            The result of the last call to `method`.
    
        Raises:
            TimeoutException: If 'method' does not return a truthy value within
                the WebDriverWait object's timeout.
    
        Example:
            >>> from selenium.webdriver.common.by import By
            >>> from selenium.webdriver.support.ui import WebDriverWait
            >>> from selenium.webdriver.support import expected_conditions as EC
            >>>
            >>> # Wait until an element is visible on the page
            >>> wait = WebDriverWait(driver, 10)
            >>> element = wait.until(EC.visibility_of_element_located((By.ID, "exampleId")))
            >>> print(element.text)
        """
        screen = None
        stacktrace = None
    
        end_time = time.monotonic() + self._timeout
        while True:
            try:
>               value = method(self._driver)
                        ^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/support/wait.py:112: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <tests.selenium.SeleniumTestMixin.shady_dom.<locals>.wrapper object at 0x7f74d9eddd30>

    def _predicate(driver: WebDriverOrWebElement):
>       return driver.find_element(*locator)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/support/expected_conditions.py:92: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.selenium.SeleniumTestMixin.shady_dom.<locals>.wrapper object at 0x7f74d9eddd30>
by = 'css selector', selector = 'input[name=uidField]'

    def find_element(self, by: str, selector: str) -> WebElement:
>       return self.container.execute_script(
            "return document.__shady_native_querySelector(arguments[0])", selector
        )

tests/selenium.py:290: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="6289a11a3456d4e18270b6af82437c2d")>
script = 'return document.__shady_native_querySelector(arguments[0])'
args = ('input[name=uidField]',), converted_args = ['input[name=uidField]']
command = 'w3cExecuteScript'

    def execute_script(self, script: str, *args) -> Any:
        """Synchronously Executes JavaScript in the current window/frame.
    
        Args:
            script: The javascript to execute.
            *args: Any applicable arguments for your JavaScript.
    
        Example:
            ```
            id = "username"
            value = "test_user"
            driver.execute_script("document.getElementById(arguments[0]).value = arguments[1];", id, value)
            ```
        """
        if isinstance(script, ScriptKey):
            try:
                script = self.pinned_scripts[script.id]
            except KeyError:
                raise JavascriptException("Pinned script could not be found")
    
        converted_args = list(args)
        command = Command.W3C_EXECUTE_SCRIPT
    
>       return self.execute(command, {"script": script, "args": converted_args})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webdriver.py:536: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="6289a11a3456d4e18270b6af82437c2d")>
driver_command = 'w3cExecuteScript'
params = {'args': ['input[name=uidField]'], 'script': 'return document.__shady_native_querySelector(arguments[0])'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d3a04550>
response = {'status': 500, 'value': '{"value":{"error":"javascript error","message":"javascript error: document.__shady_native_qu...\\n#18 0x55d0b5189d6d \\u003Cunknown>\\n#19 0x55d0b519b903 \\u003Cunknown>\\n#20 0x7fb7029df469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.JavascriptException: Message: javascript error: document.__shady_native_querySelector is not a function
E         (Session info: chrome=145.0.7632.109)
E       Stacktrace:
E       #0 0x55d0b519d302 <unknown>
E       #1 0x55d0b4b720c6 <unknown>
E       #2 0x55d0b4b79684 <unknown>
E       #3 0x55d0b4b7bf4c <unknown>
E       #4 0x55d0b4c0cc06 <unknown>
E       #5 0x55d0b4be9836 <unknown>
E       #6 0x55d0b4c0bd7d <unknown>
E       #7 0x55d0b4be95d7 <unknown>
E       #8 0x55d0b4bb68b2 <unknown>
E       #9 0x55d0b4bb7725 <unknown>
E       #10 0x55d0b5160d44 <unknown>
E       #11 0x55d0b5164086 <unknown>
E       #12 0x55d0b5163b3e <unknown>
E       #13 0x55d0b51644f9 <unknown>
E       #14 0x55d0b51506fa <unknown>
E       #15 0x55d0b516487a <unknown>
E       #16 0x55d0b5138e49 <unknown>
E       #17 0x55d0b5189b79 <unknown>
E       #18 0x55d0b5189d6d <unknown>
E       #19 0x55d0b519b903 <unknown>
E       #20 0x7fb7029df469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: JavascriptException

During handling of the above exception, another exception occurred:

self = <unittest.case._Outcome object at 0x7f74d8455940>
test_case = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
subTest = False

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

.../hostedtoolcache/Python/3.14.4........./x64/lib/python3.14/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
result = <TestCaseFunction test_login_compatibility_mode>

    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.14.4........./x64/lib/python3.14/unittest/case.py:669: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
method = <bound method TestFlowsLogin.test_login_compatibility_mode of <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>>

    def _callTestMethod(self, method):
>       result = method()
                 ^^^^^^^^

.../hostedtoolcache/Python/3.14.4........./x64/lib/python3.14/unittest/case.py:615: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
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/decorators.py:73: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
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/decorators.py:73: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
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/decorators.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    def test_login_compatibility_mode(self):
        """test default login flow with compatibility mode enabled"""
        Flow.objects.filter(slug="default-authentication-flow").update(compatibility_mode=True)
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
            )
        )
>       self.login(shadow_dom=False)

tests/e2e/test_flows_login.py:49: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login.TestFlowsLogin testMethod=test_login_compatibility_mode>
shadow_dom = False, skip_stages = []

    def login(self, shadow_dom=True, skip_stages: list[str] | None = None):
        """Perform the entire authentik login flow."""
        skip_stages = skip_stages or []
    
        if "ak-stage-identification" not in skip_stages:
            if shadow_dom:
                flow_executor = self.get_shadow_root("ak-flow-executor")
                identification_stage = self.get_shadow_root(
                    "ak-stage-identification", flow_executor
                )
            else:
                flow_executor = self.shady_dom()
                identification_stage = self.shady_dom()
    
            wait = WebDriverWait(identification_stage, self.wait_timeout)
>           wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "input[name=uidField]")))

tests/selenium.py:311: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[AttributeError("'wrapper' object has no attribute 'session_id'") raised in repr()] WebDriverWait object at 0x7f74d9a44370>
method = <function presence_of_element_located.<locals>._predicate at 0x7f74da6afb60>
message = ''

    def until(self, method: Callable[[D], Literal[False] | T], message: str = "") -> T:
        """Wait until the method returns a value that is not False.
    
        Calls the method provided with the driver as an argument until the
        return value does not evaluate to ``False``.
    
        Args:
            method: A callable object that takes a WebDriver instance as an
                argument.
            message: Optional message for TimeoutException.
    
        Returns:
            The result of the last call to `method`.
    
        Raises:
            TimeoutException: If 'method' does not return a truthy value within
                the WebDriverWait object's timeout.
    
        Example:
            >>> from selenium.webdriver.common.by import By
            >>> from selenium.webdriver.support.ui import WebDriverWait
            >>> from selenium.webdriver.support import expected_conditions as EC
            >>>
            >>> # Wait until an element is visible on the page
            >>> wait = WebDriverWait(driver, 10)
            >>> element = wait.until(EC.visibility_of_element_located((By.ID, "exampleId")))
            >>> print(element.text)
        """
        screen = None
        stacktrace = None
    
        end_time = time.monotonic() + self._timeout
        while True:
            try:
>               value = method(self._driver)
                        ^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/support/wait.py:112: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <tests.selenium.SeleniumTestMixin.shady_dom.<locals>.wrapper object at 0x7f74d8998980>

    def _predicate(driver: WebDriverOrWebElement):
>       return driver.find_element(*locator)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/support/expected_conditions.py:92: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.selenium.SeleniumTestMixin.shady_dom.<locals>.wrapper object at 0x7f74d8998980>
by = 'css selector', selector = 'input[name=uidField]'

    def find_element(self, by: str, selector: str) -> WebElement:
>       return self.container.execute_script(
            "return document.__shady_native_querySelector(arguments[0])", selector
        )

tests/selenium.py:290: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="4fcb8818db39e4a28a484fe6c6fb7abf")>
script = 'return document.__shady_native_querySelector(arguments[0])'
args = ('input[name=uidField]',), converted_args = ['input[name=uidField]']
command = 'w3cExecuteScript'

    def execute_script(self, script: str, *args) -> Any:
        """Synchronously Executes JavaScript in the current window/frame.
    
        Args:
            script: The javascript to execute.
            *args: Any applicable arguments for your JavaScript.
    
        Example:
            ```
            id = "username"
            value = "test_user"
            driver.execute_script("document.getElementById(arguments[0]).value = arguments[1];", id, value)
            ```
        """
        if isinstance(script, ScriptKey):
            try:
                script = self.pinned_scripts[script.id]
            except KeyError:
                raise JavascriptException("Pinned script could not be found")
    
        converted_args = list(args)
        command = Command.W3C_EXECUTE_SCRIPT
    
>       return self.execute(command, {"script": script, "args": converted_args})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webdriver.py:536: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="4fcb8818db39e4a28a484fe6c6fb7abf")>
driver_command = 'w3cExecuteScript'
params = {'args': ['input[name=uidField]'], 'script': 'return document.__shady_native_querySelector(arguments[0])'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d30e3350>
response = {'status': 500, 'value': '{"value":{"error":"javascript error","message":"javascript error: document.__shady_native_qu...\\n#18 0x55f8a3269d6d \\u003Cunknown>\\n#19 0x55f8a327b903 \\u003Cunknown>\\n#20 0x7f97ef4e3469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.JavascriptException: Message: javascript error: document.__shady_native_querySelector is not a function
E         (Session info: chrome=145.0.7632.109)
E       Stacktrace:
E       #0 0x55f8a327d302 <unknown>
E       #1 0x55f8a2c520c6 <unknown>
E       #2 0x55f8a2c59684 <unknown>
E       #3 0x55f8a2c5bf4c <unknown>
E       #4 0x55f8a2cecc06 <unknown>
E       #5 0x55f8a2cc9836 <unknown>
E       #6 0x55f8a2cebd7d <unknown>
E       #7 0x55f8a2cc95d7 <unknown>
E       #8 0x55f8a2c968b2 <unknown>
E       #9 0x55f8a2c97725 <unknown>
E       #10 0x55f8a3240d44 <unknown>
E       #11 0x55f8a3244086 <unknown>
E       #12 0x55f8a3243b3e <unknown>
E       #13 0x55f8a32444f9 <unknown>
E       #14 0x55f8a32306fa <unknown>
E       #15 0x55f8a324487a <unknown>
E       #16 0x55f8a3218e49 <unknown>
E       #17 0x55f8a3269b79 <unknown>
E       #18 0x55f8a3269d6d <unknown>
E       #19 0x55f8a327b903 <unknown>
E       #20 0x7f97ef4e3469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: JavascriptException
tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE::test_login_mfa_static_deny
Stack Traces | 106s run time
self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    def test_login_mfa_static_deny(self):
        """test default login flow"""
        mfa = AuthenticatorValidateStage.objects.get(
            name="default-authentication-mfa-validation",
        )
        mfa.not_configured_action = NotConfiguredAction.DENY
        mfa.device_classes = [DeviceClasses.STATIC]
        mfa.save()
    
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
                query={"sfe": True},
            )
        )
>       login_sfe(self.driver, self.user)

tests/e2e/test_flows_login_sfe.py:78: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <selenium.webdriver.remote.webdriver.WebDriver (session="ca5fd1c789eb0a6b751b257e315c1b0b")>
user = <User: rOH4XiGanpiC4Fdr1UiL>

    def login_sfe(driver: WebDriver, user: User):
        """Do entire login flow adjusted for SFE"""
        flow_executor = driver.find_element(By.ID, "flow-sfe-container")
>       identification_stage = flow_executor.find_element(By.ID, "ident-form")
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/e2e/test_flows_login_sfe.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="ca5fd1c789eb0a6b751b257e315c1b0b", element="f.96FB8E8FF2DDB230E1E5135971068CC8.d.C7A263B7030A7967C913EF9F167DA39A.e.2")>
by = 'css selector', value = '[id="ident-form"]'

    def find_element(self, by: str = By.ID, value: str | None = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        Args:
            by: The locating strategy to use. Default is `By.ID`. Supported values include:
                - By.ID: Locate by element ID.
                - By.NAME: Locate by the `name` attribute.
                - By.XPATH: Locate by an XPath expression.
                - By.CSS_SELECTOR: Locate by a CSS selector.
                - By.CLASS_NAME: Locate by the `class` attribute.
                - By.TAG_NAME: Locate by the tag name (e.g., "input", "button").
                - By.LINK_TEXT: Locate a link element by its exact text.
                - By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.
            value: The locator value to use with the specified `by` strategy.
    
        Returns:
            The first matching `WebElement` found on the page.
    
        Example:
            element = driver.find_element(By.ID, "foo")
        """
        by, value = self._parent.locator_converter.convert(by, value)
>       return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:532: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="ca5fd1c789eb0a6b751b257e315c1b0b", element="f.96FB8E8FF2DDB230E1E5135971068CC8.d.C7A263B7030A7967C913EF9F167DA39A.e.2")>
command = 'findChildElement'
params = {'id': 'f.96FB8E8FF2DDB230E1E5135971068CC8.d.C7A263B7030A7967C913EF9F167DA39A.e.2', 'using': 'css selector', 'value': '[id="ident-form"]'}

    def _execute(self, command, params=None):
        """Executes a command against the underlying HTML element.
    
        Args:
            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.
        """
        if not params:
            params = {}
        params["id"] = self._id
>       return self._parent.execute(command, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="ca5fd1c789eb0a6b751b257e315c1b0b")>
driver_command = 'findChildElement'
params = {'using': 'css selector', 'value': '[id="ident-form"]'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d8c155b0>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#20 0x5582cb6c0d6d \\u003Cunknown>\\n#21 0x5582cb6d2903 \\u003Cunknown>\\n#22 0x7f1117b11469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="ident-form"]"}
E         (Session info: chrome=145.0.7632.109); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#nosuchelementexception
E       Stacktrace:
E       #0 0x5582cb6d4302 <unknown>
E       #1 0x5582cb0a90c6 <unknown>
E       #2 0x5582cb0fb25c <unknown>
E       #3 0x5582cb0fb475 <unknown>
E       #4 0x5582cb0ef5da <unknown>
E       #5 0x5582cb120861 <unknown>
E       #6 0x5582cb0ef4e2 <unknown>
E       #7 0x5582cb120ba2 <unknown>
E       #8 0x5582cb142d7d <unknown>
E       #9 0x5582cb1205d7 <unknown>
E       #10 0x5582cb0ed8b2 <unknown>
E       #11 0x5582cb0ee725 <unknown>
E       #12 0x5582cb697d44 <unknown>
E       #13 0x5582cb69b086 <unknown>
E       #14 0x5582cb69ab3e <unknown>
E       #15 0x5582cb69b4f9 <unknown>
E       #16 0x5582cb6876fa <unknown>
E       #17 0x5582cb69b87a <unknown>
E       #18 0x5582cb66fe49 <unknown>
E       #19 0x5582cb6c0b79 <unknown>
E       #20 0x5582cb6c0d6d <unknown>
E       #21 0x5582cb6d2903 <unknown>
E       #22 0x7f1117b11469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: NoSuchElementException

During handling of the above exception, another exception occurred:

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    def test_login_mfa_static_deny(self):
        """test default login flow"""
        mfa = AuthenticatorValidateStage.objects.get(
            name="default-authentication-mfa-validation",
        )
        mfa.not_configured_action = NotConfiguredAction.DENY
        mfa.device_classes = [DeviceClasses.STATIC]
        mfa.save()
    
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
                query={"sfe": True},
            )
        )
>       login_sfe(self.driver, self.user)

tests/e2e/test_flows_login_sfe.py:78: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <selenium.webdriver.remote.webdriver.WebDriver (session="24f16df655131351fcaff56854a7254e")>
user = <User: fXjv3s50LbIafNqiXUzF>

    def login_sfe(driver: WebDriver, user: User):
        """Do entire login flow adjusted for SFE"""
        flow_executor = driver.find_element(By.ID, "flow-sfe-container")
>       identification_stage = flow_executor.find_element(By.ID, "ident-form")
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/e2e/test_flows_login_sfe.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="24f16df655131351fcaff56854a7254e", element="f.8F7FA0166C73A5FE76249ABE96FE7390.d.56CB8AF252071CE906AB0B2D340B2627.e.2")>
by = 'css selector', value = '[id="ident-form"]'

    def find_element(self, by: str = By.ID, value: str | None = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        Args:
            by: The locating strategy to use. Default is `By.ID`. Supported values include:
                - By.ID: Locate by element ID.
                - By.NAME: Locate by the `name` attribute.
                - By.XPATH: Locate by an XPath expression.
                - By.CSS_SELECTOR: Locate by a CSS selector.
                - By.CLASS_NAME: Locate by the `class` attribute.
                - By.TAG_NAME: Locate by the tag name (e.g., "input", "button").
                - By.LINK_TEXT: Locate a link element by its exact text.
                - By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.
            value: The locator value to use with the specified `by` strategy.
    
        Returns:
            The first matching `WebElement` found on the page.
    
        Example:
            element = driver.find_element(By.ID, "foo")
        """
        by, value = self._parent.locator_converter.convert(by, value)
>       return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:532: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="24f16df655131351fcaff56854a7254e", element="f.8F7FA0166C73A5FE76249ABE96FE7390.d.56CB8AF252071CE906AB0B2D340B2627.e.2")>
command = 'findChildElement'
params = {'id': 'f.8F7FA0166C73A5FE76249ABE96FE7390.d.56CB8AF252071CE906AB0B2D340B2627.e.2', 'using': 'css selector', 'value': '[id="ident-form"]'}

    def _execute(self, command, params=None):
        """Executes a command against the underlying HTML element.
    
        Args:
            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.
        """
        if not params:
            params = {}
        params["id"] = self._id
>       return self._parent.execute(command, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="24f16df655131351fcaff56854a7254e")>
driver_command = 'findChildElement'
params = {'using': 'css selector', 'value': '[id="ident-form"]'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d8c15a70>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#20 0x5565b7d63d6d \\u003Cunknown>\\n#21 0x5565b7d75903 \\u003Cunknown>\\n#22 0x7fdaa1fc0469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="ident-form"]"}
E         (Session info: chrome=145.0.7632.109); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#nosuchelementexception
E       Stacktrace:
E       #0 0x5565b7d77302 <unknown>
E       #1 0x5565b774c0c6 <unknown>
E       #2 0x5565b779e25c <unknown>
E       #3 0x5565b779e475 <unknown>
E       #4 0x5565b77925da <unknown>
E       #5 0x5565b77c3861 <unknown>
E       #6 0x5565b77924e2 <unknown>
E       #7 0x5565b77c3ba2 <unknown>
E       #8 0x5565b77e5d7d <unknown>
E       #9 0x5565b77c35d7 <unknown>
E       #10 0x5565b77908b2 <unknown>
E       #11 0x5565b7791725 <unknown>
E       #12 0x5565b7d3ad44 <unknown>
E       #13 0x5565b7d3e086 <unknown>
E       #14 0x5565b7d3db3e <unknown>
E       #15 0x5565b7d3e4f9 <unknown>
E       #16 0x5565b7d2a6fa <unknown>
E       #17 0x5565b7d3e87a <unknown>
E       #18 0x5565b7d12e49 <unknown>
E       #19 0x5565b7d63b79 <unknown>
E       #20 0x5565b7d63d6d <unknown>
E       #21 0x5565b7d75903 <unknown>
E       #22 0x7fdaa1fc0469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: NoSuchElementException

During handling of the above exception, another exception occurred:

self = <unittest.case._Outcome object at 0x7f74db92f390>
test_case = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>
subTest = False

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

.../hostedtoolcache/Python/3.14.4........./x64/lib/python3.14/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>
result = <TestCaseFunction test_login_mfa_static_deny>

    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.14.4........./x64/lib/python3.14/unittest/case.py:669: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>
method = <bound method TestFlowsLoginSFE.test_login_mfa_static_deny of <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>>

    def _callTestMethod(self, method):
>       result = method()
                 ^^^^^^^^

.../hostedtoolcache/Python/3.14.4........./x64/lib/python3.14/unittest/case.py:615: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>
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/decorators.py:73: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>
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/decorators.py:73: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>
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/decorators.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login_mfa_static_deny>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    def test_login_mfa_static_deny(self):
        """test default login flow"""
        mfa = AuthenticatorValidateStage.objects.get(
            name="default-authentication-mfa-validation",
        )
        mfa.not_configured_action = NotConfiguredAction.DENY
        mfa.device_classes = [DeviceClasses.STATIC]
        mfa.save()
    
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
                query={"sfe": True},
            )
        )
>       login_sfe(self.driver, self.user)

tests/e2e/test_flows_login_sfe.py:78: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <selenium.webdriver.remote.webdriver.WebDriver (session="92710f35b8061905f1a07c8d93145c00")>
user = <User: Fpk1sUSPisq350ujNKIy>

    def login_sfe(driver: WebDriver, user: User):
        """Do entire login flow adjusted for SFE"""
        flow_executor = driver.find_element(By.ID, "flow-sfe-container")
>       identification_stage = flow_executor.find_element(By.ID, "ident-form")
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/e2e/test_flows_login_sfe.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="92710f35b8061905f1a07c8d93145c00", element="f.10E9DB785E87F2856853E55F8B90905B.d.54DC9A3B443F42831554D35D2CBEBA9B.e.2")>
by = 'css selector', value = '[id="ident-form"]'

    def find_element(self, by: str = By.ID, value: str | None = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        Args:
            by: The locating strategy to use. Default is `By.ID`. Supported values include:
                - By.ID: Locate by element ID.
                - By.NAME: Locate by the `name` attribute.
                - By.XPATH: Locate by an XPath expression.
                - By.CSS_SELECTOR: Locate by a CSS selector.
                - By.CLASS_NAME: Locate by the `class` attribute.
                - By.TAG_NAME: Locate by the tag name (e.g., "input", "button").
                - By.LINK_TEXT: Locate a link element by its exact text.
                - By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.
            value: The locator value to use with the specified `by` strategy.
    
        Returns:
            The first matching `WebElement` found on the page.
    
        Example:
            element = driver.find_element(By.ID, "foo")
        """
        by, value = self._parent.locator_converter.convert(by, value)
>       return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:532: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="92710f35b8061905f1a07c8d93145c00", element="f.10E9DB785E87F2856853E55F8B90905B.d.54DC9A3B443F42831554D35D2CBEBA9B.e.2")>
command = 'findChildElement'
params = {'id': 'f.10E9DB785E87F2856853E55F8B90905B.d.54DC9A3B443F42831554D35D2CBEBA9B.e.2', 'using': 'css selector', 'value': '[id="ident-form"]'}

    def _execute(self, command, params=None):
        """Executes a command against the underlying HTML element.
    
        Args:
            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.
        """
        if not params:
            params = {}
        params["id"] = self._id
>       return self._parent.execute(command, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="92710f35b8061905f1a07c8d93145c00")>
driver_command = 'findChildElement'
params = {'using': 'css selector', 'value': '[id="ident-form"]'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d0471eb0>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#20 0x55573211cd6d \\u003Cunknown>\\n#21 0x55573212e903 \\u003Cunknown>\\n#22 0x7f368a21d469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="ident-form"]"}
E         (Session info: chrome=145.0.7632.109); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#nosuchelementexception
E       Stacktrace:
E       #0 0x555732130302 <unknown>
E       #1 0x555731b050c6 <unknown>
E       #2 0x555731b5725c <unknown>
E       #3 0x555731b57475 <unknown>
E       #4 0x555731b4b5da <unknown>
E       #5 0x555731b7c861 <unknown>
E       #6 0x555731b4b4e2 <unknown>
E       #7 0x555731b7cba2 <unknown>
E       #8 0x555731b9ed7d <unknown>
E       #9 0x555731b7c5d7 <unknown>
E       #10 0x555731b498b2 <unknown>
E       #11 0x555731b4a725 <unknown>
E       #12 0x5557320f3d44 <unknown>
E       #13 0x5557320f7086 <unknown>
E       #14 0x5557320f6b3e <unknown>
E       #15 0x5557320f74f9 <unknown>
E       #16 0x5557320e36fa <unknown>
E       #17 0x5557320f787a <unknown>
E       #18 0x5557320cbe49 <unknown>
E       #19 0x55573211cb79 <unknown>
E       #20 0x55573211cd6d <unknown>
E       #21 0x55573212e903 <unknown>
E       #22 0x7f368a21d469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: NoSuchElementException
tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn::test_webauthn_authenticate_sfe
Stack Traces | 123s run time
self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>,)
kwargs = {}, file = 'default/flow-default-authenticator-webauthn-setup.yaml'
content = 'version: 1\nmetadata:\n  name: Default - WebAuthn MFA setup flow\nentries:\n- attrs:\n    designation: stage_configur...age: !KeyOf default-authenticator-webauthn-setup\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    @apply_blueprint("default/flow-default-authenticator-webauthn-setup.yaml")
    def test_webauthn_authenticate_sfe(self):
        """Test WebAuthn authentication (SFE)"""
        self.register()
        self.driver.delete_all_cookies()
    
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
                query={"sfe": True},
            )
        )
>       login_sfe(self.driver, self.user)

tests/e2e/test_flows_authenticators_webauthn.py:100: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <selenium.webdriver.remote.webdriver.WebDriver (session="682ebc3b75f13c25806fad28c16c565d")>
user = <User: 0aXr7lStqxrCpbcu5GGt>

    def login_sfe(driver: WebDriver, user: User):
        """Do entire login flow adjusted for SFE"""
        flow_executor = driver.find_element(By.ID, "flow-sfe-container")
>       identification_stage = flow_executor.find_element(By.ID, "ident-form")
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/e2e/test_flows_login_sfe.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="682ebc3b75f13c25806fad28c16c565d", element="f.EB924892230A687571CD9B6326FB99DF.d.12DD8EBECC12E07B0221EB8CC59B5313.e.69")>
by = 'css selector', value = '[id="ident-form"]'

    def find_element(self, by: str = By.ID, value: str | None = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        Args:
            by: The locating strategy to use. Default is `By.ID`. Supported values include:
                - By.ID: Locate by element ID.
                - By.NAME: Locate by the `name` attribute.
                - By.XPATH: Locate by an XPath expression.
                - By.CSS_SELECTOR: Locate by a CSS selector.
                - By.CLASS_NAME: Locate by the `class` attribute.
                - By.TAG_NAME: Locate by the tag name (e.g., "input", "button").
                - By.LINK_TEXT: Locate a link element by its exact text.
                - By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.
            value: The locator value to use with the specified `by` strategy.
    
        Returns:
            The first matching `WebElement` found on the page.
    
        Example:
            element = driver.find_element(By.ID, "foo")
        """
        by, value = self._parent.locator_converter.convert(by, value)
>       return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:532: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="682ebc3b75f13c25806fad28c16c565d", element="f.EB924892230A687571CD9B6326FB99DF.d.12DD8EBECC12E07B0221EB8CC59B5313.e.69")>
command = 'findChildElement'
params = {'id': 'f.EB924892230A687571CD9B6326FB99DF.d.12DD8EBECC12E07B0221EB8CC59B5313.e.69', 'using': 'css selector', 'value': '[id="ident-form"]'}

    def _execute(self, command, params=None):
        """Executes a command against the underlying HTML element.
    
        Args:
            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.
        """
        if not params:
            params = {}
        params["id"] = self._id
>       return self._parent.execute(command, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="682ebc3b75f13c25806fad28c16c565d")>
driver_command = 'findChildElement'
params = {'using': 'css selector', 'value': '[id="ident-form"]'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d80d3650>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#20 0x55d0e4497d6d \\u003Cunknown>\\n#21 0x55d0e44a9903 \\u003Cunknown>\\n#22 0x7f4d4ce39469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="ident-form"]"}
E         (Session info: chrome=145.0.7632.109); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#nosuchelementexception
E       Stacktrace:
E       #0 0x55d0e44ab302 <unknown>
E       #1 0x55d0e3e800c6 <unknown>
E       #2 0x55d0e3ed225c <unknown>
E       #3 0x55d0e3ed2475 <unknown>
E       #4 0x55d0e3ec65da <unknown>
E       #5 0x55d0e3ef7861 <unknown>
E       #6 0x55d0e3ec64e2 <unknown>
E       #7 0x55d0e3ef7ba2 <unknown>
E       #8 0x55d0e3f19d7d <unknown>
E       #9 0x55d0e3ef75d7 <unknown>
E       #10 0x55d0e3ec48b2 <unknown>
E       #11 0x55d0e3ec5725 <unknown>
E       #12 0x55d0e446ed44 <unknown>
E       #13 0x55d0e4472086 <unknown>
E       #14 0x55d0e4471b3e <unknown>
E       #15 0x55d0e44724f9 <unknown>
E       #16 0x55d0e445e6fa <unknown>
E       #17 0x55d0e447287a <unknown>
E       #18 0x55d0e4446e49 <unknown>
E       #19 0x55d0e4497b79 <unknown>
E       #20 0x55d0e4497d6d <unknown>
E       #21 0x55d0e44a9903 <unknown>
E       #22 0x7f4d4ce39469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: NoSuchElementException

During handling of the above exception, another exception occurred:

self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>,)
kwargs = {}, file = 'default/flow-default-authenticator-webauthn-setup.yaml'
content = 'version: 1\nmetadata:\n  name: Default - WebAuthn MFA setup flow\nentries:\n- attrs:\n    designation: stage_configur...age: !KeyOf default-authenticator-webauthn-setup\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    @apply_blueprint("default/flow-default-authenticator-webauthn-setup.yaml")
    def test_webauthn_authenticate_sfe(self):
        """Test WebAuthn authentication (SFE)"""
        self.register()
        self.driver.delete_all_cookies()
    
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
                query={"sfe": True},
            )
        )
>       login_sfe(self.driver, self.user)

tests/e2e/test_flows_authenticators_webauthn.py:100: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <selenium.webdriver.remote.webdriver.WebDriver (session="02483f5fbbc38d68c1ff6c8a3bec128f")>
user = <User: IGHcRyRVY75WF2ccEHAg>

    def login_sfe(driver: WebDriver, user: User):
        """Do entire login flow adjusted for SFE"""
        flow_executor = driver.find_element(By.ID, "flow-sfe-container")
>       identification_stage = flow_executor.find_element(By.ID, "ident-form")
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/e2e/test_flows_login_sfe.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="02483f5fbbc38d68c1ff6c8a3bec128f", element="f.76BD5ABC04566545BB9871ED7EF25268.d.6A9293FF5EDB219BFA47387A970B5DDE.e.71")>
by = 'css selector', value = '[id="ident-form"]'

    def find_element(self, by: str = By.ID, value: str | None = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        Args:
            by: The locating strategy to use. Default is `By.ID`. Supported values include:
                - By.ID: Locate by element ID.
                - By.NAME: Locate by the `name` attribute.
                - By.XPATH: Locate by an XPath expression.
                - By.CSS_SELECTOR: Locate by a CSS selector.
                - By.CLASS_NAME: Locate by the `class` attribute.
                - By.TAG_NAME: Locate by the tag name (e.g., "input", "button").
                - By.LINK_TEXT: Locate a link element by its exact text.
                - By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.
            value: The locator value to use with the specified `by` strategy.
    
        Returns:
            The first matching `WebElement` found on the page.
    
        Example:
            element = driver.find_element(By.ID, "foo")
        """
        by, value = self._parent.locator_converter.convert(by, value)
>       return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:532: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="02483f5fbbc38d68c1ff6c8a3bec128f", element="f.76BD5ABC04566545BB9871ED7EF25268.d.6A9293FF5EDB219BFA47387A970B5DDE.e.71")>
command = 'findChildElement'
params = {'id': 'f.76BD5ABC04566545BB9871ED7EF25268.d.6A9293FF5EDB219BFA47387A970B5DDE.e.71', 'using': 'css selector', 'value': '[id="ident-form"]'}

    def _execute(self, command, params=None):
        """Executes a command against the underlying HTML element.
    
        Args:
            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.
        """
        if not params:
            params = {}
        params["id"] = self._id
>       return self._parent.execute(command, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="02483f5fbbc38d68c1ff6c8a3bec128f")>
driver_command = 'findChildElement'
params = {'using': 'css selector', 'value': '[id="ident-form"]'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d1148e10>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#20 0x55f51802fd6d \\u003Cunknown>\\n#21 0x55f518041903 \\u003Cunknown>\\n#22 0x7efdaa91d469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="ident-form"]"}
E         (Session info: chrome=145.0.7632.109); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#nosuchelementexception
E       Stacktrace:
E       #0 0x55f518043302 <unknown>
E       #1 0x55f517a180c6 <unknown>
E       #2 0x55f517a6a25c <unknown>
E       #3 0x55f517a6a475 <unknown>
E       #4 0x55f517a5e5da <unknown>
E       #5 0x55f517a8f861 <unknown>
E       #6 0x55f517a5e4e2 <unknown>
E       #7 0x55f517a8fba2 <unknown>
E       #8 0x55f517ab1d7d <unknown>
E       #9 0x55f517a8f5d7 <unknown>
E       #10 0x55f517a5c8b2 <unknown>
E       #11 0x55f517a5d725 <unknown>
E       #12 0x55f518006d44 <unknown>
E       #13 0x55f51800a086 <unknown>
E       #14 0x55f518009b3e <unknown>
E       #15 0x55f51800a4f9 <unknown>
E       #16 0x55f517ff66fa <unknown>
E       #17 0x55f51800a87a <unknown>
E       #18 0x55f517fdee49 <unknown>
E       #19 0x55f51802fb79 <unknown>
E       #20 0x55f51802fd6d <unknown>
E       #21 0x55f518041903 <unknown>
E       #22 0x7efdaa91d469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: NoSuchElementException

During handling of the above exception, another exception occurred:

self = <unittest.case._Outcome object at 0x7f74e38d8c80>
test_case = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>
subTest = False

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

.../hostedtoolcache/Python/3.14.4........./x64/lib/python3.14/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>
result = <TestCaseFunction test_webauthn_authenticate_sfe>

    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.14.4........./x64/lib/python3.14/unittest/case.py:669: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>
method = <bound method TestFlowsAuthenticatorWebAuthn.test_webauthn_authenticate_sfe of <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>>

    def _callTestMethod(self, method):
>       result = method()
                 ^^^^^^^^

.../hostedtoolcache/Python/3.14.4........./x64/lib/python3.14/unittest/case.py:615: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>
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/decorators.py:73: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>
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/decorators.py:73: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>
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/decorators.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>,)
kwargs = {}, file = 'default/flow-default-authenticator-webauthn-setup.yaml'
content = 'version: 1\nmetadata:\n  name: Default - WebAuthn MFA setup flow\nentries:\n- attrs:\n    designation: stage_configur...age: !KeyOf default-authenticator-webauthn-setup\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_authenticators_webauthn.TestFlowsAuthenticatorWebAuthn testMethod=test_webauthn_authenticate_sfe>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    @apply_blueprint("default/flow-default-authenticator-webauthn-setup.yaml")
    def test_webauthn_authenticate_sfe(self):
        """Test WebAuthn authentication (SFE)"""
        self.register()
        self.driver.delete_all_cookies()
    
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
                query={"sfe": True},
            )
        )
>       login_sfe(self.driver, self.user)

tests/e2e/test_flows_authenticators_webauthn.py:100: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <selenium.webdriver.remote.webdriver.WebDriver (session="05ff4cc2fbe6f483b27df982d0d3f000")>
user = <User: zKIOpHSC0urulG9Avnn6>

    def login_sfe(driver: WebDriver, user: User):
        """Do entire login flow adjusted for SFE"""
        flow_executor = driver.find_element(By.ID, "flow-sfe-container")
>       identification_stage = flow_executor.find_element(By.ID, "ident-form")
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/e2e/test_flows_login_sfe.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="05ff4cc2fbe6f483b27df982d0d3f000", element="f.FA2DD6F363A6221A812136D9AC443616.d.37444F56069538B44CADAC47D190F9FD.e.65")>
by = 'css selector', value = '[id="ident-form"]'

    def find_element(self, by: str = By.ID, value: str | None = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        Args:
            by: The locating strategy to use. Default is `By.ID`. Supported values include:
                - By.ID: Locate by element ID.
                - By.NAME: Locate by the `name` attribute.
                - By.XPATH: Locate by an XPath expression.
                - By.CSS_SELECTOR: Locate by a CSS selector.
                - By.CLASS_NAME: Locate by the `class` attribute.
                - By.TAG_NAME: Locate by the tag name (e.g., "input", "button").
                - By.LINK_TEXT: Locate a link element by its exact text.
                - By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.
            value: The locator value to use with the specified `by` strategy.
    
        Returns:
            The first matching `WebElement` found on the page.
    
        Example:
            element = driver.find_element(By.ID, "foo")
        """
        by, value = self._parent.locator_converter.convert(by, value)
>       return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:532: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="05ff4cc2fbe6f483b27df982d0d3f000", element="f.FA2DD6F363A6221A812136D9AC443616.d.37444F56069538B44CADAC47D190F9FD.e.65")>
command = 'findChildElement'
params = {'id': 'f.FA2DD6F363A6221A812136D9AC443616.d.37444F56069538B44CADAC47D190F9FD.e.65', 'using': 'css selector', 'value': '[id="ident-form"]'}

    def _execute(self, command, params=None):
        """Executes a command against the underlying HTML element.
    
        Args:
            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.
        """
        if not params:
            params = {}
        params["id"] = self._id
>       return self._parent.execute(command, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="05ff4cc2fbe6f483b27df982d0d3f000")>
driver_command = 'findChildElement'
params = {'using': 'css selector', 'value': '[id="ident-form"]'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d8ca6fc0>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#20 0x56050f101d6d \\u003Cunknown>\\n#21 0x56050f113903 \\u003Cunknown>\\n#22 0x7ff690324469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="ident-form"]"}
E         (Session info: chrome=145.0.7632.109); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#nosuchelementexception
E       Stacktrace:
E       #0 0x56050f115302 <unknown>
E       #1 0x56050eaea0c6 <unknown>
E       #2 0x56050eb3c25c <unknown>
E       #3 0x56050eb3c475 <unknown>
E       #4 0x56050eb305da <unknown>
E       #5 0x56050eb61861 <unknown>
E       #6 0x56050eb304e2 <unknown>
E       #7 0x56050eb61ba2 <unknown>
E       #8 0x56050eb83d7d <unknown>
E       #9 0x56050eb615d7 <unknown>
E       #10 0x56050eb2e8b2 <unknown>
E       #11 0x56050eb2f725 <unknown>
E       #12 0x56050f0d8d44 <unknown>
E       #13 0x56050f0dc086 <unknown>
E       #14 0x56050f0dbb3e <unknown>
E       #15 0x56050f0dc4f9 <unknown>
E       #16 0x56050f0c86fa <unknown>
E       #17 0x56050f0dc87a <unknown>
E       #18 0x56050f0b0e49 <unknown>
E       #19 0x56050f101b79 <unknown>
E       #20 0x56050f101d6d <unknown>
E       #21 0x56050f113903 <unknown>
E       #22 0x7ff690324469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: NoSuchElementException
tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE::test_login
Stack Traces | 168s run time
self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    def test_login(self):
        """test default login flow"""
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
                query={"sfe": True},
            )
        )
>       login_sfe(self.driver, self.user)

tests/e2e/test_flows_login_sfe.py:53: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <selenium.webdriver.remote.webdriver.WebDriver (session="7a6b19648d82bb6d843106a682b1029f")>
user = <User: ATN5EOIJzYvoaWAaHsBs>

    def login_sfe(driver: WebDriver, user: User):
        """Do entire login flow adjusted for SFE"""
        flow_executor = driver.find_element(By.ID, "flow-sfe-container")
>       identification_stage = flow_executor.find_element(By.ID, "ident-form")
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/e2e/test_flows_login_sfe.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="7a6b19648d82bb6d843106a682b1029f", element="f.C0EA579EA26153F7FF603562C1C25975.d.8B5C00813A2334FDE75D917A8E43D684.e.2")>
by = 'css selector', value = '[id="ident-form"]'

    def find_element(self, by: str = By.ID, value: str | None = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        Args:
            by: The locating strategy to use. Default is `By.ID`. Supported values include:
                - By.ID: Locate by element ID.
                - By.NAME: Locate by the `name` attribute.
                - By.XPATH: Locate by an XPath expression.
                - By.CSS_SELECTOR: Locate by a CSS selector.
                - By.CLASS_NAME: Locate by the `class` attribute.
                - By.TAG_NAME: Locate by the tag name (e.g., "input", "button").
                - By.LINK_TEXT: Locate a link element by its exact text.
                - By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.
            value: The locator value to use with the specified `by` strategy.
    
        Returns:
            The first matching `WebElement` found on the page.
    
        Example:
            element = driver.find_element(By.ID, "foo")
        """
        by, value = self._parent.locator_converter.convert(by, value)
>       return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:532: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="7a6b19648d82bb6d843106a682b1029f", element="f.C0EA579EA26153F7FF603562C1C25975.d.8B5C00813A2334FDE75D917A8E43D684.e.2")>
command = 'findChildElement'
params = {'id': 'f.C0EA579EA26153F7FF603562C1C25975.d.8B5C00813A2334FDE75D917A8E43D684.e.2', 'using': 'css selector', 'value': '[id="ident-form"]'}

    def _execute(self, command, params=None):
        """Executes a command against the underlying HTML element.
    
        Args:
            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.
        """
        if not params:
            params = {}
        params["id"] = self._id
>       return self._parent.execute(command, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="7a6b19648d82bb6d843106a682b1029f")>
driver_command = 'findChildElement'
params = {'using': 'css selector', 'value': '[id="ident-form"]'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74da4312b0>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#20 0x5638b54ced6d \\u003Cunknown>\\n#21 0x5638b54e0903 \\u003Cunknown>\\n#22 0x7ff12627e469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="ident-form"]"}
E         (Session info: chrome=145.0.7632.109); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#nosuchelementexception
E       Stacktrace:
E       #0 0x5638b54e2302 <unknown>
E       #1 0x5638b4eb70c6 <unknown>
E       #2 0x5638b4f0925c <unknown>
E       #3 0x5638b4f09475 <unknown>
E       #4 0x5638b4efd5da <unknown>
E       #5 0x5638b4f2e861 <unknown>
E       #6 0x5638b4efd4e2 <unknown>
E       #7 0x5638b4f2eba2 <unknown>
E       #8 0x5638b4f50d7d <unknown>
E       #9 0x5638b4f2e5d7 <unknown>
E       #10 0x5638b4efb8b2 <unknown>
E       #11 0x5638b4efc725 <unknown>
E       #12 0x5638b54a5d44 <unknown>
E       #13 0x5638b54a9086 <unknown>
E       #14 0x5638b54a8b3e <unknown>
E       #15 0x5638b54a94f9 <unknown>
E       #16 0x5638b54956fa <unknown>
E       #17 0x5638b54a987a <unknown>
E       #18 0x5638b547de49 <unknown>
E       #19 0x5638b54ceb79 <unknown>
E       #20 0x5638b54ced6d <unknown>
E       #21 0x5638b54e0903 <unknown>
E       #22 0x7ff12627e469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: NoSuchElementException

During handling of the above exception, another exception occurred:

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    def test_login(self):
        """test default login flow"""
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
                query={"sfe": True},
            )
        )
>       login_sfe(self.driver, self.user)

tests/e2e/test_flows_login_sfe.py:53: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <selenium.webdriver.remote.webdriver.WebDriver (session="633fdffcea23a921b6adcf747193502f")>
user = <User: PCNEj1U9ZMGRXfID4nnf>

    def login_sfe(driver: WebDriver, user: User):
        """Do entire login flow adjusted for SFE"""
        flow_executor = driver.find_element(By.ID, "flow-sfe-container")
>       identification_stage = flow_executor.find_element(By.ID, "ident-form")
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/e2e/test_flows_login_sfe.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="633fdffcea23a921b6adcf747193502f", element="f.096796FE98447BEB3B70A549303CB998.d.ECF092CD2772A978A916C92730208751.e.2")>
by = 'css selector', value = '[id="ident-form"]'

    def find_element(self, by: str = By.ID, value: str | None = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        Args:
            by: The locating strategy to use. Default is `By.ID`. Supported values include:
                - By.ID: Locate by element ID.
                - By.NAME: Locate by the `name` attribute.
                - By.XPATH: Locate by an XPath expression.
                - By.CSS_SELECTOR: Locate by a CSS selector.
                - By.CLASS_NAME: Locate by the `class` attribute.
                - By.TAG_NAME: Locate by the tag name (e.g., "input", "button").
                - By.LINK_TEXT: Locate a link element by its exact text.
                - By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.
            value: The locator value to use with the specified `by` strategy.
    
        Returns:
            The first matching `WebElement` found on the page.
    
        Example:
            element = driver.find_element(By.ID, "foo")
        """
        by, value = self._parent.locator_converter.convert(by, value)
>       return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:532: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="633fdffcea23a921b6adcf747193502f", element="f.096796FE98447BEB3B70A549303CB998.d.ECF092CD2772A978A916C92730208751.e.2")>
command = 'findChildElement'
params = {'id': 'f.096796FE98447BEB3B70A549303CB998.d.ECF092CD2772A978A916C92730208751.e.2', 'using': 'css selector', 'value': '[id="ident-form"]'}

    def _execute(self, command, params=None):
        """Executes a command against the underlying HTML element.
    
        Args:
            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.
        """
        if not params:
            params = {}
        params["id"] = self._id
>       return self._parent.execute(command, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="633fdffcea23a921b6adcf747193502f")>
driver_command = 'findChildElement'
params = {'using': 'css selector', 'value': '[id="ident-form"]'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d84791d0>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#20 0x556c37973d6d \\u003Cunknown>\\n#21 0x556c37985903 \\u003Cunknown>\\n#22 0x7f710ef47469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="ident-form"]"}
E         (Session info: chrome=145.0.7632.109); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#nosuchelementexception
E       Stacktrace:
E       #0 0x556c37987302 <unknown>
E       #1 0x556c3735c0c6 <unknown>
E       #2 0x556c373ae25c <unknown>
E       #3 0x556c373ae475 <unknown>
E       #4 0x556c373a25da <unknown>
E       #5 0x556c373d3861 <unknown>
E       #6 0x556c373a24e2 <unknown>
E       #7 0x556c373d3ba2 <unknown>
E       #8 0x556c373f5d7d <unknown>
E       #9 0x556c373d35d7 <unknown>
E       #10 0x556c373a08b2 <unknown>
E       #11 0x556c373a1725 <unknown>
E       #12 0x556c3794ad44 <unknown>
E       #13 0x556c3794e086 <unknown>
E       #14 0x556c3794db3e <unknown>
E       #15 0x556c3794e4f9 <unknown>
E       #16 0x556c3793a6fa <unknown>
E       #17 0x556c3794e87a <unknown>
E       #18 0x556c37922e49 <unknown>
E       #19 0x556c37973b79 <unknown>
E       #20 0x556c37973d6d <unknown>
E       #21 0x556c37985903 <unknown>
E       #22 0x7f710ef47469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: NoSuchElementException

During handling of the above exception, another exception occurred:

self = <unittest.case._Outcome object at 0x7f74de67d550>
test_case = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>
subTest = False

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

.../hostedtoolcache/Python/3.14.4........./x64/lib/python3.14/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>
result = <TestCaseFunction test_login>

    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.14.4........./x64/lib/python3.14/unittest/case.py:669: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>
method = <bound method TestFlowsLoginSFE.test_login of <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>>

    def _callTestMethod(self, method):
>       result = method()
                 ^^^^^^^^

.../hostedtoolcache/Python/3.14.4........./x64/lib/python3.14/unittest/case.py:615: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>
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/decorators.py:73: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>
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/decorators.py:73: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>
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/decorators.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>
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/decorators.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_flows_login_sfe.TestFlowsLoginSFE testMethod=test_login>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    def test_login(self):
        """test default login flow"""
        self.driver.get(
            self.url(
                "authentik_core:if-flow",
                flow_slug="default-authentication-flow",
                query={"sfe": True},
            )
        )
>       login_sfe(self.driver, self.user)

tests/e2e/test_flows_login_sfe.py:53: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

driver = <selenium.webdriver.remote.webdriver.WebDriver (session="35d6390cf007ccea9159a230c21db731")>
user = <User: sM16UAiNxo6UNT2kcabE>

    def login_sfe(driver: WebDriver, user: User):
        """Do entire login flow adjusted for SFE"""
        flow_executor = driver.find_element(By.ID, "flow-sfe-container")
>       identification_stage = flow_executor.find_element(By.ID, "ident-form")
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/e2e/test_flows_login_sfe.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="35d6390cf007ccea9159a230c21db731", element="f.AFB621C2316AC5BBC98B3A629F10CF59.d.AD65D3A56E34875E7485BBDC560D8D66.e.2")>
by = 'css selector', value = '[id="ident-form"]'

    def find_element(self, by: str = By.ID, value: str | None = None) -> WebElement:
        """Find an element given a By strategy and locator.
    
        Args:
            by: The locating strategy to use. Default is `By.ID`. Supported values include:
                - By.ID: Locate by element ID.
                - By.NAME: Locate by the `name` attribute.
                - By.XPATH: Locate by an XPath expression.
                - By.CSS_SELECTOR: Locate by a CSS selector.
                - By.CLASS_NAME: Locate by the `class` attribute.
                - By.TAG_NAME: Locate by the tag name (e.g., "input", "button").
                - By.LINK_TEXT: Locate a link element by its exact text.
                - By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.
            value: The locator value to use with the specified `by` strategy.
    
        Returns:
            The first matching `WebElement` found on the page.
    
        Example:
            element = driver.find_element(By.ID, "foo")
        """
        by, value = self._parent.locator_converter.convert(by, value)
>       return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"]
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:532: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webelement.WebElement (session="35d6390cf007ccea9159a230c21db731", element="f.AFB621C2316AC5BBC98B3A629F10CF59.d.AD65D3A56E34875E7485BBDC560D8D66.e.2")>
command = 'findChildElement'
params = {'id': 'f.AFB621C2316AC5BBC98B3A629F10CF59.d.AD65D3A56E34875E7485BBDC560D8D66.e.2', 'using': 'css selector', 'value': '[id="ident-form"]'}

    def _execute(self, command, params=None):
        """Executes a command against the underlying HTML element.
    
        Args:
            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.
        """
        if not params:
            params = {}
        params["id"] = self._id
>       return self._parent.execute(command, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.venv/lib/python3.14.../webdriver/remote/webelement.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.webdriver.WebDriver (session="35d6390cf007ccea9159a230c21db731")>
driver_command = 'findChildElement'
params = {'using': 'css selector', 'value': '[id="ident-form"]'}

    def execute(self, driver_command: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """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 = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    
        if response:
>           self.error_handler.check_response(response)

.venv/lib/python3.14.../webdriver/remote/webdriver.py:450: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7f74d15016d0>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\\n#20 0x564095960d6d \\u003Cunknown>\\n#21 0x564095972903 \\u003Cunknown>\\n#22 0x7f193ca79469 \\u003Cunknown>\\n"}}'}

    def check_response(self, response: dict[str, Any]) -> None:
        """Check 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:
            WebDriverException: 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):
                try:
                    value = json.loads(value_json)
                    if isinstance(value, dict):
                        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") if isinstance(message, dict) else None
                        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)
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="ident-form"]"}
E         (Session info: chrome=145.0.7632.109); For documentation on this error, please visit: https://www.selenium..../webdriver/troubleshooting/errors#nosuchelementexception
E       Stacktrace:
E       #0 0x564095974302 <unknown>
E       #1 0x5640953490c6 <unknown>
E       #2 0x56409539b25c <unknown>
E       #3 0x56409539b475 <unknown>
E       #4 0x56409538f5da <unknown>
E       #5 0x5640953c0861 <unknown>
E       #6 0x56409538f4e2 <unknown>
E       #7 0x5640953c0ba2 <unknown>
E       #8 0x5640953e2d7d <unknown>
E       #9 0x5640953c05d7 <unknown>
E       #10 0x56409538d8b2 <unknown>
E       #11 0x56409538e725 <unknown>
E       #12 0x564095937d44 <unknown>
E       #13 0x56409593b086 <unknown>
E       #14 0x56409593ab3e <unknown>
E       #15 0x56409593b4f9 <unknown>
E       #16 0x5640959276fa <unknown>
E       #17 0x56409593b87a <unknown>
E       #18 0x56409590fe49 <unknown>
E       #19 0x564095960b79 <unknown>
E       #20 0x564095960d6d <unknown>
E       #21 0x564095972903 <unknown>
E       #22 0x7f193ca79469 <unknown>

.venv/lib/python3.14.../webdriver/remote/errorhandler.py:232: NoSuchElementException

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

GirlBossRush and others added 2 commits April 27, 2026 23:30
Mermaid (and a handful of other libs in the bundle) inject `<style>`
elements at runtime via createElement+appendChild, which never carries a
nonce. CSP3 §6.6.2.2 specifies that browsers ignore `'unsafe-inline'`
whenever a nonce is also present in the same source list, so we cannot
have both — keep the nonce and break dynamic styling, or drop it and
rely on `'unsafe-inline'`. Script-side CSP keeps its nonce + strict
allowlist; only style-src is relaxed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants