* 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>
87 lines
4.1 KiB
TypeScript
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…");
|
|
});
|