Skip to content

flows: fix blip of un-templated flow title placeholder (cherry-pick #26905 to version-2026.8) - #27141

Open
authentik-cherry-pick[bot] wants to merge 2 commits into
version-2026.8from
cherry-pick/26905-to-version-2026.8
Open

authentik-cherry-pick[bot] wants to merge 2 commits into
version-2026.8from
cherry-pick/26905-to-version-2026.8

Conversation

@authentik-cherry-pick

@authentik-cherry-pick authentik-cherry-pick Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ This cherry-pick has conflicts that require manual resolution.

Cherry-pick of #26905 to version-2026.8 branch.

Original PR: #26905
Original Author: @BeryJu
Cherry-picked commit: a5b1f7f

Please resolve the conflicts in this PR before merging.

closes #27134

This cherry-pick has conflicts that need manual resolution.

Original PR: #26905
Original commit: a5b1f7f
@netlify

netlify Bot commented Oct 24, 2026

Copy link
Copy Markdown

✅ Deploy Preview for authentik-storybook ready!

Name Link
🔨 Latest commit 6b6f560
🔍 Latest deploy log https://app.netlify.com/projects/authentik-storybook/deploys/6adcbddaacad7a7813790746
😎 Deploy Preview https://deploy-preview-27141--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.

@netlify

netlify Bot commented Oct 24, 2026

Copy link
Copy Markdown

✅ Deploy Preview for authentik-integrations ready!

Name Link
🔨 Latest commit 6b6f560
🔍 Latest deploy log https://app.netlify.com/projects/authentik-integrations/deploys/6adcbddaafbac57969f9c9a7
😎 Deploy Preview https://deploy-preview-27141--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.

@codecov

codecov Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
4365 2 4363 1
View the top 2 failed test(s) by shortest run time
authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle::test_title_placeholder
Stack Traces | 0.093s run time
self = <unittest.case._Outcome object at 0x7f60703a4980>
test_case = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_placeholder>
subTest = False

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

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

self = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_placeholder>
result = <TestCaseFunction test_title_placeholder>

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

self = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_placeholder>
method = <bound method TestFlowInterfaceTitle.test_title_placeholder of <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_placeholder>>

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

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

self = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_placeholder>

    def test_title_placeholder(self):
        """Placeholders are blanked as no plan context exists yet"""
        flow = create_test_flow()
        flow.title = "Welcome to %(app)s"
        flow.save()
        response = self.client.get(
            reverse("authentik_core:if-flow", kwargs={"flow_slug": flow.slug})
        )
        self.assertEqual(response.status_code, 200)
>       self.assertContains(response, '<meta name="ak-flow-title" content="Welcome to">')

.../flows/tests/test_interface_sfe.py:21: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_placeholder>
response = <TemplateResponse status_code=200, "text/html; charset=utf-8">
text = '<meta name="ak-flow-title" content="Welcome to">', count = None
status_code = 200, msg_prefix = '', html = False

    def assertContains(
        self, response, text, count=None, status_code=200, msg_prefix="", html=False
    ):
        """
        Assert that a response indicates that some content was retrieved
        successfully, (i.e., the HTTP status code was as expected) and that
        ``text`` occurs ``count`` times in the content of the response.
        If ``count`` is None, the count doesn't matter - the assertion is true
        if the text occurs at least once in the response.
        """
        text_repr, real_count, msg_prefix, content_repr = self._assert_contains(
            response, text, status_code, msg_prefix, html
        )
    
        if count is not None:
            self.assertEqual(
                real_count,
                count,
                (
                    f"{msg_prefix}Found {real_count} instances of {text_repr} "
                    f"(expected {count}) in the following response\n{content_repr}"
                ),
            )
        else:
>           self.assertTrue(
                real_count != 0,
                (
                    f"{msg_prefix}Couldn't find {text_repr} in the following response\n"
                    f"{content_repr}"
                ),
            )

.venv/lib/python3.14.../django/test/testcases.py:633: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_placeholder>
expr = False
msg = 'False is not true : Couldn\'t find \'<meta name="ak-flow-title" content="Welcome to">\' in the following response\nb\...vjts5jlm8"\\n    ></ak-flow-inspector>\\n</ak-drawer>\\n\\n        \\n        \\n        \\n    </body>\\n</html>\\n\''

    def assertTrue(self, expr, msg=None):
        """Check that the expression is true."""
        if not expr:
            msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
>           raise self.failureException(msg)
E           AssertionError: False is not true : Couldn't find '<meta name="ak-flow-title" content="Welcome to">' in the following response
E           b'\n\n\n\n\n<!DOCTYPE html>\n<html\n    lang="en"\n    \n    data-theme="light"\n    data-theme-choice="auto"\n>\n    <head>\n        <meta charset="UTF-8">\n        <meta name="viewport" content="width=device-width, initial-scale=1">\n        \n        <meta name="darkreader-lock">\n        <title>authentik</title>\n        \n\n<link rel="icon" href=".../assets/icons/icon.png">\n<link rel="shortcut icon" href=".../assets/icons/icon.png">\n\n\n\n\n        \n\n        \n<link rel="prefetch" href="http:.../assets/images/flow_background.jpg" />\n\n\n\n\n<script data-id="authentik-config">\n    "use strict";\n\n    window.authentik = {\n        locale: "en",\n        config: JSON.parse(\'{\\u0022error_reporting\\u0022: {\\u0022enabled\\u0022: false, \\u0022sentry_dsn\\u0022: \\u0022https://151ba72610234c4c97c5bcff4e1cffd8@authentik.error\\u002Dreporting.a7k.io/4504163677503489\\u0022, \\u0022environment\\u0022: \\u0022testing\\u0022, \\u0022send_pii\\u0022: true, \\u0022traces_sample_rate\\u0022: 0.0}, \\u0022capabilities\\u0022: [\\u0022can_save_media\\u0022, \\u0022can_save_reports\\u0022, \\u0022can_asn\\u0022, \\u0022can_geo_ip\\u0022, \\u0022can_impersonate\\u0022, \\u0022is_enterprise\\u0022], \\u0022cache_timeout\\u0022: 300, \\u0022cache_timeout_flows\\u0022: 300, \\u0022cache_timeout_policies\\u0022: 300}\' || "{}"),\n        brand: JSON.parse(\'{\\u0022matched_domain\\u0022: \\u0022fallback\\u0022, \\u0022branding_title\\u0022: \\u0022authentik\\u0022, \\u0022branding_logo\\u0022: \\.../assets/icons/icon_left_brand.svg\\u0022, \\u0022branding_logo_themed_urls\\u0022: null, \\u0022branding_favicon\\u0022: \\u0022.../assets/icons/icon.png\\u0022, \\u0022branding_favicon_themed_urls\\u0022: null, \\u0022branding_custom_css\\u0022: \\u0022\\u0022, \\u0022branding_map_tiles\\u0022: \\u0022\\u0022, \\u0022ui_footer_links\\u0022: [], \\u0022ui_theme\\u0022: \\u0022automatic\\u0022, \\u0022default_locale\\u0022: \\u0022\\u0022, \\u0022flags\\u0022: {\\u0022flows_continuous_login\\u0022: false, \\u0022flows_refresh_others\\u0022: false}}\' || "{}"),\n        versionFamily: "2026.8",\n        versionSubdomain: "version-2026-8",\n        build: "",\n        api: {\n            base: "http://testserver/",\n            relBase: "/",\n        },\n    };\n</script>\n\n<script data-id="authentik-messages" type="application/json">\n  []\n</script>\n\n\n<script data-id="flow-config">\n    "use strict";\n\n    window.authentik.flow = {\n        "layout": "stacked",\n        "background": "",\n        "title": "Welcome to",\n    };\n</script>\n\n\n        \n<link rel="stylesheet" type="text/css" href=".../dist/styles/flow-2026.8.5.css" />\n\n\n        \n\n\n\n  <script data-id="theme-script">\n    "use strict";\n\n    (function () {\n        try {\n          const { documentElement } = document;\n\n            /* Ignore older theme names */\n            let locallyStoredTheme = window.localStorage?.getItem("theme") || null;\n\n            if (typeof locallyStoredTheme === "string") {\n                locallyStoredTheme = locallyStoredTheme.trim();\n            }\n            if (!(["auto", "light", "dark"].includes(locallyStoredTheme))) {\n                locallyStoredTheme = null;\n            }\n\n            const initialThemeChoice =\n                new URLSearchParams(window.location.search).get("theme") || locallyStoredTheme;\n\n            const themeChoice =\n                initialThemeChoice || documentElement.dataset.themeChoice || "auto";\n\n            documentElement.dataset.themeChoice = themeChoice;\n\n            if (themeChoice === "auto") {\n                documentElement.dataset.theme = window.matchMedia(\n                    "(prefers-color-scheme: dark)",\n                ).matches\n                    ? "dark"\n                    : "light";\n            } else {\n                documentElement.dataset.theme = themeChoice;\n            }\n\n            documentElement.classList.toggle("pf-theme-dark", documentElement.dataset.theme === "dark");\n        } catch (e) {\n            console.error("Failed to apply theme", e);\n        }\n    })();\n  </script>\n\n  <meta name="color-scheme" content="light dark" />\n  <meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">\n  <meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">\n\n\n\n        <style data-id="brand-css"></style>\n        <script src=".../static/dist/poly-2026.8.5.js" type="module"></script>\n        \n<script src=".../dist/flow/FlowInterface-2026.8.5.js" type="module"></script>\n<style data-id="flow-css">\n  :root {\n      --ak-global--background-image: url("http:.../assets/images/flow_background.jpg");\n  }\n</style>\n\n        \n        <meta name="sentry-trace" content="ceecd555cfb44e9a84adf193d49307c5-b62b6d87fa57ace4" />\n        \n    </head>\n    <body>\n        \n<ak-skip-to-content></ak-skip-to-content>\n<ak-message-container></ak-message-container>\n<ak-drawer id="flow-drawer">\n    <ak-flow-executor\n        slug="gvjts5jlm8"\n        data-layout="stacked"\n        loading\n    >\n        \n\n<div class="ak-c-placeholder" id="ak-placeholder" slot="placeholder">\n    <span\n        class="pf-c-spinner"\n        role="progressbar"\n        aria-valuetext="Loading..."\n        >\n        <span class="pf-c-spinner__clipper"></span>\n        <span class="pf-c-spinner__lead-ball"></span>\n        <span class="pf-c-spinner__tail-ball"></span>\n    </span>\n</div>\n\n        \n        <ak-brand-links name="flow-links" slot="footer"></ak-brand-links>\n    </ak-flow-executor>\n    \n    <ak-flow-inspector\n        slot="panel"\n        id="flow-inspector"\n        data-registration="lazy"\n        slug="gvjts5jlm8"\n    ></ak-flow-inspector>\n</ak-drawer>\n\n        \n        \n        \n    </body>\n</html>\n'

.../hostedtoolcache/Python/3.14.8............/x64/lib/python3.14/unittest/case.py:762: AssertionError
authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle::test_title_literal_percent
Stack Traces | 0.151s run time
self = <unittest.case._Outcome object at 0x7f60703a49f0>
test_case = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_literal_percent>
subTest = False

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

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

self = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_literal_percent>
result = <TestCaseFunction test_title_literal_percent>

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

self = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_literal_percent>
method = <bound method TestFlowInterfaceTitle.test_title_literal_percent of <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_literal_percent>>

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

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

self = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_literal_percent>

    def test_title_literal_percent(self):
        """Titles with a bare percent sign are left as-is"""
        flow = create_test_flow()
        flow.title = "100% secure"
        flow.save()
        response = self.client.get(
            reverse("authentik_core:if-flow", kwargs={"flow_slug": flow.slug})
        )
>       self.assertContains(response, '<meta name="ak-flow-title" content="100% secure">')

.../flows/tests/test_interface_sfe.py:33: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_literal_percent>
response = <TemplateResponse status_code=200, "text/html; charset=utf-8">
text = '<meta name="ak-flow-title" content="100% secure">', count = None
status_code = 200, msg_prefix = '', html = False

    def assertContains(
        self, response, text, count=None, status_code=200, msg_prefix="", html=False
    ):
        """
        Assert that a response indicates that some content was retrieved
        successfully, (i.e., the HTTP status code was as expected) and that
        ``text`` occurs ``count`` times in the content of the response.
        If ``count`` is None, the count doesn't matter - the assertion is true
        if the text occurs at least once in the response.
        """
        text_repr, real_count, msg_prefix, content_repr = self._assert_contains(
            response, text, status_code, msg_prefix, html
        )
    
        if count is not None:
            self.assertEqual(
                real_count,
                count,
                (
                    f"{msg_prefix}Found {real_count} instances of {text_repr} "
                    f"(expected {count}) in the following response\n{content_repr}"
                ),
            )
        else:
>           self.assertTrue(
                real_count != 0,
                (
                    f"{msg_prefix}Couldn't find {text_repr} in the following response\n"
                    f"{content_repr}"
                ),
            )

.venv/lib/python3.14.../django/test/testcases.py:633: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.flows.tests.test_interface_sfe.TestFlowInterfaceTitle testMethod=test_title_literal_percent>
expr = False
msg = 'False is not true : Couldn\'t find \'<meta name="ak-flow-title" content="100% secure">\' in the following response\nb...9eoysnfdi"\\n    ></ak-flow-inspector>\\n</ak-drawer>\\n\\n        \\n        \\n        \\n    </body>\\n</html>\\n\''

    def assertTrue(self, expr, msg=None):
        """Check that the expression is true."""
        if not expr:
            msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
>           raise self.failureException(msg)
E           AssertionError: False is not true : Couldn't find '<meta name="ak-flow-title" content="100% secure">' in the following response
E           b'\n\n\n\n\n<!DOCTYPE html>\n<html\n    lang="en"\n    \n    data-theme="light"\n    data-theme-choice="auto"\n>\n    <head>\n        <meta charset="UTF-8">\n        <meta name="viewport" content="width=device-width, initial-scale=1">\n        \n        <meta name="darkreader-lock">\n        <title>authentik</title>\n        \n\n<link rel="icon" href=".../assets/icons/icon.png">\n<link rel="shortcut icon" href=".../assets/icons/icon.png">\n\n\n\n\n        \n\n        \n<link rel="prefetch" href="http:.../assets/images/flow_background.jpg" />\n\n\n\n\n<script data-id="authentik-config">\n    "use strict";\n\n    window.authentik = {\n        locale: "en",\n        config: JSON.parse(\'{\\u0022error_reporting\\u0022: {\\u0022enabled\\u0022: false, \\u0022sentry_dsn\\u0022: \\u0022https://151ba72610234c4c97c5bcff4e1cffd8@authentik.error\\u002Dreporting.a7k.io/4504163677503489\\u0022, \\u0022environment\\u0022: \\u0022testing\\u0022, \\u0022send_pii\\u0022: true, \\u0022traces_sample_rate\\u0022: 0.0}, \\u0022capabilities\\u0022: [\\u0022can_save_media\\u0022, \\u0022can_save_reports\\u0022, \\u0022can_asn\\u0022, \\u0022can_geo_ip\\u0022, \\u0022can_impersonate\\u0022, \\u0022is_enterprise\\u0022], \\u0022cache_timeout\\u0022: 300, \\u0022cache_timeout_flows\\u0022: 300, \\u0022cache_timeout_policies\\u0022: 300}\' || "{}"),\n        brand: JSON.parse(\'{\\u0022matched_domain\\u0022: \\u0022fallback\\u0022, \\u0022branding_title\\u0022: \\u0022authentik\\u0022, \\u0022branding_logo\\u0022: \\.../assets/icons/icon_left_brand.svg\\u0022, \\u0022branding_logo_themed_urls\\u0022: null, \\u0022branding_favicon\\u0022: \\u0022.../assets/icons/icon.png\\u0022, \\u0022branding_favicon_themed_urls\\u0022: null, \\u0022branding_custom_css\\u0022: \\u0022\\u0022, \\u0022branding_map_tiles\\u0022: \\u0022\\u0022, \\u0022ui_footer_links\\u0022: [], \\u0022ui_theme\\u0022: \\u0022automatic\\u0022, \\u0022default_locale\\u0022: \\u0022\\u0022, \\u0022flags\\u0022: {\\u0022flows_continuous_login\\u0022: false, \\u0022flows_refresh_others\\u0022: false}}\' || "{}"),\n        versionFamily: "2026.8",\n        versionSubdomain: "version-2026-8",\n        build: "",\n        api: {\n            base: "http://testserver/",\n            relBase: "/",\n        },\n    };\n</script>\n\n<script data-id="authentik-messages" type="application/json">\n  []\n</script>\n\n\n<script data-id="flow-config">\n    "use strict";\n\n    window.authentik.flow = {\n        "layout": "stacked",\n        "background": "",\n        "title": "100% secure",\n    };\n</script>\n\n\n        \n<link rel="stylesheet" type="text/css" href=".../dist/styles/flow-2026.8.5.css" />\n\n\n        \n\n\n\n  <script data-id="theme-script">\n    "use strict";\n\n    (function () {\n        try {\n          const { documentElement } = document;\n\n            /* Ignore older theme names */\n            let locallyStoredTheme = window.localStorage?.getItem("theme") || null;\n\n            if (typeof locallyStoredTheme === "string") {\n                locallyStoredTheme = locallyStoredTheme.trim();\n            }\n            if (!(["auto", "light", "dark"].includes(locallyStoredTheme))) {\n                locallyStoredTheme = null;\n            }\n\n            const initialThemeChoice =\n                new URLSearchParams(window.location.search).get("theme") || locallyStoredTheme;\n\n            const themeChoice =\n                initialThemeChoice || documentElement.dataset.themeChoice || "auto";\n\n            documentElement.dataset.themeChoice = themeChoice;\n\n            if (themeChoice === "auto") {\n                documentElement.dataset.theme = window.matchMedia(\n                    "(prefers-color-scheme: dark)",\n                ).matches\n                    ? "dark"\n                    : "light";\n            } else {\n                documentElement.dataset.theme = themeChoice;\n            }\n\n            documentElement.classList.toggle("pf-theme-dark", documentElement.dataset.theme === "dark");\n        } catch (e) {\n            console.error("Failed to apply theme", e);\n        }\n    })();\n  </script>\n\n  <meta name="color-scheme" content="light dark" />\n  <meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">\n  <meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">\n\n\n\n        <style data-id="brand-css"></style>\n        <script src=".../static/dist/poly-2026.8.5.js" type="module"></script>\n        \n<script src=".../dist/flow/FlowInterface-2026.8.5.js" type="module"></script>\n<style data-id="flow-css">\n  :root {\n      --ak-global--background-image: url("http:.../assets/images/flow_background.jpg");\n  }\n</style>\n\n        \n        <meta name="sentry-trace" content="ceecd555cfb44e9a84adf193d49307c5-92a3883310f3a530" />\n        \n    </head>\n    <body>\n        \n<ak-skip-to-content></ak-skip-to-content>\n<ak-message-container></ak-message-container>\n<ak-drawer id="flow-drawer">\n    <ak-flow-executor\n        slug="09eoysnfdi"\n        data-layout="stacked"\n        loading\n    >\n        \n\n<div class="ak-c-placeholder" id="ak-placeholder" slot="placeholder">\n    <span\n        class="pf-c-spinner"\n        role="progressbar"\n        aria-valuetext="Loading..."\n        >\n        <span class="pf-c-spinner__clipper"></span>\n        <span class="pf-c-spinner__lead-ball"></span>\n        <span class="pf-c-spinner__tail-ball"></span>\n    </span>\n</div>\n\n        \n        <ak-brand-links name="flow-links" slot="footer"></ak-brand-links>\n    </ak-flow-executor>\n    \n    <ak-flow-inspector\n        slot="panel"\n        id="flow-inspector"\n        data-registration="lazy"\n        slug="09eoysnfdi"\n    ></ak-flow-inspector>\n</ak-drawer>\n\n        \n        \n        \n    </body>\n</html>\n'

.../hostedtoolcache/Python/3.14.8............/x64/lib/python3.14/unittest/case.py:762: AssertionError

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

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant