import { expect, test, type Page } from './fixtures'; // The first-run onboarding coachmarks. `?coach` forces the overlay on in the mock build (where it // is otherwise off so it cannot eat the smoke's taps) and bypasses the persisted "seen" flag, so // the series replay deterministically here. A tap anywhere on the overlay advances; after the last // hint the overlay removes itself. // Tap the overlay near a corner (clear of the bubble) to advance to the next hint. async function advance(page: Page): Promise { await page.locator('[data-coach-overlay]').click({ position: { x: 5, y: 5 } }); } // Drive both series end to end: guest login -> lobby coachmarks (3) -> open the seeded game -> // game coachmarks (5) -> gone. Shared by the portrait and landscape projects/cases. async function runOnboarding(page: Page): Promise { const overlay = page.locator('[data-coach-overlay]'); await page.goto('/?coach=1'); await page.getByRole('button', { name: /guest/i }).click(); // Lobby series: settings -> stats -> new game. await expect(overlay).toBeVisible({ timeout: 10000 }); await advance(page); await advance(page); await advance(page); await expect(overlay).toBeHidden(); // The lobby is interactive again: open the seeded active game. await page.getByRole('button', { name: /Ann/ }).click(); await expect(page.locator('[data-cell]').first()).toBeVisible(); // Game series: header -> pass/exchange -> hints -> shuffle -> rack. await expect(overlay).toBeVisible({ timeout: 10000 }); for (let i = 0; i < 5; i++) await advance(page); await expect(overlay).toBeHidden(); } test('onboarding walks the lobby then the first game (portrait)', async ({ page }) => { await runOnboarding(page); }); test.describe('landscape', () => { test.use({ viewport: { width: 1100, height: 640 } }); test('onboarding anchors and advances in the wide layout', async ({ page }) => { await runOnboarding(page); }); });