- onboarding-intake.spec walks focus, goal (after typing into the composer, which still works), check-ins, quiet hours and the notifications card when the browser offers it, with the onboarding-intake-goal, -rhythm and -done screenshots. - completeOnboarding and the wizard specs drop the preferences step; the scan step is optional (skipped when it asks, otherwise it advances by itself). - The user-profile spec now checks the browser-filled profile and the focus fact; the conversation spec checks the shorter app suggestion and the following goal question. - The hover spec measures a reply that fills its row (a bot row's rail sits at the row's end, so the old long onboarding line was what made it pass) and scopes Send to the composer, since an open goal card has its own. - Mobile shows a choice card as its question and answer instead of an empty bubble. - The focus options drop their unused summary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
import type { Page } from "@playwright/test";
|
|
import { expect, test } from "@playwright/test";
|
|
import { captureScreenshot, signup } 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 }],
|
|
},
|
|
},
|
|
}),
|
|
);
|
|
});
|
|
|
|
test.use({
|
|
hasTouch: true,
|
|
isMobile: true,
|
|
viewport: { width: 390, height: 844 },
|
|
});
|
|
|
|
async function swipeLook(page: Page, start: [number, number], end: [number, number]) {
|
|
await page.getByTestId("onboarding-look-carousel").evaluate(
|
|
(root, { start, end }) => {
|
|
function touch([clientX, clientY]: [number, number]) {
|
|
return new Touch({ clientX, clientY, identifier: 1, target: root });
|
|
}
|
|
const first = touch(start);
|
|
root.dispatchEvent(
|
|
new TouchEvent("touchstart", {
|
|
bubbles: true,
|
|
cancelable: true,
|
|
changedTouches: [first],
|
|
touches: [first],
|
|
}),
|
|
);
|
|
const last = touch(end);
|
|
root.dispatchEvent(
|
|
new TouchEvent("touchend", {
|
|
bubbles: true,
|
|
cancelable: true,
|
|
changedTouches: [last],
|
|
touches: [],
|
|
}),
|
|
);
|
|
},
|
|
{ start, end },
|
|
);
|
|
}
|
|
|
|
test("mobile onboarding: category pick and swipe look previews", async ({ page }, testInfo) => {
|
|
const stamp = Date.now();
|
|
await signup(page, `oo-swipe-${stamp}@rakazo.test`, "password12", "Swipe Tester");
|
|
|
|
await page.waitForURL(/\/(onboarding|app)/, { timeout: 20_000 });
|
|
await expect(page.getByTestId("onboarding-oo-designer")).toBeVisible();
|
|
await expect(page.getByRole("heading", { name: /Design your Oo/i })).toBeVisible();
|
|
await expect(page.getByTestId("onboarding-look-preview")).toBeVisible();
|
|
|
|
await page.getByTestId("onboarding-look-category-coder").click();
|
|
await expect(page.getByTestId("onboarding-look-category-coder")).toHaveAttribute(
|
|
"aria-selected",
|
|
"true",
|
|
);
|
|
|
|
const secondDot = page.getByRole("tab", { name: /Look 2 of/i });
|
|
await swipeLook(page, [280, 420], [120, 420]);
|
|
await expect(secondDot).toHaveAttribute("aria-selected", "true");
|
|
|
|
if (testInfo) await captureScreenshot(page, testInfo, "mobile-onboarding-oo-swipe");
|
|
|
|
await page
|
|
.getByRole("button", { name: /Continue/i })
|
|
.first()
|
|
.click();
|
|
await expect(page.getByRole("heading", { name: /Choose your language/i })).toBeVisible();
|
|
});
|