* Fix first-run onboarding UX: naming, locale, voices, Heute route, mobile drawer Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Fix biome import order and formatting Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Fix biome formatting on OoStage and E2E specs Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Fix E2E specs for onboarding name step and Heute reload route Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Fix German onboarding heading matcher in E2E Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Fix German signup E2E, Escape menu stacking, and Heute rhythm click Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Make onboarding E2E helpers locale-aware for German UI Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Fix completeOnboarding language skip for Skip · locale label Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Use language-step Skip · locale button in completeOnboarding Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Fix German E2E: Nachricht composer, voice loading wait, Heute rhythm Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Stabilize Heute reload URL and German voice E2E assertions Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Fix Heute bootstrap redirect and German onboarding voices When Kokoro lists no locale-matched voices, onboarding now uses offline presets instead of showing English-only options. Shell bootstrap skips bot redirects while the user is on /app/heute. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Relax German voice E2E name matching for voice labels Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Harden Heute route and German voice onboarding E2E Rebased onto main with Expo SDK 57 typecheck fixes. Voice options expose stable test ids; Shell keeps /app/heute across bootstrap and redirects legacy /app/heute bot URLs. Heute coach E2E asserts URL after reload. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Format Shell after Heute route helper 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>
112 lines
4.1 KiB
TypeScript
112 lines
4.1 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import { captureScreenshot, signup, skipOnboardingNameStep } from "./helpers";
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.route("**/rpc/integrationSetup/get", (route) =>
|
|
route.fulfill({
|
|
json: {
|
|
json: {
|
|
canConfigure: true,
|
|
needsSetup: false,
|
|
webUrl: "https://example.test/integrations/setup",
|
|
providers: [{ id: "composio", configured: true }],
|
|
},
|
|
},
|
|
}),
|
|
);
|
|
});
|
|
|
|
/**
|
|
* E2E test for the emoji-first onboarding flow:
|
|
* 1. Sign up → lands on onboarding
|
|
* 2. Design Oo: pick shape + color → live preview
|
|
* 3. Choose language, skip the voice
|
|
* 4. Skip integrations → bot created → land in chat, where the main bot asks the rest
|
|
*/
|
|
|
|
test("emoji-first onboarding: shape + color selection with live preview", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
const stamp = Date.now();
|
|
await signup(page, `emoji-${stamp}@rakazo.test`, "password12", "TestUser");
|
|
|
|
// Should land on onboarding page
|
|
await page.waitForURL(/\/(onboarding|app)/, { timeout: 20_000 });
|
|
|
|
// Step 1: Design your Oo
|
|
await expect(page.getByRole("heading", { name: /Design your Oo/i })).toBeVisible();
|
|
|
|
if (testInfo) await captureScreenshot(page, testInfo, "01-design-your-oo");
|
|
|
|
await expect(page.getByTestId("onboarding-oo-designer")).toBeVisible();
|
|
await expect(page.getByTestId("onboarding-look-preview")).toBeVisible();
|
|
|
|
await page.getByTestId("onboarding-look-category-work").click();
|
|
await page.getByRole("tab", { name: /Look 3 of/i }).click();
|
|
|
|
const botAvatar = page.locator('[data-testid="onboarding-look-preview"] svg').first();
|
|
await expect(botAvatar).toBeVisible();
|
|
|
|
if (testInfo) await captureScreenshot(page, testInfo, "02-shape-color-preview");
|
|
|
|
// Click Continue → naming, then language.
|
|
await page
|
|
.getByRole("button", { name: /Continue/i })
|
|
.first()
|
|
.click();
|
|
await skipOnboardingNameStep(page);
|
|
|
|
// Step 2: Language selection
|
|
await expect(page.getByRole("heading", { name: /Choose your language/i })).toBeVisible();
|
|
|
|
if (testInfo) await captureScreenshot(page, testInfo, "05-language-step");
|
|
|
|
// Select Deutsch — choosing a language continues to the voice step.
|
|
await page.getByRole("button", { name: /Deutsch/ }).click();
|
|
await expect(page.getByRole("heading", { name: /Pick a voice/i })).toBeVisible();
|
|
await page.getByRole("button", { name: "Skip", exact: true }).click();
|
|
|
|
const chief = page.getByText("Chief").first();
|
|
const integrationsHeading = page.getByRole("heading", {
|
|
name: /Server integrations/i,
|
|
});
|
|
await integrationsHeading.or(chief).waitFor({ timeout: 20_000 });
|
|
|
|
if (testInfo) await captureScreenshot(page, testInfo, "06-integrations-or-bot");
|
|
|
|
// If integrations shown, skip
|
|
if (await integrationsHeading.isVisible().catch(() => false)) {
|
|
await page.getByRole("button", { name: "Skip", exact: true }).click();
|
|
}
|
|
|
|
await page.waitForURL(/\/app\//, { timeout: 20_000 });
|
|
await expect(chief).toBeVisible();
|
|
|
|
if (testInfo) await captureScreenshot(page, testInfo, "07-onboarding-complete");
|
|
});
|
|
|
|
test("onboarding: skip language defaults to English", async ({ page }) => {
|
|
const stamp = Date.now();
|
|
await signup(page, `lang-skip-${stamp}@rakazo.test`, "password12", "Skipper");
|
|
|
|
await page.waitForURL(/\/(onboarding|app)/, { timeout: 20_000 });
|
|
|
|
// Go through emoji step quickly (just click continue)
|
|
await expect(page.getByRole("heading", { name: /Design your Oo/i })).toBeVisible();
|
|
await page
|
|
.getByRole("button", { name: /Continue/i })
|
|
.first()
|
|
.click();
|
|
await skipOnboardingNameStep(page);
|
|
|
|
// Language step — click Skip, then skip voice.
|
|
await expect(page.getByRole("heading", { name: /Choose your language/i })).toBeVisible();
|
|
await page.getByRole("button", { name: /Skip/i }).click();
|
|
await expect(page.getByRole("heading", { name: /Pick a voice/i })).toBeVisible();
|
|
await page.getByRole("button", { name: "Skip", exact: true }).click();
|
|
|
|
// Should land in bot chat
|
|
await page.waitForURL(/\/app\//, { timeout: 20_000 });
|
|
await expect(page.getByText("Chief").first()).toBeVisible();
|
|
});
|