* feat(web): WOW mobile-first onboarding look picker with swipe previews Replace the form-style emoji step with category chips and a swipeable look carousel. Each preset maps to existing color, shape, and pose taxonomies; avatarValue still lands as color::shape on bot create. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * style(web): format onboarding look picker files 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>
141 lines
4.8 KiB
TypeScript
141 lines
4.8 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import { captureScreenshot, completeOnboarding, signup } from "./helpers";
|
|
|
|
/**
|
|
* E2E test for the new emoji-first onboarding flow:
|
|
* 1. Sign up → lands on onboarding
|
|
* 2. Design Oo: pick shape + color → live preview
|
|
* 3. Tell us about yourself: name, timezone, hobbies, work style, communication
|
|
* 4. Choose language
|
|
* 5. Skip integrations → bot created → land in chat
|
|
*/
|
|
|
|
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');
|
|
await expect(botAvatar).toBeVisible();
|
|
|
|
if (testInfo) await captureScreenshot(page, testInfo, "02-shape-color-preview");
|
|
|
|
// Click Continue → goes to preferences step
|
|
await page
|
|
.getByRole("button", { name: /Continue/i })
|
|
.first()
|
|
.click();
|
|
|
|
// Step 2: Tell us about yourself
|
|
await expect(page.getByRole("heading", { name: /Tell us about yourself/i })).toBeVisible();
|
|
|
|
if (testInfo) await captureScreenshot(page, testInfo, "03-user-preferences");
|
|
|
|
// Fill in name
|
|
await page.getByPlaceholder(/Your name/i).fill("Alice");
|
|
|
|
// Fill in timezone
|
|
await page.getByPlaceholder(/Timezone/i).fill("Europe/Vienna");
|
|
|
|
// Select a hobby
|
|
const hobbyButtons = page.locator("button[aria-pressed]");
|
|
if (await hobbyButtons.count()) {
|
|
await hobbyButtons.first().click(); // toggle first hobby
|
|
}
|
|
|
|
// Select work style
|
|
const workStyleButtons = page.locator("button[aria-pressed]:visible");
|
|
if ((await workStyleButtons.count()) >= 2) {
|
|
await workStyleButtons.nth(0).click();
|
|
}
|
|
|
|
// Select communication style
|
|
const commButtons = page.locator("button[aria-pressed]:visible");
|
|
if ((await commButtons.count()) >= 2) {
|
|
await commButtons.nth(0).click();
|
|
}
|
|
|
|
if (testInfo) await captureScreenshot(page, testInfo, "04-preferences-filled");
|
|
|
|
// Click Continue → goes to language step
|
|
await page
|
|
.getByRole("button", { name: /Continue/i })
|
|
.first()
|
|
.click();
|
|
|
|
// Step 3: Language selection
|
|
await expect(page.getByRole("heading", { name: /Choose your language/i })).toBeVisible();
|
|
|
|
if (testInfo) await captureScreenshot(page, testInfo, "05-language-step");
|
|
|
|
// Select Deutsch
|
|
await page.getByRole("button", { name: /Deutsch/ }).click();
|
|
|
|
// Should go to integrations or bot creation
|
|
// Either skip integrations or go directly to bot creation
|
|
const chief = page.getByText("Chief").first();
|
|
const integrationsHeading = page.getByRole("heading", {
|
|
name: /Server integrations/i,
|
|
});
|
|
await integrationsHeading
|
|
.or(chief)
|
|
.or(page.getByText("Opening chat…"))
|
|
.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 }, testInfo) => {
|
|
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();
|
|
|
|
// Preferences step — just continue
|
|
await expect(page.getByRole("heading", { name: /Tell us about yourself/i })).toBeVisible();
|
|
await page
|
|
.getByRole("button", { name: /Continue/i })
|
|
.first()
|
|
.click();
|
|
|
|
// Language step — click Skip
|
|
await expect(page.getByRole("heading", { name: /Choose your language/i })).toBeVisible();
|
|
await page.getByRole("button", { name: /Skip/i }).click();
|
|
|
|
// Should land in bot chat
|
|
await page.waitForURL(/\/app\//, { timeout: 20_000 });
|
|
await expect(page.getByText("Chief").first()).toBeVisible();
|
|
});
|