carbon-tokenization / backend /e2e /chat-persistence.test.ts
tfrere's picture
tfrere HF Staff
test(backend): add Playwright E2E suite + deps for editor basics, chat persistence and publish
6a34a48
Raw
History Blame Contribute Delete
3.19 kB
/**
* E2E: Chat persistence across page reloads.
*
* Validates: send message -> receive AI response -> reload -> conversation restored.
* Uses mocked /api/chat endpoint via page.route() (no real LLM calls).
*/
import { test, expect } from "./fixtures.js";
test.describe("Chat persistence", () => {
test("conversation survives page reload", async ({ appPage, serverUrl }) => {
// 1. Open chat panel
await appPage.click("[aria-label='AI Assistant']");
const input = appPage.getByPlaceholder("Ask anything...");
await expect(input).toBeVisible({ timeout: 3_000 });
// 2. Send a message
await input.fill("say hello");
await input.press("Enter");
// 3. Wait for AI response to appear
await expect(appPage.locator("text=Hello! I'm the AI assistant.")).toBeVisible({ timeout: 10_000 });
// 4. Wait for persistence to trigger (status transitions to "ready")
await appPage.waitForTimeout(2_000);
// 5. Verify localStorage has chat data
const chatKeys = await appPage.evaluate(() =>
Object.keys(localStorage).filter((k) => k.startsWith("chat:"))
);
expect(chatKeys.length).toBeGreaterThan(0);
expect(chatKeys[0]).toMatch(/^chat:.+:article$/);
// 6. Reload the page
await appPage.reload();
await appPage.waitForSelector("[aria-label='Undo']", { timeout: 15_000 });
// 7. Re-open chat and verify conversation is restored
await appPage.click("[aria-label='AI Assistant']");
await expect(appPage.locator("text=say hello")).toBeVisible({ timeout: 5_000 });
await expect(appPage.locator("text=Hello! I'm the AI assistant.")).toBeVisible({ timeout: 5_000 });
});
test("new conversation button clears messages", async ({ appPage }) => {
// 1. Open chat and send a message
await appPage.click("[aria-label='AI Assistant']");
const input = appPage.getByPlaceholder("Ask anything...");
await expect(input).toBeVisible({ timeout: 3_000 });
await input.fill("test message");
await input.press("Enter");
await expect(appPage.locator("text=Hello! I'm the AI assistant.")).toBeVisible({ timeout: 10_000 });
// Wait for persistence
await appPage.waitForTimeout(2_000);
// 2. Click "New conversation"
await appPage.click("[aria-label='New conversation']");
// 3. Verify the empty state is back
await expect(
appPage.locator("text=Ask me to write, edit, expand, or improve your article.")
).toBeVisible({ timeout: 3_000 });
// 4. Verify localStorage was cleared
const chatKeys = await appPage.evaluate(() =>
Object.keys(localStorage).filter((k) => k.startsWith("chat:"))
);
expect(chatKeys.length).toBe(0);
});
test("stable user identity across reloads", async ({ appPage }) => {
const userName1 = await appPage.evaluate(
() => JSON.parse(localStorage.getItem("collab-editor:fallback-user")!).name
);
await appPage.reload();
await appPage.waitForSelector("[aria-label='Undo']", { timeout: 15_000 });
const userName2 = await appPage.evaluate(
() => JSON.parse(localStorage.getItem("collab-editor:fallback-user")!).name
);
expect(userName1).toBe(userName2);
});
});