mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 10:08:46 +02:00
Add Playwright assistant regression coverage
This commit is contained in:
113
frontend/e2e/asistente.spec.ts
Normal file
113
frontend/e2e/asistente.spec.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { expect, test, type Page } from "@playwright/test";
|
||||
|
||||
test.setTimeout(150_000);
|
||||
|
||||
async function startFreshAssistant(page: Page) {
|
||||
await page.goto("/login");
|
||||
await page.getByLabel("Username").fill(process.env.ADMIN_USERNAME!);
|
||||
await page.getByLabel("Password").fill(process.env.ADMIN_PASSWORD!);
|
||||
await page.getByRole("button", { name: /sign in/i }).click();
|
||||
await page.waitForURL("/");
|
||||
|
||||
const initialConnect = page.waitForResponse((response) => {
|
||||
if (!response.url().includes("/api/copilotkit") || response.request().method() !== "POST") {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(response.request().postData() ?? "{}").method === "agent/connect";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
await page.goto("/asistente");
|
||||
await expect(page.getByRole("heading", { name: "Asistente" })).toBeVisible();
|
||||
await (await initialConnect).finished();
|
||||
|
||||
const newConversation = page.getByRole("button", { name: "Nueva conversación" });
|
||||
if (await newConversation.isEnabled()) {
|
||||
await newConversation.click();
|
||||
const reconnect = page.waitForResponse((response) => {
|
||||
if (!response.url().includes("/api/copilotkit") || response.request().method() !== "POST") {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(response.request().postData() ?? "{}").method === "agent/connect";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
await page.getByRole("button", { name: "Borrar historial" }).click();
|
||||
await (await reconnect).finished();
|
||||
await expect(
|
||||
page.getByRole("textbox", { name: "Escribe tu pregunta…" }),
|
||||
).toBeEnabled({ timeout: 30_000 });
|
||||
}
|
||||
}
|
||||
|
||||
async function ask(page: Page, question: string, expectedTool: string) {
|
||||
// The BFF response is the exact CopilotKit stream consumed by the browser.
|
||||
// Checking it catches server-side RUN_ERROR events even if the UI changes.
|
||||
const stream = page.waitForResponse(
|
||||
(response) => {
|
||||
if (
|
||||
!response.url().includes("/api/copilotkit") ||
|
||||
response.request().method() !== "POST"
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(response.request().postData() ?? "{}").method === "agent/run";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
);
|
||||
const composer = page.getByRole("textbox", { name: "Escribe tu pregunta…" });
|
||||
await expect(composer).toBeEnabled({ timeout: 30_000 });
|
||||
await composer.fill(question);
|
||||
const sendButton = page.getByTestId("copilot-send-button");
|
||||
await expect(sendButton).toBeEnabled({ timeout: 30_000 });
|
||||
await sendButton.click();
|
||||
await expect(page.getByText(question, { exact: true }).last()).toBeVisible();
|
||||
|
||||
const response = await stream;
|
||||
await response.finished();
|
||||
const events = await response.text();
|
||||
expect(events).not.toContain("RUN_ERROR");
|
||||
expect(events).toContain(expectedTool);
|
||||
|
||||
// The HTTP stream may finish before CopilotKit has committed the tool run
|
||||
// and released its client-side running state. Waiting for the page action
|
||||
// avoids losing the next Enter keypress during that short interval.
|
||||
await expect(page.getByRole("button", { name: "Nueva conversación" })).toBeEnabled({
|
||||
timeout: 30_000,
|
||||
});
|
||||
}
|
||||
|
||||
test("Asistente completes Luna's read-only tool flows", async ({ page }) => {
|
||||
const consoleErrors: string[] = [];
|
||||
page.on("console", (message) => {
|
||||
if (message.type() === "error") consoleErrors.push(message.text());
|
||||
});
|
||||
|
||||
await startFreshAssistant(page);
|
||||
|
||||
await ask(page, "What date is it today?", "get_current_date");
|
||||
await ask(page, "List my last 10 transactions.", "get_recent_transactions");
|
||||
await ask(page, "What is my net worth?", "get_net_worth");
|
||||
await ask(page, "How much did I spend today?", "get_daily_spending");
|
||||
await ask(page, "Show my spending by category this month.", "render_spending_summary");
|
||||
|
||||
const spendingCard = page.getByTestId("spending-summary-card");
|
||||
await expect(spendingCard).toBeVisible({ timeout: 30_000 });
|
||||
await expect(page.getByRole("textbox", { name: "Escribe tu pregunta…" })).toBeEnabled({
|
||||
timeout: 30_000,
|
||||
});
|
||||
|
||||
await page.reload();
|
||||
await expect(page.getByRole("heading", { name: "Asistente" })).toBeVisible();
|
||||
await expect(page.getByText("Show my spending by category this month.", { exact: true })).toBeVisible();
|
||||
await expect(page.getByTestId("spending-summary-card")).toBeVisible();
|
||||
|
||||
expect(consoleErrors.join("\n")).not.toContain("ChatClientException");
|
||||
});
|
||||
Reference in New Issue
Block a user