Skip to content

Commit 8efd6ec

Browse files
committed
test(saas-demo): Playwright smoke test for golden path
Adds a CI-safe Playwright smoke test that verifies the banking showcase boots and the CopilotKit v2 popup opens with its configured suggestion pills, without invoking the agent (so it runs in CI without secrets). Covers: - Document title shows the Northwind Finance brand - Credit-cards dashboard renders ("Credit Cards" heading) - CopilotPopup launcher opens the dialog (Northwind Copilot) - Three suggestion pills render: View transactions, Add a card, Assign a policy The dev server gets a dummy OPENAI_API_KEY so the runtime route boots, but the test never sends a chat message or clicks a suggestion. .gitignore: ignore test-results/, playwright-report/, and tsconfig.tsbuildinfo so they don't become clutter.
1 parent 77c96ac commit 8efd6ec

3 files changed

Lines changed: 134 additions & 0 deletions

File tree

examples/showcases/banking/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,11 @@ node_modules/
55
.DS_Store
66

77
.next
8+
9+
# TypeScript incremental build cache
10+
tsconfig.tsbuildinfo
11+
12+
# Playwright
13+
test-results/
14+
playwright-report/
15+
playwright/.cache/
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { test, expect } from "@playwright/test";
2+
import type { ConsoleMessage, Page } from "@playwright/test";
3+
4+
/**
5+
* CI-safe smoke test for the Northwind banking showcase.
6+
*
7+
* What this covers:
8+
* 1. App boots and the dashboard renders credible content (brand + cards UI).
9+
* 2. The CopilotKit v2 popup launcher opens the modal.
10+
* 3. The three configured suggestion pills are visible.
11+
*
12+
* What this intentionally does NOT do:
13+
* - Send any chat message
14+
* - Click any suggestion (which would invoke the agent / hit OpenAI)
15+
* - Exercise any tool
16+
*
17+
* That keeps the test runnable in CI without secrets.
18+
*/
19+
20+
// Console-error filtering: the page may legitimately log network errors for
21+
// the /api/copilotkit endpoint (e.g. if the popup pings it on open and the
22+
// runtime fails because OPENAI_API_KEY is a dummy value), and Next.js dev mode
23+
// prints various non-fatal warnings. We only fail on genuine page/script
24+
// errors that indicate the app itself is broken.
25+
const IGNORED_ERROR_PATTERNS: RegExp[] = [
26+
/favicon/i,
27+
/\/api\/copilotkit/i,
28+
/Failed to load resource/i,
29+
/net::ERR_/i,
30+
/Download the React DevTools/i,
31+
/Hydration/i, // Next.js dev-only hydration warnings are out of scope
32+
];
33+
34+
function isIgnoredError(message: ConsoleMessage): boolean {
35+
if (message.type() !== "error") return true;
36+
const text = message.text();
37+
return IGNORED_ERROR_PATTERNS.some((re) => re.test(text));
38+
}
39+
40+
function collectConsoleErrors(page: Page): string[] {
41+
const errors: string[] = [];
42+
page.on("console", (msg) => {
43+
if (msg.type() === "error" && !isIgnoredError(msg)) {
44+
errors.push(msg.text());
45+
}
46+
});
47+
return errors;
48+
}
49+
50+
test.describe("banking showcase smoke", () => {
51+
test("dashboard renders and popup opens with suggestions", async ({
52+
page,
53+
}) => {
54+
const consoleErrors = collectConsoleErrors(page);
55+
56+
await page.goto("/");
57+
58+
// Brand assertion: the document title is the Northwind Finance brand.
59+
await expect(page).toHaveTitle(/Northwind/);
60+
61+
// The credit-cards page renders an h1 "Credit Cards" and an "Add Card"
62+
// dropdown — that's our credible-content check that the dashboard is up.
63+
await expect(
64+
page.getByRole("heading", { name: "Credit Cards", level: 1 }),
65+
).toBeVisible();
66+
67+
// Open the CopilotKit popup. v2 renders a fixed launcher button with
68+
// data-testid="copilot-chat-toggle" (see CopilotChatToggleButton.tsx).
69+
const launcher = page.getByTestId("copilot-chat-toggle");
70+
await expect(launcher).toBeVisible();
71+
await launcher.click();
72+
73+
// The popup modal exposes the configured assistant title as its aria-label
74+
// (modalHeaderTitle = IDENTITY.assistant = "Northwind Copilot"). We assert
75+
// on the dialog rather than visible text since the title may be rendered
76+
// as aria-only.
77+
await expect(
78+
page.getByRole("dialog", { name: /Northwind Copilot/i }),
79+
).toBeVisible();
80+
81+
// The three suggestion pills configured by BankingSuggestions render as
82+
// buttons with data-testid="copilot-suggestion" (see
83+
// CopilotChatSuggestionPill.tsx). Their labels are the suggestion titles.
84+
const suggestions = page.getByTestId("copilot-suggestion");
85+
await expect(suggestions).toHaveCount(3);
86+
await expect(
87+
suggestions.filter({ hasText: "View transactions" }),
88+
).toBeVisible();
89+
await expect(suggestions.filter({ hasText: "Add a card" })).toBeVisible();
90+
await expect(
91+
suggestions.filter({ hasText: "Assign a policy" }),
92+
).toBeVisible();
93+
94+
// Make sure nothing genuinely broken showed up in the console while the
95+
// page rendered and the popup opened.
96+
expect(
97+
consoleErrors,
98+
`Unexpected console errors:\n${consoleErrors.join("\n")}`,
99+
).toEqual([]);
100+
});
101+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { defineConfig } from "@playwright/test";
2+
3+
export default defineConfig({
4+
testDir: "./e2e",
5+
fullyParallel: true,
6+
forbidOnly: !!process.env.CI,
7+
retries: process.env.CI ? 2 : 0,
8+
reporter: "list",
9+
use: { baseURL: "http://localhost:3000", trace: "on-first-retry" },
10+
webServer: {
11+
command: "pnpm dev",
12+
url: "http://localhost:3000",
13+
reuseExistingServer: !process.env.CI,
14+
timeout: 120_000,
15+
env: {
16+
// The runtime route imports BuiltInAgent which requires OPENAI_API_KEY at
17+
// module load. The smoke test never invokes the agent — it only checks
18+
// that the page renders and the popup opens — but the dev server needs
19+
// *some* value here to boot the API route without crashing. Tests must
20+
// remain LLM-free; we only set this so the Next.js server starts.
21+
OPENAI_API_KEY: process.env.OPENAI_API_KEY ?? "test",
22+
NEXT_TELEMETRY_DISABLED: "1",
23+
},
24+
},
25+
});

0 commit comments

Comments
 (0)