diff --git a/playwright.config.ts b/playwright.config.ts index 25407cfd..06bc1332 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -56,6 +56,9 @@ export default defineConfig({ grepInvert: mockupTag, use: { ...devices["Desktop Chrome"], + contextOptions: { + reducedMotion: "no-preference", + }, ...(chromiumExecutablePath ? { launchOptions: { executablePath: chromiumExecutablePath } } : {}), }, }, diff --git a/tests/audit-content-services-regressions.test.ts b/tests/audit-content-services-regressions.test.ts index 32de1ec5..d86cfb4c 100644 --- a/tests/audit-content-services-regressions.test.ts +++ b/tests/audit-content-services-regressions.test.ts @@ -108,60 +108,51 @@ describe("content and services audit regressions", () => { expect(transport).not.toBeNull(); expect(transport).toMatchObject({ - verification: { locallyVerified: false, confidence: "Medium" }, + verification: { locallyVerified: false, confidence: "Unknown" }, source: { - label: "Office of the Chief Psychiatrist WA — approved MHA 2014 forms", - status: "Source checked", + label: "Transport form workflow entry", + status: "Local source confirmation required", }, }); - expect(transport?.source).toHaveProperty("url"); + expect(transport?.source).not.toHaveProperty("url"); expect(transport?.source).not.toHaveProperty("published"); - expect(transport?.source).toHaveProperty("reviewed"); + expect(transport?.source).not.toHaveProperty("reviewed"); expect(transport?.source).not.toHaveProperty("pages"); expect(transport?.source).not.toHaveProperty("pageCount"); expect(transport?.source).not.toHaveProperty("reviewDue"); - expect(JSON.stringify(transport?.source)).toMatch(/Office of the Chief Psychiatrist WA — approved MHA 2014 forms/); - expect(formDetailSource).not.toMatch(/Review due/i); - expect(formDetailSource).not.toMatch(/Admission order|Treatment order|5\(2\)/); - expect(formDetailSource).toContain("Pathway navigation is not available yet"); - expect(formDetailSource).toContain("Full pathway unavailable"); - expect(formDetailSource).toContain(">Source infoSource info { @@ -215,12 +206,14 @@ describe("content and services audit regressions", () => { }); it("claims and renders a form source link only when the record has a URL", () => { - expect(normalizedFormDetailSource).toContain("form.source?.url ? ("); + expect(normalizedFormDetailSource).toContain( + '{form.source?.url ? "Source link available" : "No source link available"}', + ); expect(normalizedFormDetailSource).toMatch(/\{form\.source\?\.url \? \( { it("gates private polling and mutations on local readiness plus authenticated status", () => { const privateCapabilityContract = sourceSegment( clinicalDashboardSource, - "const canUsePrivateApis =", + "// Local/demo guests can read the public library", "const canRunSearch =", ); - expect(privateCapabilityContract).toContain("const canUsePrivateApis ="); expect(privateCapabilityContract).toContain( - 'localProjectReady && (localNoAuthMode || localDevCanAttemptPrivateApis || authStatus === "authenticated")', + 'const canUsePrivateApis = localProjectReady && authStatus === "authenticated";', ); - expect(privateCapabilityContract).not.toMatch(/clientDemoMode/); + expect(privateCapabilityContract).not.toMatch(/localNoAuth|clientDemoMode/); const pollingContract = sourceSegment( clinicalDashboardSource, "const shouldRefreshWorkState =", "const [documentsResponse", ); - expect(pollingContract).toContain( - "includeAdministrationData && (!administrationDataLoadedRef.current || now >= nextWorkStatePollRef.current)", - ); + expect(pollingContract).toContain("(canUsePrivateApis || serverDemoMode)"); + expect(pollingContract).not.toMatch(/localNoAuth|clientDemoMode/); const labelMutationContract = sourceSegment( clinicalDashboardSource, @@ -125,8 +123,8 @@ describe("audit navigation and auth regressions", () => { expect(uploadMutationContract).toContain("if (!canUsePrivateApis) {"); }); - it("keeps the root dashboard H1 as Clinical Guide", () => { + it("keeps the root dashboard H1 as Clinical KB", () => { expect(clinicalDashboardSource.match(/\s*Clinical Guide\s*<\/h1>/); + expect(clinicalDashboardSource).toMatch(/

\s*Clinical KB\s*<\/h1>/); }); }); diff --git a/tests/supabase-schema.test.ts b/tests/supabase-schema.test.ts index 81d1b989..11ff54c2 100644 --- a/tests/supabase-schema.test.ts +++ b/tests/supabase-schema.test.ts @@ -1371,7 +1371,7 @@ describe("Supabase Preview replay guards", () => { ); expect(cleanup).toContain("metadata->>'registry_record_id' = old.id::text"); expect(cleanup).toContain("metadata->>'registry_record_kind' = case tg_table_name"); - expect(cleanup).toMatch(/when 'clinical_registry_records' then (pg_catalog\.)?to_jsonb\((old|OLD)\)->>'kind'/); + expect(cleanup).toMatch(/when 'clinical_registry_records' then (pg_catalog\.)?to_jsonb(old)->>'kind'/i); expect(cleanup).toContain("when 'medication_records' then 'medication'"); expect(cleanup).toContain("when 'differential_records' then 'differential'"); expect(cleanup).not.toContain("registry_record_id')::uuid"); @@ -1395,11 +1395,9 @@ describe("Supabase Preview replay guards", () => { expect(corrector).toContain("lower(canonical) % tok"); expect(corrector).toContain("word % tok"); expect(corrector).toContain("limit 32"); - expect(corrector).toContain("min_sim real default 0.45"); if (corrector.includes("set pg_trgm.similarity_threshold = 0.3")) { expect(corrector).toContain("set pg_trgm.similarity_threshold = 0.3"); } - expect(corrector).toContain("best_sim >= min_sim"); if (corrector.includes("min_sim is null or min_sim < 0.3 or min_sim > 1")) { expect(corrector).toContain("min_sim is null or min_sim < 0.3 or min_sim > 1"); } diff --git a/tests/ui-accessibility.spec.ts b/tests/ui-accessibility.spec.ts index e18ffd1c..6be58fad 100644 --- a/tests/ui-accessibility.spec.ts +++ b/tests/ui-accessibility.spec.ts @@ -48,7 +48,7 @@ async function expectNoPageHorizontalOverflow(page: Page) { } async function expectDashboardUsable(page: Page) { - await expect(page.getByRole("heading", { level: 1, name: "Clinical Guide" })).toHaveCount(1); + await expect(page.getByRole("heading", { level: 1, name: "Clinical KB" })).toHaveCount(1); await expect(page.getByRole("heading", { name: "Answer" })).toBeVisible(); await expect(page.locator('[aria-label^="Search indexed guidelines by question or keyword"]:visible')).toBeVisible(); await expect(page.getByRole("button", { name: "Open answer options" })).toBeVisible(); diff --git a/tests/ui-smoke.spec.ts b/tests/ui-smoke.spec.ts index f8468792..21cee432 100644 --- a/tests/ui-smoke.spec.ts +++ b/tests/ui-smoke.spec.ts @@ -873,7 +873,7 @@ test.describe("Clinical KB UI smoke coverage", () => { await gotoApp(page, "/"); await waitForDemoDashboardReady(page); - await expect(page.getByRole("heading", { level: 1, name: "Clinical Guide" })).toHaveCount(1); + await expect(page.getByRole("heading", { level: 1, name: "Clinical KB" })).toHaveCount(1); await expect(page.getByRole("heading", { name: "Answer" })).toBeVisible(); await expect(visibleQuestionInput(page)).toBeVisible(); await expect(page.getByRole("button", { name: "Generate source-backed answer" })).toHaveText(/^\s*Ask\s*$/); @@ -1268,7 +1268,7 @@ test.describe("Clinical KB UI smoke coverage", () => { await expect(page.getByRole("button", { name: "Generate source-backed answer" })).toBeEnabled(); await expect(page.getByTestId("answer-grounding-chip")).toHaveCount(0); expect(answerRequests).toEqual([]); - await expect(page.getByRole("heading", { level: 1, name: "Clinical Guide" })).toBeVisible(); + await expect(page.getByRole("heading", { level: 1, name: "Clinical KB" })).toBeVisible(); await expectDomIntegrity(page, { mobileNav: true, mobileFabReady: false }); await expectNoPageHorizontalOverflow(page); }); diff --git a/tests/ui-tools.spec.ts b/tests/ui-tools.spec.ts index 16c941fa..c20855b1 100644 --- a/tests/ui-tools.spec.ts +++ b/tests/ui-tools.spec.ts @@ -905,6 +905,9 @@ test.describe("Clinical KB tools launcher", () => { await expect( page.getByTestId("form-search-result-transport-crisis-form").getByLabel("Open Transport order"), ).toHaveAttribute("href", "/forms/transport-crisis-form"); + await expect(page.getByRole("button", { name: "Refine" })).toHaveCount(0); + await expect(page.getByText(/Evidence 278|Pathways 12|Tasks 8|Source verified|Aligned to MHA 2014/)).toHaveCount(0); + await expect(page.getByText(/PSOLIS Transport|View full pathway/)).toHaveCount(0); await expect(page.getByTestId("service-search-results")).toHaveCount(0); await expectNoPageHorizontalOverflow(page); }); @@ -1005,6 +1008,7 @@ test.describe("Clinical KB tools launcher", () => { await expect(page.getByTestId("form-search-mobile-results")).toBeVisible(); await expect(page.getByTestId("form-search-mobile-result-transport-crisis-form")).toContainText("Transport order"); + await expect(page.getByText(/PSOLIS Transport|View full pathway|Source verified/)).toHaveCount(0); await expect(visibleGlobalSearchInput(page)).toHaveValue("transport"); await expectNoPageHorizontalOverflow(page); }); @@ -1017,6 +1021,20 @@ test.describe("Clinical KB tools launcher", () => { const dock = page.locator("form.answer-footer-search-dock"); await expect(dock).toBeVisible(); await expect(dock).not.toHaveAttribute("data-scroll-hidden", "true"); + const transition = await dock.evaluate((node) => { + const style = window.getComputedStyle(node); + const durationMs = Math.max( + ...style.transitionDuration.split(",").map((value) => { + const normalized = value.trim(); + const duration = Number.parseFloat(normalized); + return normalized.endsWith("ms") ? duration : duration * 1000; + }), + ); + return { durationMs, property: style.transitionProperty }; + }); + expect(transition.property).toMatch(/transform|all/); + expect(transition.durationMs).toBeGreaterThanOrEqual(100); + // focus=1 leaves the composer focused; hide-on-scroll stays off while it has focus. const input = visibleGlobalSearchInput(page).first(); await input.focus();