// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0 // The default Agent and Help integrations over real Postgres and the simulated Cloud protocol. import { expect, type Page, test } from "@playwright/test" import { moduleSelected } from "../modules/inclusion" import { call, makeOrganization, signIn, unique, violations } from "./support/app" test.skip( !["agent", "guides", "support"].every((id) => moduleSelected(id as "agent" | "guides" | "support")), "Assistance was explicitly excluded", ) async function prepare(page: Page) { await signIn(page, `${unique("owner")}@example.test`) const scope = await makeOrganization(page) await page.goto(`/${scope.org}/${scope.workspace}/modules/notes`) // Functional panel checks start after the person resolves privacy choices. // The first-visit consent flow has its own keyboard and accessibility suite. await page.getByRole("button", { name: "Reject analytics and replay", exact: true }).click() await expect(page.getByRole("region", { name: "Privacy choices", exact: true })).toHaveCount(0) return scope } test("Agent streams and persists a marked answer, and keeps a draft when switching panels", async ({ page }, info) => { const errors: string[] = [] page.on("pageerror", (error) => errors.push(error.message)) const scope = await prepare(page) await expect(page.locator("[data-conusai-guide-root]")).toHaveCount(0) await page.getByRole("button", { name: "Agent", exact: true }).click() await expect(page.getByText("Ask the Agent", { exact: true })).toBeVisible() await expect(page.getByText("The Agent is AI and can make mistakes. Check anything important.")).toBeVisible() const input = page.getByRole("textbox", { name: "Message the Agent" }) await input.fill("Explain this workspace") await input.press("Shift+Enter") await input.press("x") await expect(input).toHaveValue("Explain this workspace\nx") await input.press("Enter") const answer = page.getByRole("log").getByText("This is the fake platform: no model is behind it.", { exact: true }) await expect(answer).toBeVisible() await expect .poll(async () => { const list = await call<{ conversations: { conversationId: string }[] }>(page, "assistant.conversation.list", { org: scope.org, workspace: scope.workspace, }) const id = list.conversations[0]?.conversationId if (!id) return null const conversation = await call<{ turns: { status: string; answerProvenance: unknown }[] }>( page, "assistant.conversation.get", { org: scope.org, workspace: scope.workspace, conversationId: id }, ) return conversation.turns.at(-1) }) .toMatchObject({ status: "complete", answerProvenance: { ai_generated: true } }) await expect(input).toBeFocused() await expect(page.locator(".kit-side-panel-head")).toBeInViewport({ ratio: 1 }) expect(await page.evaluate(() => window.scrollY)).toBe(0) await page.screenshot({ path: info.outputPath("agent-desktop.png") }) expect(await violations(page)).toEqual([]) await page.reload() await page.getByRole("button", { name: "Agent", exact: true }).click() await expect(answer).toBeVisible() await input.fill("Keep this draft") await page.getByRole("button", { name: "Full screen", exact: true }).click() const full = page.getByRole("dialog", { name: "Agent", exact: true }) await expect(full).toBeVisible() await expect(full.getByRole("textbox", { name: "Message the Agent" })).toHaveValue("Keep this draft") await expect(answer).toBeVisible() expect(await violations(page)).toEqual([]) await page.screenshot({ path: info.outputPath("agent-fullscreen.png") }) await full.getByRole("button", { name: "Restore panel", exact: true }).click() await expect(full).toBeHidden() await expect(input).toHaveValue("Keep this draft") await page.getByRole("button", { name: "Help", exact: true }).click() await page.getByRole("tab", { name: "Agent", exact: true }).click() await expect(input).toHaveValue("Keep this draft") await input.focus() await page.keyboard.press("Escape") const guard = page.getByRole("alertdialog") await expect(guard).toBeVisible() await guard.getByRole("button", { name: /Keep/ }).click() await expect(input).toHaveValue("Keep this draft") await input.fill("") await page.getByRole("button", { name: "Help", exact: true }).click() await page.getByRole("tab", { name: "Agent", exact: true }).click() await expect(answer).toBeVisible() expect(errors).toEqual([]) }) test("Help runs a requested Notes tour and explains local Support on a phone", async ({ page }, info) => { const scope = await prepare(page) await page.setViewportSize({ width: 375, height: 812 }) await page.goto(`/${scope.org}/${scope.workspace}/${scope.project}/notes`) await expect(page.locator("[data-conusai-guide-root]")).toHaveCount(0) await page.getByRole("button", { name: "Help", exact: true }).click() const panel = page.getByRole("dialog", { name: "Help", exact: true }) await expect(panel.getByText("Get started with notes", { exact: true })).toBeVisible() await panel.getByRole("checkbox", { name: "Tell your team where the notes are" }).check() await expect(panel.getByRole("checkbox", { name: "Tell your team where the notes are" })).toBeChecked() await panel.getByRole("button", { name: "Start guide: Take the notes tour", exact: true }).click() const tour = page.locator("[data-conusai-guide-root]") await expect(tour.getByRole("heading", { name: "Write a note", exact: true })).toBeVisible() await expect(panel).toBeHidden() await page.screenshot({ path: info.outputPath("guides-mobile-tour.png") }) await tour.getByRole("button", { name: "Next", exact: true }).click() await tour.getByRole("button", { name: "Next", exact: true }).click() await tour.getByRole("button", { name: "Done", exact: true }).click() await page.getByRole("button", { name: "Help", exact: true }).click() await panel.getByRole("tab", { name: "Support", exact: true }).click() await expect(panel.getByText("Support is not connected in this local demo", { exact: true })).toBeVisible() await expect(panel.getByRole("button", { name: "Try again" })).toHaveCount(0) await expect(page.locator(".support-launcher")).toHaveCount(0) expect(await violations(page)).toEqual([]) expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true) await page.screenshot({ path: info.outputPath("help-mobile-support.png") }) }) test("Support distinguishes loading, a retryable failure and a permission refusal", async ({ page }, info) => { await prepare(page) let release: (() => void) | undefined const wait = new Promise((resolve) => { release = resolve }) await page.route("**/api/v1/support.widget.config", async (route) => { await wait await route.fulfill({ status: 503, contentType: "application/problem+json", body: JSON.stringify({ status: 503, title: "Unavailable" }), }) }) await page.getByRole("button", { name: "Help", exact: true }).click() const panel = page.locator("[data-slot=side-panel]") await panel.getByRole("tab", { name: "Support", exact: true }).click() await expect(panel.locator("[data-slot=support-loading]")).toBeVisible() await page.screenshot({ path: info.outputPath("support-loading.png") }) release?.() await expect(panel.locator("[data-slot=support-unavailable]")).toBeVisible() await page.unroute("**/api/v1/support.widget.config") await panel.getByRole("button", { name: "Try again", exact: true }).focus() await page.keyboard.press("Enter") await expect(panel.locator("[data-slot=support-offline]")).toBeVisible() await page.route("**/api/v1/support.widget.config", (route) => route.fulfill({ status: 403, contentType: "application/problem+json", body: JSON.stringify({ status: 403, title: "Forbidden" }), }), ) await page.reload() await page.getByRole("button", { name: "Help", exact: true }).click() await panel.getByRole("tab", { name: "Support", exact: true }).click() await expect(panel.locator("[data-slot=support-denied]")).toBeVisible() await expect(panel.getByRole("button", { name: "Try again" })).toHaveCount(0) }) test("navigation keeps the Agent draft and respects reduced motion", async ({ page }) => { const errors: string[] = [] page.on("pageerror", (error) => errors.push(error.message)) const scope = await prepare(page) await page.emulateMedia({ reducedMotion: "no-preference" }) await page.evaluate(() => { const native = document.startViewTransition.bind(document) const proof = window as unknown as { transitions: number; sameDocument: string } proof.transitions = 0 proof.sameDocument = "preserved" document.startViewTransition = ((...args: Parameters) => { proof.transitions += 1 return native(...args) }) as typeof document.startViewTransition }) await page.getByRole("button", { name: "Agent", exact: true }).click() const input = page.getByRole("textbox", { name: "Message the Agent" }) await input.fill("Keep this while navigating") await page.getByRole("link", { name: "Workspace overview", exact: true }).click() await expect(page).toHaveURL(new RegExp(`/${scope.org}/${scope.workspace}$`)) await expect(input).toHaveValue("Keep this while navigating") await expect .poll(() => page.evaluate(() => (window as unknown as { transitions: number }).transitions)) .toBeGreaterThan(0) await page.waitForFunction(() => !document.documentElement.matches(":active-view-transition")) const before = await page.evaluate(() => (window as unknown as { transitions: number }).transitions) await page.emulateMedia({ reducedMotion: "reduce" }) await page.getByRole("link", { name: "Notes in this workspace", exact: true }).click() await expect(page).toHaveURL(new RegExp(`/${scope.org}/${scope.workspace}/modules/notes$`)) await expect(input).toHaveValue("Keep this while navigating") expect(await page.evaluate(() => (window as unknown as { transitions: number }).transitions)).toBe(before) expect(await page.evaluate(() => (window as unknown as { sameDocument: string }).sameDocument)).toBe("preserved") expect(errors).toEqual([]) })