{
  "config": {
    "argv": [
      "/opt/hostedtoolcache/node/20.20.2/x64/bin/node",
      "/home/runner/work/dr-card-web/dr-card-web/node_modules/.bin/playwright",
      "test",
      "tests/e2e/test-gate.spec.ts"
    ],
    "configFile": "/home/runner/work/dr-card-web/dr-card-web/playwright.config.ts",
    "rootDir": "/home/runner/work/dr-card-web/dr-card-web/tests/e2e",
    "failOnFlakyTests": false,
    "forbidOnly": true,
    "fullyParallel": true,
    "globalSetup": null,
    "globalTeardown": null,
    "globalTimeout": 0,
    "grep": {},
    "grepInvert": null,
    "maxFailures": 0,
    "metadata": {
      "ci": {
        "commitHref": "https://github.com/sanchuang-dev/dr-card-web/commit/4cdf6445891e2365ebb0861cd41f4b083bdb1047",
        "commitHash": "4cdf6445891e2365ebb0861cd41f4b083bdb1047",
        "prHref": "https://github.com/sanchuang-dev/dr-card-web/pull/282",
        "prTitle": "promote(dev->test): mall iframe first-entry initialization fix",
        "prBaseHash": "38ec3ea6820510e4ff94aa3bb6f6fd424de98e0f",
        "buildHref": "https://github.com/sanchuang-dev/dr-card-web/actions/runs/41620615317"
      },
      "gitCommit": {
        "shortHash": "4cdf644",
        "hash": "4cdf6445891e2365ebb0861cd41f4b083bdb1047",
        "subject": "Merge 13adfe9e66f1cf113f6d1a29b1bbdd4984684445 into 38ec3ea6820510e4ff94aa3bb6f6fd424de98e0f",
        "body": "Merge 13adfe9e66f1cf113f6d1a29b1bbdd4984684445 into 38ec3ea6820510e4ff94aa3bb6f6fd424de98e0f\n",
        "author": {
          "name": "SINGING-AKIBA",
          "email": "980325684@qq.com",
          "time": 1793702158000
        },
        "committer": {
          "name": "GitHub",
          "email": "noreply@github.com",
          "time": 1793702158000
        },
        "branch": "HEAD"
      },
      "gitDiff": "diff --git a/src/layouts/MobileLayout.notifications.test.tsx b/src/layouts/MobileLayout.notifications.test.tsx\nindex 7078b49..bc3f995 100644\n--- a/src/layouts/MobileLayout.notifications.test.tsx\n+++ b/src/layouts/MobileLayout.notifications.test.tsx\n@@ -42,6 +42,7 @@ function showShell(initialPath: string) {\n         { path: 'points', element: <p>泡泡值</p> },\n         { path: 'dearseed', element: <p>诗得丽</p> },\n         { path: 'notifications', element: <p>消息列表</p> },\n+        { path: 'mall', element: <p>商城路由 Outlet 不应重复渲染</p> },\n       ],\n     },\n   ], { initialEntries: [initialPath] })\n@@ -77,3 +78,31 @@ describe('member-center unread badge lifecycle', () => {\n     expect(mocks.refresh).toHaveBeenCalledTimes(2)\n   })\n })\n+\n+\n+describe('mall iframe lifecycle', () => {\n+  it('does not mount the mall before first entry and reuses the iframe after leaving the tab', async () => {\n+    const router = showShell('/')\n+    expect(screen.queryByTitle('卡博士商城')).toBeNull()\n+\n+    await act(async () => { await router.navigate('/mall') })\n+    const iframe = screen.getByTitle('卡博士商城')\n+    const mallShell = iframe.closest('[data-mall-shell]')\n+    expect(mallShell).not.toBeNull()\n+    expect(mallShell?.classList.contains('invisible')).toBe(false)\n+\n+    await act(async () => { await router.navigate('/points') })\n+    expect(screen.getByTitle('卡博士商城')).toBe(iframe)\n+    expect(mallShell?.classList.contains('invisible')).toBe(true)\n+    expect(mallShell?.classList.contains('pointer-events-none')).toBe(true)\n+\n+    await act(async () => { await router.navigate('/mall') })\n+    expect(screen.getByTitle('卡博士商城')).toBe(iframe)\n+    expect(mallShell?.classList.contains('invisible')).toBe(false)\n+  })\n+\n+  it('mounts the mall immediately when /mall is the initial route', () => {\n+    showShell('/mall')\n+    expect(screen.getByTitle('卡博士商城')).toBeTruthy()\n+  })\n+})\ndiff --git a/src/layouts/MobileLayout.tsx b/src/layouts/MobileLayout.tsx\nindex 0b048ff..8c0b6f2 100644\n--- a/src/layouts/MobileLayout.tsx\n+++ b/src/layouts/MobileLayout.tsx\n@@ -123,6 +123,8 @@ export default function MobileLayout() {\n   const { open: openOverlay } = useOverlay()\n   const [authExpired, setAuthExpired] = useState(false)\n   const [backFeedback, setBackFeedback] = useState<string | null>(null)\n+  // Do not initialize the cross-origin mall until the user first enters its tab.\n+  const [mallActivated, setMallActivated] = useState(() => location.pathname === '/mall')\n   const authExpiredHandledRef = useRef(false)\n   const showLegacyNav = isLegacyTabPath(location.pathname)\n   const showNav = showLegacyNav || isFormalH5TabPath(location.pathname)\n@@ -191,6 +193,10 @@ export default function MobileLayout() {\n     previousShellPathname.current = location.pathname\n   }, [location.pathname])\n \n+  useLayoutEffect(() => {\n+    if (location.pathname === '/mall') setMallActivated(true)\n+  }, [location.pathname])\n+\n   if (fixtureRedirect) {\n     return <Navigate to={fixtureRedirect.to} replace state={fixtureRedirect.state} />\n   }\n@@ -309,14 +315,21 @@ export default function MobileLayout() {\n             <H5ScrollRestoration previousPathname={scrollSourcePathname} />\n           )}\n           <H5RouteOutlet />\n-          {/* Keep the iframe alive across tab changes; only hide its wrapper when another route is active. */}\n-          <div\n-            className={location.pathname === '/mall' ? 'absolute inset-0 z-10 bg-background' : 'hidden'}\n-            data-h5-route-active={location.pathname === '/mall' ? 'true' : 'false'}\n-            aria-hidden={location.pathname !== '/mall'}\n-          >\n-            <MallWebView />\n-          </div>\n+          {/* Mount on first entry while visible, then preserve the iframe's layout viewport off-tab. */}\n+          {mallActivated && (\n+            <div\n+              className={\n+                location.pathname === '/mall'\n+                  ? 'absolute inset-0 z-10 bg-background'\n+                  : 'invisible pointer-events-none absolute inset-0 z-0'\n+              }\n+              data-mall-shell=\"true\"\n+              data-h5-route-active={location.pathname === '/mall' ? 'true' : 'false'}\n+              aria-hidden={location.pathname !== '/mall'}\n+            >\n+              <MallWebView />\n+            </div>\n+          )}\n         </div>\n         {showNav && <BottomNav variant={showLegacyNav ? 'legacy' : 'main'} />}\n       </div>\ndiff --git a/tests/e2e/formal-h5.spec.ts b/tests/e2e/formal-h5.spec.ts\nindex a17ef8a..1423c32 100644\n--- a/tests/e2e/formal-h5.spec.ts\n+++ b/tests/e2e/formal-h5.spec.ts\n@@ -15,15 +15,16 @@ function routeUrl(path: string) {\n   return path === '/' ? '/?newcomer=off' : path\n }\n \n-async function stubMallIframes(page: Page) {\n+async function stubMallIframes(page: Page, onRequest?: (url: string, resourceType: string) => void) {\n   for (const origin of ['https://kbs-shop.3cgroup.cn', 'https://kbs-shop2.3cgroup.cn']) {\n-    await page.route(`${origin}/**`, (route) =>\n-      route.fulfill({\n+    await page.route(`${origin}/**`, async (route) => {\n+      onRequest?.(route.request().url(), route.request().resourceType())\n+      await route.fulfill({\n         status: 200,\n         contentType: 'text/html',\n         body: '<!doctype html><html><body>商城 E2E stub</body></html>',\n-      }),\n-    )\n+      })\n+    })\n   }\n }\n \n@@ -136,6 +137,49 @@ test('@formal-h5 first-level tab uses CSS fade without root snapshot', async ({\n   expect(runtimeErrors, runtimeErrors.join('\\n')).toEqual([])\n })\n \n+test('@formal-h5 mall iframe mounts on first entry and is reused across tab changes', async ({ page }) => {\n+  const runtimeErrors = collectRuntimeErrors(page)\n+  let mallDocumentRequests = 0\n+  await stubMallIframes(page, (url, resourceType) => {\n+    if (resourceType === 'document' && url.startsWith('https://kbs-shop.3cgroup.cn/')) {\n+      mallDocumentRequests += 1\n+    }\n+  })\n+\n+  await page.goto('/?newcomer=off', { waitUntil: 'domcontentloaded' })\n+  await expectHealthyFormalRoute(page)\n+\n+  const mallShell = page.locator('[data-mall-shell]')\n+  const mallIframe = page.locator('iframe[title=\"卡博士商城\"]')\n+  await expect(mallIframe).toHaveCount(0)\n+  expect(mallDocumentRequests).toBe(0)\n+\n+  await page.getByRole('button', { name: '商城' }).click()\n+  await expect.poll(() => new URL(page.url()).pathname).toBe('/mall')\n+  await expect(mallShell).toBeVisible()\n+  await expect(mallIframe).toHaveCount(1)\n+  await expect.poll(() => mallDocumentRequests).toBe(1)\n+\n+  const firstLayout = await mallShell.boundingBox()\n+  expect(firstLayout?.width ?? 0).toBeGreaterThan(0)\n+  expect(firstLayout?.height ?? 0).toBeGreaterThan(0)\n+  await mallIframe.evaluate((node) => node.setAttribute('data-e2e-instance', 'first'))\n+\n+  await page.getByRole('button', { name: '首页' }).click()\n+  await expect.poll(() => new URL(page.url()).pathname).toBe('/')\n+  await expect(mallShell).toBeHidden()\n+  await expect(mallShell).toHaveClass(/pointer-events-none/)\n+  await expect(mallIframe).toHaveCount(1)\n+\n+  await page.getByRole('button', { name: '商城' }).click()\n+  await expect.poll(() => new URL(page.url()).pathname).toBe('/mall')\n+  await expect(mallShell).toBeVisible()\n+  await expect(mallIframe).toHaveAttribute('data-e2e-instance', 'first')\n+  expect(mallDocumentRequests).toBe(1)\n+\n+  expect(runtimeErrors, runtimeErrors.join('\\n')).toEqual([])\n+})\n+\n test('@formal-h5 @business profile notification navigation remains inside formal H5', async ({ page }) => {\n   const runtimeErrors = collectRuntimeErrors(page)",
      "actualWorkers": 2
    },
    "preserveOutput": "always",
    "projects": [
      {
        "outputDir": "/home/runner/work/dr-card-web/dr-card-web/test-results/artifacts",
        "repeatEach": 1,
        "retries": 1,
        "metadata": {
          "ci": {
            "commitHref": "https://github.com/sanchuang-dev/dr-card-web/commit/4cdf6445891e2365ebb0861cd41f4b083bdb1047",
            "commitHash": "4cdf6445891e2365ebb0861cd41f4b083bdb1047",
            "prHref": "https://github.com/sanchuang-dev/dr-card-web/pull/282",
            "prTitle": "promote(dev->test): mall iframe first-entry initialization fix",
            "prBaseHash": "38ec3ea6820510e4ff94aa3bb6f6fd424de98e0f",
            "buildHref": "https://github.com/sanchuang-dev/dr-card-web/actions/runs/41620615317"
          },
          "gitCommit": {
            "shortHash": "4cdf644",
            "hash": "4cdf6445891e2365ebb0861cd41f4b083bdb1047",
            "subject": "Merge 13adfe9e66f1cf113f6d1a29b1bbdd4984684445 into 38ec3ea6820510e4ff94aa3bb6f6fd424de98e0f",
            "body": "Merge 13adfe9e66f1cf113f6d1a29b1bbdd4984684445 into 38ec3ea6820510e4ff94aa3bb6f6fd424de98e0f\n",
            "author": {
              "name": "SINGING-AKIBA",
              "email": "980325684@qq.com",
              "time": 1793702158000
            },
            "committer": {
              "name": "GitHub",
              "email": "noreply@github.com",
              "time": 1793702158000
            },
            "branch": "HEAD"
          },
          "gitDiff": "diff --git a/src/layouts/MobileLayout.notifications.test.tsx b/src/layouts/MobileLayout.notifications.test.tsx\nindex 7078b49..bc3f995 100644\n--- a/src/layouts/MobileLayout.notifications.test.tsx\n+++ b/src/layouts/MobileLayout.notifications.test.tsx\n@@ -42,6 +42,7 @@ function showShell(initialPath: string) {\n         { path: 'points', element: <p>泡泡值</p> },\n         { path: 'dearseed', element: <p>诗得丽</p> },\n         { path: 'notifications', element: <p>消息列表</p> },\n+        { path: 'mall', element: <p>商城路由 Outlet 不应重复渲染</p> },\n       ],\n     },\n   ], { initialEntries: [initialPath] })\n@@ -77,3 +78,31 @@ describe('member-center unread badge lifecycle', () => {\n     expect(mocks.refresh).toHaveBeenCalledTimes(2)\n   })\n })\n+\n+\n+describe('mall iframe lifecycle', () => {\n+  it('does not mount the mall before first entry and reuses the iframe after leaving the tab', async () => {\n+    const router = showShell('/')\n+    expect(screen.queryByTitle('卡博士商城')).toBeNull()\n+\n+    await act(async () => { await router.navigate('/mall') })\n+    const iframe = screen.getByTitle('卡博士商城')\n+    const mallShell = iframe.closest('[data-mall-shell]')\n+    expect(mallShell).not.toBeNull()\n+    expect(mallShell?.classList.contains('invisible')).toBe(false)\n+\n+    await act(async () => { await router.navigate('/points') })\n+    expect(screen.getByTitle('卡博士商城')).toBe(iframe)\n+    expect(mallShell?.classList.contains('invisible')).toBe(true)\n+    expect(mallShell?.classList.contains('pointer-events-none')).toBe(true)\n+\n+    await act(async () => { await router.navigate('/mall') })\n+    expect(screen.getByTitle('卡博士商城')).toBe(iframe)\n+    expect(mallShell?.classList.contains('invisible')).toBe(false)\n+  })\n+\n+  it('mounts the mall immediately when /mall is the initial route', () => {\n+    showShell('/mall')\n+    expect(screen.getByTitle('卡博士商城')).toBeTruthy()\n+  })\n+})\ndiff --git a/src/layouts/MobileLayout.tsx b/src/layouts/MobileLayout.tsx\nindex 0b048ff..8c0b6f2 100644\n--- a/src/layouts/MobileLayout.tsx\n+++ b/src/layouts/MobileLayout.tsx\n@@ -123,6 +123,8 @@ export default function MobileLayout() {\n   const { open: openOverlay } = useOverlay()\n   const [authExpired, setAuthExpired] = useState(false)\n   const [backFeedback, setBackFeedback] = useState<string | null>(null)\n+  // Do not initialize the cross-origin mall until the user first enters its tab.\n+  const [mallActivated, setMallActivated] = useState(() => location.pathname === '/mall')\n   const authExpiredHandledRef = useRef(false)\n   const showLegacyNav = isLegacyTabPath(location.pathname)\n   const showNav = showLegacyNav || isFormalH5TabPath(location.pathname)\n@@ -191,6 +193,10 @@ export default function MobileLayout() {\n     previousShellPathname.current = location.pathname\n   }, [location.pathname])\n \n+  useLayoutEffect(() => {\n+    if (location.pathname === '/mall') setMallActivated(true)\n+  }, [location.pathname])\n+\n   if (fixtureRedirect) {\n     return <Navigate to={fixtureRedirect.to} replace state={fixtureRedirect.state} />\n   }\n@@ -309,14 +315,21 @@ export default function MobileLayout() {\n             <H5ScrollRestoration previousPathname={scrollSourcePathname} />\n           )}\n           <H5RouteOutlet />\n-          {/* Keep the iframe alive across tab changes; only hide its wrapper when another route is active. */}\n-          <div\n-            className={location.pathname === '/mall' ? 'absolute inset-0 z-10 bg-background' : 'hidden'}\n-            data-h5-route-active={location.pathname === '/mall' ? 'true' : 'false'}\n-            aria-hidden={location.pathname !== '/mall'}\n-          >\n-            <MallWebView />\n-          </div>\n+          {/* Mount on first entry while visible, then preserve the iframe's layout viewport off-tab. */}\n+          {mallActivated && (\n+            <div\n+              className={\n+                location.pathname === '/mall'\n+                  ? 'absolute inset-0 z-10 bg-background'\n+                  : 'invisible pointer-events-none absolute inset-0 z-0'\n+              }\n+              data-mall-shell=\"true\"\n+              data-h5-route-active={location.pathname === '/mall' ? 'true' : 'false'}\n+              aria-hidden={location.pathname !== '/mall'}\n+            >\n+              <MallWebView />\n+            </div>\n+          )}\n         </div>\n         {showNav && <BottomNav variant={showLegacyNav ? 'legacy' : 'main'} />}\n       </div>\ndiff --git a/tests/e2e/formal-h5.spec.ts b/tests/e2e/formal-h5.spec.ts\nindex a17ef8a..1423c32 100644\n--- a/tests/e2e/formal-h5.spec.ts\n+++ b/tests/e2e/formal-h5.spec.ts\n@@ -15,15 +15,16 @@ function routeUrl(path: string) {\n   return path === '/' ? '/?newcomer=off' : path\n }\n \n-async function stubMallIframes(page: Page) {\n+async function stubMallIframes(page: Page, onRequest?: (url: string, resourceType: string) => void) {\n   for (const origin of ['https://kbs-shop.3cgroup.cn', 'https://kbs-shop2.3cgroup.cn']) {\n-    await page.route(`${origin}/**`, (route) =>\n-      route.fulfill({\n+    await page.route(`${origin}/**`, async (route) => {\n+      onRequest?.(route.request().url(), route.request().resourceType())\n+      await route.fulfill({\n         status: 200,\n         contentType: 'text/html',\n         body: '<!doctype html><html><body>商城 E2E stub</body></html>',\n-      }),\n-    )\n+      })\n+    })\n   }\n }\n \n@@ -136,6 +137,49 @@ test('@formal-h5 first-level tab uses CSS fade without root snapshot', async ({\n   expect(runtimeErrors, runtimeErrors.join('\\n')).toEqual([])\n })\n \n+test('@formal-h5 mall iframe mounts on first entry and is reused across tab changes', async ({ page }) => {\n+  const runtimeErrors = collectRuntimeErrors(page)\n+  let mallDocumentRequests = 0\n+  await stubMallIframes(page, (url, resourceType) => {\n+    if (resourceType === 'document' && url.startsWith('https://kbs-shop.3cgroup.cn/')) {\n+      mallDocumentRequests += 1\n+    }\n+  })\n+\n+  await page.goto('/?newcomer=off', { waitUntil: 'domcontentloaded' })\n+  await expectHealthyFormalRoute(page)\n+\n+  const mallShell = page.locator('[data-mall-shell]')\n+  const mallIframe = page.locator('iframe[title=\"卡博士商城\"]')\n+  await expect(mallIframe).toHaveCount(0)\n+  expect(mallDocumentRequests).toBe(0)\n+\n+  await page.getByRole('button', { name: '商城' }).click()\n+  await expect.poll(() => new URL(page.url()).pathname).toBe('/mall')\n+  await expect(mallShell).toBeVisible()\n+  await expect(mallIframe).toHaveCount(1)\n+  await expect.poll(() => mallDocumentRequests).toBe(1)\n+\n+  const firstLayout = await mallShell.boundingBox()\n+  expect(firstLayout?.width ?? 0).toBeGreaterThan(0)\n+  expect(firstLayout?.height ?? 0).toBeGreaterThan(0)\n+  await mallIframe.evaluate((node) => node.setAttribute('data-e2e-instance', 'first'))\n+\n+  await page.getByRole('button', { name: '首页' }).click()\n+  await expect.poll(() => new URL(page.url()).pathname).toBe('/')\n+  await expect(mallShell).toBeHidden()\n+  await expect(mallShell).toHaveClass(/pointer-events-none/)\n+  await expect(mallIframe).toHaveCount(1)\n+\n+  await page.getByRole('button', { name: '商城' }).click()\n+  await expect.poll(() => new URL(page.url()).pathname).toBe('/mall')\n+  await expect(mallShell).toBeVisible()\n+  await expect(mallIframe).toHaveAttribute('data-e2e-instance', 'first')\n+  expect(mallDocumentRequests).toBe(1)\n+\n+  expect(runtimeErrors, runtimeErrors.join('\\n')).toEqual([])\n+})\n+\n test('@formal-h5 @business profile notification navigation remains inside formal H5', async ({ page }) => {\n   const runtimeErrors = collectRuntimeErrors(page)",
          "actualWorkers": 2
        },
        "id": "chromium-mobile",
        "name": "chromium-mobile",
        "testDir": "/home/runner/work/dr-card-web/dr-card-web/tests/e2e",
        "testIgnore": [],
        "testMatch": [
          "**/*.@(spec|test).?(c|m)[jt]s?(x)"
        ],
        "timeout": 30000
      }
    ],
    "quiet": false,
    "reporter": [
      [
        "line",
        null
      ],
      [
        "html",
        {
          "outputFolder": "playwright-report",
          "open": "never"
        }
      ],
      [
        "json",
        {
          "outputFile": "test-results/playwright-results.json"
        }
      ]
    ],
    "reportSlowTests": {
      "max": 5,
      "threshold": 300000
    },
    "shard": null,
    "tags": [],
    "updateSnapshots": "missing",
    "updateSourceMethod": "patch",
    "version": "1.63.0",
    "workers": 2,
    "webServer": null
  },
  "suites": [
    {
      "title": "test-gate.spec.ts",
      "file": "test-gate.spec.ts",
      "column": 0,
      "line": 0,
      "specs": [
        {
          "title": "@test-gate build identity matches the production-like test policy",
          "ok": true,
          "tags": [
            "test-gate"
          ],
          "tests": [
            {
              "timeout": 30000,
              "annotations": [],
              "expectedStatus": "passed",
              "projectId": "chromium-mobile",
              "projectName": "chromium-mobile",
              "results": [
                {
                  "workerIndex": 0,
                  "parallelIndex": 0,
                  "status": "passed",
                  "duration": 35,
                  "errors": [],
                  "stdout": [],
                  "stderr": [],
                  "retry": 0,
                  "startTime": "2026-11-03T10:36:48.778Z",
                  "annotations": [],
                  "attachments": []
                }
              ],
              "status": "expected"
            }
          ],
          "id": "37c772ca39f4c8e5dd7a-c3b6e0ce5d8c5d8734e5",
          "file": "test-gate.spec.ts",
          "line": 31,
          "column": 1
        },
        {
          "title": "@test-gate browser entry does not start the app router",
          "ok": true,
          "tags": [
            "test-gate"
          ],
          "tests": [
            {
              "timeout": 30000,
              "annotations": [],
              "expectedStatus": "passed",
              "projectId": "chromium-mobile",
              "projectName": "chromium-mobile",
              "results": [
                {
                  "workerIndex": 1,
                  "parallelIndex": 1,
                  "status": "passed",
                  "duration": 758,
                  "errors": [],
                  "stdout": [],
                  "stderr": [],
                  "retry": 0,
                  "startTime": "2026-11-03T10:36:48.780Z",
                  "annotations": [],
                  "attachments": []
                }
              ],
              "status": "expected"
            }
          ],
          "id": "37c772ca39f4c8e5dd7a-8ed37c8041402a2a6b34",
          "file": "test-gate.spec.ts",
          "line": 40,
          "column": 1
        },
        {
          "title": "@test-gate / shows the unsupported-host notice in a browser",
          "ok": true,
          "tags": [
            "test-gate"
          ],
          "tests": [
            {
              "timeout": 30000,
              "annotations": [],
              "expectedStatus": "passed",
              "projectId": "chromium-mobile",
              "projectName": "chromium-mobile",
              "results": [
                {
                  "workerIndex": 0,
                  "parallelIndex": 0,
                  "status": "passed",
                  "duration": 779,
                  "errors": [],
                  "stdout": [],
                  "stderr": [],
                  "retry": 0,
                  "startTime": "2026-11-03T10:36:48.848Z",
                  "annotations": [],
                  "attachments": []
                }
              ],
              "status": "expected"
            }
          ],
          "id": "37c772ca39f4c8e5dd7a-b030d57053896c93a550",
          "file": "test-gate.spec.ts",
          "line": 51,
          "column": 3
        },
        {
          "title": "@test-gate /profile shows the unsupported-host notice in a browser",
          "ok": true,
          "tags": [
            "test-gate"
          ],
          "tests": [
            {
              "timeout": 30000,
              "annotations": [],
              "expectedStatus": "passed",
              "projectId": "chromium-mobile",
              "projectName": "chromium-mobile",
              "results": [
                {
                  "workerIndex": 1,
                  "parallelIndex": 1,
                  "status": "passed",
                  "duration": 719,
                  "errors": [],
                  "stdout": [],
                  "stderr": [],
                  "retry": 0,
                  "startTime": "2026-11-03T10:36:50.727Z",
                  "annotations": [],
                  "attachments": []
                }
              ],
              "status": "expected"
            }
          ],
          "id": "37c772ca39f4c8e5dd7a-8605535a2807e17fcccc",
          "file": "test-gate.spec.ts",
          "line": 51,
          "column": 3
        },
        {
          "title": "@test-gate /settings shows the unsupported-host notice in a browser",
          "ok": true,
          "tags": [
            "test-gate"
          ],
          "tests": [
            {
              "timeout": 30000,
              "annotations": [],
              "expectedStatus": "passed",
              "projectId": "chromium-mobile",
              "projectName": "chromium-mobile",
              "results": [
                {
                  "workerIndex": 0,
                  "parallelIndex": 0,
                  "status": "passed",
                  "duration": 685,
                  "errors": [],
                  "stdout": [],
                  "stderr": [],
                  "retry": 0,
                  "startTime": "2026-11-03T10:36:50.741Z",
                  "annotations": [],
                  "attachments": []
                }
              ],
              "status": "expected"
            }
          ],
          "id": "37c772ca39f4c8e5dd7a-4a2fdc9884c1725de4f8",
          "file": "test-gate.spec.ts",
          "line": 51,
          "column": 3
        },
        {
          "title": "@test-gate gated browser entry issues no business API request",
          "ok": true,
          "tags": [
            "test-gate"
          ],
          "tests": [
            {
              "timeout": 30000,
              "annotations": [],
              "expectedStatus": "passed",
              "projectId": "chromium-mobile",
              "projectName": "chromium-mobile",
              "results": [
                {
                  "workerIndex": 0,
                  "parallelIndex": 0,
                  "status": "passed",
                  "duration": 687,
                  "errors": [],
                  "stdout": [],
                  "stderr": [],
                  "retry": 0,
                  "startTime": "2026-11-03T10:36:51.439Z",
                  "annotations": [],
                  "attachments": []
                }
              ],
              "status": "expected"
            }
          ],
          "id": "37c772ca39f4c8e5dd7a-09f38a2b8ed735e192d8",
          "file": "test-gate.spec.ts",
          "line": 65,
          "column": 1
        },
        {
          "title": "@test-gate injected native host bypasses the notice and starts the app",
          "ok": true,
          "tags": [
            "test-gate"
          ],
          "tests": [
            {
              "timeout": 30000,
              "annotations": [],
              "expectedStatus": "passed",
              "projectId": "chromium-mobile",
              "projectName": "chromium-mobile",
              "results": [
                {
                  "workerIndex": 1,
                  "parallelIndex": 1,
                  "status": "passed",
                  "duration": 725,
                  "errors": [],
                  "stdout": [],
                  "stderr": [],
                  "retry": 0,
                  "startTime": "2026-11-03T10:36:51.465Z",
                  "annotations": [],
                  "attachments": []
                }
              ],
              "status": "expected"
            }
          ],
          "id": "37c772ca39f4c8e5dd7a-8caf237c4d42513fff2f",
          "file": "test-gate.spec.ts",
          "line": 80,
          "column": 1
        }
      ]
    }
  ],
  "errors": [],
  "stats": {
    "startTime": "2026-11-03T10:36:48.077Z",
    "duration": 4157.428,
    "expected": 7,
    "skipped": 0,
    "unexpected": 0,
    "flaky": 0
  }
}