evOo-local/apps/web/e2e/unterhaltungen-sidebar.spec.ts
cynarAI 263e3a31f8
Fix red main: mobile group kind, i18n catalogs, project picker check (#218)
* Fix red main: mobile group kind, i18n catalogs, project picker check

Main CI failed on typecheck, unit tests and web E2E after the last two
direct pushes. MobileGroup now carries the optional chat kind the mobile
screens read, the Lingui catalogs are re-extracted with German strings
for the new voice texts, the project overview plus icon meets the UI
scale guard, and the sidebar E2E expects the renamed project lead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8L4XgqjAemFR2remB5hVY

* Format files merged from main

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wy1md9QE1ayJbDCwJ4vAQs

* Align E2E with the canvas close button and per-chat drafts

The in-app browser now closes from the side panel header, and each chat
keeps its own unsent draft. The group chat test waits for the settings
save to land before switching chats, so the switch no longer races the
panel closing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wy1md9QE1ayJbDCwJ4vAQs

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-20 09:34:40 +02:00

87 lines
4.1 KiB
TypeScript

import { expect, test } from "@playwright/test";
import { completeOnboarding, openNewBot, signup, unterhaltungenOnly } from "./helpers";
test("conversations and projects stay separate; + opens bot picker", async ({ page }) => {
const stamp = Date.now();
await signup(page, `unterhaltungen-${stamp}@rakazo.test`, "password12", "Unterhaltungen UX");
await completeOnboarding(page);
await page.goto("/app");
await page.waitForURL(/\/app\/[^/]+$/);
const unterhaltungen = page.locator(".sidebar-unterhaltungen");
const projekte = page.locator(".sidebar-projekte");
await expect(unterhaltungen.getByText("Talk to your Oos", { exact: true })).toBeVisible();
await expect(projekte.getByText("Projects", { exact: true })).toBeVisible();
await expect(unterhaltungen.getByRole("button", { name: /^Chief/ })).toBeVisible();
const [projekteBox, unterhaltungenBox] = await Promise.all([
projekte.boundingBox(),
unterhaltungen.boundingBox(),
]);
expect(projekteBox).not.toBeNull();
expect(unterhaltungenBox).not.toBeNull();
expect(projekteBox!.y).toBeLessThan(unterhaltungenBox!.y);
await unterhaltungen.getByTestId("conversation-picker-trigger").click();
const picker = page.getByTestId("conversation-bot-picker");
await expect(picker).toBeVisible();
await expect(picker.getByTestId("conversation-create-bot")).toBeVisible();
await expect(picker.getByText("Chief", { exact: true })).toBeVisible();
await picker.getByTestId("conversation-create-bot").click();
await expect(page.getByTestId("create-bot-form")).toBeVisible();
await page.keyboard.press("Escape");
await openNewBot(page);
const form = page.getByTestId("create-bot-form");
await form.locator("label:has-text('Name') input").fill("Researcher");
await form.getByRole("button", { name: "Create", exact: true }).click();
await page.waitForURL(/\/app\/[^/]+$/);
await expect(page.getByRole("combobox", { name: "Message" })).toBeVisible();
await projekte.getByTestId("create-project-trigger").click();
const dialog = page.getByRole("dialog", { name: "New project" });
await dialog.getByLabel("Name").fill("Side project");
await dialog.getByRole("button", { name: "Create project", exact: true }).click();
await page.waitForURL(/\/app/);
await expect(projekte.getByText("Side project", { exact: true })).toBeVisible();
await expect(unterhaltungenOnly(page).getByText("Side project", { exact: true })).toHaveCount(0);
// The new project's main agent leads the picker, even after other bots exist.
await unterhaltungen.getByTestId("conversation-picker-trigger").click();
await expect(
page
.getByTestId("conversation-bot-picker")
.locator("[data-testid^='conversation-picker-bot-']")
.first(),
).toHaveText("Projektmanager");
await page.keyboard.press("Escape");
// Creating a project that already exists opens it instead of listing it twice.
await projekte.getByTestId("create-project-trigger").click();
const again = page.getByRole("dialog", { name: "New project" });
await again.getByLabel("Name").fill("side project");
await again.getByRole("button", { name: "Create project", exact: true }).click();
await expect(again).toBeHidden();
await expect(projekte.getByText("Side project", { exact: true })).toHaveCount(1);
await expect(projekte.getByText("side project", { exact: true })).toHaveCount(0);
});
test("chat header shows avatar once and composer uses generic placeholder", async ({ page }) => {
const stamp = Date.now();
await signup(page, `chat-header-${stamp}@rakazo.test`, "password12", "Chat Header");
await completeOnboarding(page);
await page.goto("/app");
await page.waitForURL(/\/app\/[^/]+$/);
const header = page.getByTestId("bot-settings-trigger");
await expect(
header.locator(".rakazo-bot-avatar, [data-testid='bot-avatar']").first(),
).toBeVisible();
await expect(header.getByText("Chief", { exact: true })).toBeVisible();
await expect(header.getByText("1:1 conversation", { exact: true })).toHaveCount(0);
const composer = page.getByRole("combobox", { name: "Message" });
await expect(composer).toHaveAttribute("placeholder", "Message…");
});