evOo-local/apps/web/e2e/chat-queued-progress.spec.ts
cynarAI 97787a0272
Production readiness phase 1: journey audit, fixes 1–4, E2E (#175)
* Production readiness phase 1: journeys doc, onboarding persistence, teardown, chat UX

- Add docs/PRODUCTION-READINESS.md with journey matrix and defect backlog
- Persist onboarding draft in session storage across reload
- Localize onboarding discovery main-bot role; German Chief of Staff string
- Destroy team sandboxes and home folders when deleting an account
- Keep composer/transcript visible during queued runs; extend send watchdog
- Add Playwright specs: reload persistence, DE intake, queued progress, console guard

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* Fix CI: sync Lingui catalogs, onboarding name draft, E2E stability

- Localize Chief of Staff in discovery shell; sync all locale PO files
- Propagate Oo name to onboarding draft while typing
- Adjust DE intake, queued-run, and console-error E2E specs

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* Format chat-queued-progress E2E spec

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(api): scope account-delete sandbox teardown to owned spaces

Only destroy team sandboxes and homes for spaces the deleting user
owns with no remaining members or bots. Guard home removal under
dataDir/homes. Add unit and postgres journey coverage.

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* chore: apply biome formatting

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
2026-10-07 11:25:39 +02:00

54 lines
1.8 KiB
TypeScript

import { expect, test } from "@playwright/test";
import { completeOnboarding, routePatchRpc, signup, waitForChatComposer } from "./helpers";
const viewports = [
{ name: "desktop", width: 1440, height: 900 },
{ name: "mobile", width: 390, height: 844 },
];
for (const viewport of viewports) {
test(`queued run shows waiting status (${viewport.name})`, async ({ page }) => {
await page.setViewportSize({ width: viewport.width, height: viewport.height });
const stamp = Date.now();
await signup(page, `queued-${viewport.name}-${stamp}@rakazo.test`, "password12", "Queue");
await completeOnboarding(page);
await waitForChatComposer(page);
const botId = new URL(page.url()).pathname.split("/").filter(Boolean).at(-1)!;
let holdQueued = false;
await routePatchRpc(page, "threads/get", (json) => {
if (!holdQueued) return json;
const run = {
id: "run-queued-e2e",
botId,
threadId: String(json.threadId ?? "thread-e2e"),
taskId: "task-queued-e2e",
status: "queued",
trigger: "user",
routineId: null,
modelProvider: null,
modelId: null,
error: null,
startedAt: null,
completedAt: null,
createdAt: new Date().toISOString(),
};
return { ...json, run, activeRuns: [run] };
});
await page.route("**/rpc/threads/send", async (route) => {
holdQueued = true;
await route.continue();
});
const composer = page.getByRole("combobox", { name: /Message|Nachricht/i });
await composer.fill("Hallo");
await composer.press("Enter");
await expect(
page.getByRole("status").filter({ hasText: /Queued|Wartet|Working|Arbeitet/i }),
).toBeVisible({
timeout: 20_000,
});
await expect(page.getByRole("button", { name: /Stop|Stopp/i })).toBeVisible();
});
}