tests/fixtures.js
// Shared fixtures (§76): page objects and helpers every spec can ask for by
// name. Playwright builds them lazily, only for the tests that use them.
import { test as base, expect } from "@playwright/test";
export const USERS = {
alice: { email: "alice@example.com", password: "correct-horse-1" },
bob: { email: "bob@example.com", password: "battery-staple-2" },
};
// A page object: the one place that knows how the chat UI is built.
// Tests talk in user intent ("ask", "lastReply"), not CSS selectors.
export class ChatPage {
constructor(page) {
this.page = page;
this.input = page.getByRole("textbox", { name: "Message" });
this.send = page.getByRole("button", { name: "Send" });
this.stop = page.getByRole("button", { name: "Stop" });
this.log = page.getByRole("log", { name: "Conversation" });
this.orders = page.getByRole("list", { name: "Your orders" });
}
async goto() {
await this.page.goto("/");
await expect(this.input).toBeVisible();
}
async ask(text) {
await this.input.fill(text);
await this.send.click();
}
lastReply() {
return this.log.locator('[data-role="assistant"]').last();
}
async waitForReply() {
// aria-busy flips back to false when the stream ends.
await expect(this.log).toHaveAttribute("aria-busy", "false");
}
}
export async function login(page, { email, password }) {
await page.goto("/");
await page.getByLabel("Email").fill(email);
await page.getByLabel("Password").fill(password);
await page.getByRole("button", { name: "Sign in" }).click();
}
// Build an SSE body by hand, for tests that mock the agent (§77).
export const sse = (...events) => events.map((e) => `data: ${JSON.stringify(e)}\n\n`).join("");
export const test = base.extend({
chat: async ({ page }, use) => {
const chat = new ChatPage(page);
await chat.goto();
await use(chat);
},
// seedOrder({ item, total }) -> a fresh order owned by the signed-in user.
seedOrder: async ({ page }, use) => {
await use(async (order = {}) => {
const res = await page.request.post("/__test__/orders", { data: order });
expect(res.status()).toBe(201);
return res.json();
});
},
});
export { expect };