Make onboarding E2E helpers locale-aware for German UI

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-10-06 13:06:43 +00:00
parent c5b2ebc2b3
commit 1511880f1b
No known key found for this signature in database
4 changed files with 33 additions and 23 deletions

View File

@ -5,12 +5,12 @@ test("onboarding names the first Oo and shows it in chat", async ({ page }) => {
const stamp = Date.now();
await signup(page, `name-oo-${stamp}@rakazo.test`, "password12", "Namer");
await page.waitForURL(/\/onboarding/, { timeout: 20_000 });
await page.getByRole("button", { name: "Continue", exact: true }).click();
await page.getByRole("button", { name: /^(Continue|Weiter)$/i }).click();
await expect(page.getByTestId("onboarding-name-step")).toBeVisible();
await page.getByTestId("onboarding-oo-name-input").fill("Luna");
await page.getByTestId("onboarding-name-step").getByRole("button", { name: "Continue" }).click();
await page.getByRole("button", { name: /Skip/i }).click();
await page.getByRole("button", { name: "Skip", exact: true }).click();
await page.getByRole("button", { name: /^(Skip|Überspringen)$/i }).click();
await expect(page).toHaveURL(/\/app\/g\/[^/]+/, { timeout: 30_000 });
await expect(
page.getByTestId("bot-settings-trigger").getByText("Luna", { exact: true }),
@ -25,8 +25,8 @@ test("German UI keeps Deutsch on language skip label", async ({ page }) => {
});
const stamp = Date.now();
await signup(page, `de-skip-${stamp}@rakazo.test`, "password12", "Deutsch");
await page.getByRole("button", { name: "Continue", exact: true }).click();
await page.getByRole("button", { name: "Skip", exact: true }).click();
await page.getByRole("button", { name: /^(Continue|Weiter)$/i }).click();
await page.getByRole("button", { name: /^(Skip|Überspringen)$/i }).click();
await expect(
page.getByRole("heading", { name: /Wähle deine Sprache|Choose your language/i }),
).toBeVisible();
@ -40,8 +40,8 @@ test("German voice step lists German voices after choosing Deutsch", async ({ pa
});
const stamp = Date.now();
await signup(page, `de-voice-${stamp}@rakazo.test`, "password12", "Stimme");
await page.getByRole("button", { name: "Continue", exact: true }).click();
await page.getByRole("button", { name: "Skip", exact: true }).click();
await page.getByRole("button", { name: /^(Continue|Weiter)$/i }).click();
await page.getByRole("button", { name: /^(Skip|Überspringen)$/i }).click();
await page.getByRole("button", { name: "Deutsch", exact: true }).click();
await expect(page.getByRole("button", { name: "Eva", exact: true })).toBeVisible();
await expect(page.getByRole("button", { name: "Alloy", exact: true })).toHaveCount(0);

View File

@ -87,6 +87,9 @@ async function visible(locator: Locator, timeout: number) {
return locator.isVisible({ timeout }).catch(() => false);
}
const onboardingContinueButton = /^(Continue|Weiter)$/i;
const onboardingSkipButton = /^(Skip|Überspringen)$/i;
/** After the look picker, skip the optional Oo naming step (keeps the default name). */
export async function skipOnboardingNameStep(page: Page) {
await expect(page.getByTestId("onboarding-name-step")).toBeVisible();
@ -113,11 +116,15 @@ export async function completeOnboarding(
);
}
const design = page.getByRole("heading", { name: /Design your Oo/i });
const design = page.getByRole("heading", { name: /Design your Oo|Gestalte dein Oo/i });
const naming = page.getByTestId("onboarding-name-step");
const language = page.getByRole("heading", { name: /Choose your language/i });
const voice = page.getByRole("heading", { name: /Pick a voice/i });
const integrations = page.getByRole("heading", { name: "Server integrations", exact: true });
const language = page.getByRole("heading", {
name: /Choose your language|Wähle deine Sprache/i,
});
const voice = page.getByRole("heading", { name: /Pick a voice|Wähle eine Stimme/i });
const integrations = page.getByRole("heading", {
name: /Server integrations|Server-Integrationen/i,
});
const expectedOoName = options.ooName ?? "Chief";
const chief = page.getByText(expectedOoName).first();
@ -127,30 +134,30 @@ export async function completeOnboarding(
await expect(entry.first()).toBeVisible({ timeout: 20_000 });
if (await design.isVisible()) {
await page.getByRole("button", { name: "Continue", exact: true }).click();
await page.getByRole("button", { name: onboardingContinueButton }).click();
await expect(naming).toBeVisible();
if (options.ooName) {
await page.getByTestId("onboarding-oo-name-input").fill(options.ooName);
await naming.getByRole("button", { name: "Continue", exact: true }).click();
await naming.getByRole("button", { name: onboardingContinueButton }).click();
} else {
await page.getByRole("button", { name: "Skip", exact: true }).click();
await page.getByRole("button", { name: onboardingSkipButton }).click();
}
await expect(language).toBeVisible();
await page.getByRole("button", { name: /Skip/i }).click();
await page.getByRole("button", { name: onboardingSkipButton }).click();
await expect(voice).toBeVisible();
await page.getByRole("button", { name: "Skip", exact: true }).click();
await page.getByRole("button", { name: onboardingSkipButton }).click();
}
if (await visible(integrations, 8_000)) {
if (testInfo) await captureScreenshot(page, testInfo, "02-connect-apps");
await page.getByRole("button", { name: "Skip", exact: true }).click();
await page.getByRole("button", { name: onboardingSkipButton }).click();
}
// The scan step, when shown, either asks first (skip it) or advances by itself. Onboarding
// then lands in the main conversation.
const skipScan = page
.locator('[data-onboarding-step="scan"]')
.getByRole("button", { name: "Skip", exact: true });
.getByRole("button", { name: onboardingSkipButton });
await expect(async () => {
if (await skipScan.isVisible()) await skipScan.click();
expect(page.url()).toMatch(/\/app\/g\/[^/]+$/);

View File

@ -85,6 +85,7 @@ test("Heute shows the coach's brief, habits and goals, checks habits off and set
await captureScreenshot(page, testInfo, "heute-coach");
await page.reload();
await openHeute(page);
await expect(page).toHaveURL(/\/app\/heute$/);
await expect(page.getByTestId("heute-brief")).toBeVisible();
await expect(page.getByTestId(`heute-habit-${habit.id}`).getByRole("checkbox")).toBeChecked();
@ -92,11 +93,13 @@ test("Heute shows the coach's brief, habits and goals, checks habits off and set
// Check-in times live behind one compact control.
const rhythm = page.getByTestId("heute-rhythm");
await expect(rhythm).toBeVisible();
await expect(async () => {
await rhythm.click();
await expect(page.getByTestId("heute-rhythm-panel")).toBeVisible();
}).toPass({ timeout: 15_000 });
const rhythmLoaded = page.waitForResponse(
(response) => response.url().includes("/rpc/coach/rhythm/get") && response.ok(),
);
await rhythm.click();
await rhythmLoaded;
const panel = page.getByTestId("heute-rhythm-panel");
await expect(panel).toBeVisible();
const morning = panel.getByTestId("heute-rhythm-morning");
await expect(morning.getByRole("switch")).not.toBeChecked();
const enabled = page.waitForResponse(

View File

@ -27,8 +27,8 @@ export function useMobileSidebar() {
document.querySelector<HTMLElement>('[data-testid="open-navigation"]')?.focus();
});
}
window.addEventListener("keydown", onKeyDown, true);
return () => window.removeEventListener("keydown", onKeyDown, true);
window.addEventListener("keydown", onKeyDown);
return () => window.removeEventListener("keydown", onKeyDown);
}, [mobileSidebarOpen]);
function onMobileSidebarTouchStart(event: React.TouchEvent<HTMLDivElement>) {