Onboarding: emoji-first flow with shape/color selection, user preferences, language setup (9 locales), and bot creation with avatarValue persistence. executor.ts: split 4928→4159 lines into 8 modules (completion, computer, effects, model, utils, tools, attachments, types). pi-runtime.ts: split 1726→561 lines into 2 modules (model-config, tool-utils). E2E: new onboarding-emoji-first tests + updated completeOnboarding helper.
159 lines
5.2 KiB
TypeScript
159 lines
5.2 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");
|
|
|
|
// Live preview should show a BotAvatar
|
|
const preview = page.locator('[data-rakazo-surface="onboarding"]');
|
|
await expect(preview).toBeVisible();
|
|
|
|
// Shape selection grid should have 8 options
|
|
const shapeButtons = page.locator('[aria-pressed]');
|
|
// Click the 4th shape (index 3)
|
|
const shapes = page.locator('[data-testid*="shape"] , button:has(svg)');
|
|
if (await shapes.count()) {
|
|
await shapes.nth(3).click();
|
|
}
|
|
|
|
// Color selection: click the 3rd color swatch
|
|
const colorSwatches = page.locator("button[aria-label^=Color]");
|
|
if (await colorSwatches.count()) {
|
|
await colorSwatches.nth(2).click();
|
|
}
|
|
|
|
// Verify the preview updated (the BotAvatar should reflect the new color)
|
|
const botAvatar = page.locator('[data-rakazo-surface="onboarding"] 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();
|
|
});
|