diff --git a/.gitea/workflows/code_check.yml b/.gitea/workflows/code_check.yml index d67cf863..1235d773 100644 --- a/.gitea/workflows/code_check.yml +++ b/.gitea/workflows/code_check.yml @@ -1426,7 +1426,7 @@ jobs: run: | mkdir -p ../reports set +e - pnpm test 2>&1 | tee ../reports/devfront-test.log + pnpm run test:ci 2>&1 | tee ../reports/devfront-test.log test_exit_code=${PIPESTATUS[0]} set -e @@ -1442,7 +1442,7 @@ jobs: echo "1. \`cd devfront\`" echo "2. \`pnpm install -C ../common --no-frozen-lockfile\`" echo "3. \`pnpm exec playwright install --with-deps\`" - echo "4. \`pnpm test\`" + echo "4. \`pnpm run test:ci\`" echo echo "## Log Tail (last 200 lines)" echo '```text' diff --git a/devfront/package.json b/devfront/package.json index 0bfc6129..90c89038 100644 --- a/devfront/package.json +++ b/devfront/package.json @@ -12,6 +12,8 @@ "lint": "biome check .", "preview": "vite preview", "test": "playwright test", + "test:ci": "pnpm test && pnpm run test:refresh-token", + "test:refresh-token": "playwright test --config playwright.refresh-token.config.ts", "test:coverage": "vitest run --coverage --bail 1", "test:unit": "vitest run --bail 1", "test:roles": "playwright test tests/devfront-role-switch-report.spec.ts", diff --git a/devfront/playwright.config.ts b/devfront/playwright.config.ts index cfb1eb55..e6b4dff8 100644 --- a/devfront/playwright.config.ts +++ b/devfront/playwright.config.ts @@ -28,6 +28,7 @@ const baseURL = process.env.PLAYWRIGHT_BASE_URL || "http://127.0.0.1:4174"; */ export default defineConfig({ testDir: "./tests", + testIgnore: ["**/devfront-refresh-token.spec.ts"], /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ diff --git a/devfront/playwright.refresh-token.config.ts b/devfront/playwright.refresh-token.config.ts new file mode 100644 index 00000000..518a5fdd --- /dev/null +++ b/devfront/playwright.refresh-token.config.ts @@ -0,0 +1,52 @@ +import { createRequire } from "node:module"; +import { defineConfig, devices } from "@playwright/test"; + +const require = createRequire(import.meta.url); +const { shouldIncludeWebKit } = + require("../scripts/playwrightHostDeps.cjs") as { + shouldIncludeWebKit: () => boolean; + }; + +const configuredWorkers = process.env.PLAYWRIGHT_WORKERS + ? Number.parseInt(process.env.PLAYWRIGHT_WORKERS, 10) + : 1; +const baseURL = process.env.PLAYWRIGHT_BASE_URL || "http://127.0.0.1:4175"; +const skipWebServer = + process.env.PLAYWRIGHT_SKIP_WEBSERVER === "1" || + process.env.PLAYWRIGHT_SKIP_WEBSERVER === "true"; + +export default defineConfig({ + testDir: "./tests", + testMatch: ["**/devfront-refresh-token.spec.ts"], + fullyParallel: false, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: configuredWorkers, + reporter: [["html", { open: "never" }], ["list"]], + use: { + baseURL, + trace: "on-first-retry", + }, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ...(shouldIncludeWebKit() + ? [ + { + name: "webkit", + use: { ...devices["Desktop Safari"] }, + }, + ] + : []), + ], + webServer: skipWebServer + ? undefined + : { + command: + "VITE_OIDC_AUTHORITY=http://localhost:5000/oidc ./node_modules/.bin/vite build && ./node_modules/.bin/vite preview --host 127.0.0.1 --strictPort --port 4175", + url: baseURL, + reuseExistingServer: false, + }, +}); diff --git a/devfront/src/components/layout/AppLayout.test.tsx b/devfront/src/components/layout/AppLayout.test.tsx index 563ffa94..913b70a2 100644 --- a/devfront/src/components/layout/AppLayout.test.tsx +++ b/devfront/src/components/layout/AppLayout.test.tsx @@ -1,7 +1,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { act } from "react"; +import { act, useEffect } from "react"; import { createRoot, type Root } from "react-dom/client"; -import { MemoryRouter, Route, Routes } from "react-router-dom"; +import { MemoryRouter, Route, Routes, useNavigate } from "react-router-dom"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import AppLayout from "./AppLayout"; @@ -49,6 +49,24 @@ vi.mock("../../lib/i18n", () => ({ const roots: Root[] = []; +type TestWindow = Window & { + __baronNavigate?: (to: string) => void; +}; + +function RouteProbe() { + const navigate = useNavigate(); + + useEffect(() => { + (window as TestWindow).__baronNavigate = navigate; + + return () => { + delete (window as TestWindow).__baronNavigate; + }; + }, [navigate]); + + return