import { expect, test, type Page } from './fixtures'; // The redesigned move history: a ruled matrix with one column per seat (no player names, no // running total), opened by a swipe-down on the zoom-out board. The gesture is touch-only and // the desktop projects have no touch input, so the swipe is dispatched as PointerEvents with // pointerType:'touch'; a phone viewport so the board fills the width. test.use({ viewport: { width: 390, height: 844 } }); async function openGame(page: Page): Promise { await page.goto('/'); await page.getByRole('button', { name: /guest/i }).click(); await page.getByRole('button', { name: /Ann/ }).click(); // the seeded active game G1 (your turn) await expect(page.locator('[data-cell]').first()).toBeVisible(); await expect(page.locator('.pane')).toHaveCount(1); // let the screen-slide settle } /** touchSwipeDown dispatches a single-finger vertical touch drag on the board wrapper. */ async function touchSwipeDown(page: Page, fromY: number, toY: number): Promise { const box = (await page.locator('.boardwrap').boundingBox())!; const x = box.x + box.width / 2; await page.locator('.boardwrap').evaluate( (el, { x, fromY, toY }) => { const fire = (type: string, y: number) => el.dispatchEvent( new PointerEvent(type, { pointerType: 'touch', clientX: x, clientY: y, bubbles: true, cancelable: true }), ); fire('pointerdown', fromY); for (let i = 1; i <= 8; i++) fire('pointermove', fromY + ((toY - fromY) * i) / 8); fire('pointerup', toY); }, { x, fromY, toY }, ); } test('a swipe-down on the zoom-out board opens the history', async ({ page }) => { await openGame(page); await page.locator('.stage').evaluate((el) => (el.scrollTop = 0)); // the pull only opens at the top const box = (await page.locator('.boardwrap').boundingBox())!; await touchSwipeDown(page, box.y + 20, box.y + 180); await expect(page.locator('.history')).toBeVisible(); await expect(page.locator('.boardwrap.slid')).toBeVisible(); }); test('the history is a per-seat grid with move scores but no names or running total', async ({ page }) => { await openGame(page); await page.locator('.scoreboard').click(); // open the history (gesture is covered separately) const grid = page.locator('.hgrid'); await expect(grid).toBeVisible(); // G1: You [HELLO 16, RAT 3] vs Ann [WORLD 9, AND 4] — a 2×2 matrix, no empty/thinking cells. await expect(page.locator('.hcell')).toHaveCount(4); await expect(grid).toContainText('HELLO'); await expect(grid).toContainText('(3)'); // RAT's per-move score // The running total (RAT's was 19) and the seat names no longer appear in the table. await expect(grid).not.toContainText('19'); await expect(grid).not.toContainText('Ann'); }); test('a two-finger pinch does not open the history (pinch-zoom vs swipe-down)', async ({ page }) => { await openGame(page); await page.locator('.stage').evaluate((el) => (el.scrollTop = 0)); const box = (await page.locator('.boardwrap').boundingBox())!; const cx = box.x + box.width / 2; const y0 = box.y + 40; // Two fingers land, then spread apart while their centroid drifts down — a pinch-out whose // downward component used to also slide the history open. With the single-pointer guard the // second finger disarms the pull, so the history stays closed. await page.locator('.boardwrap').evaluate( (el, { cx, y0 }) => { const fire = (type: string, id: number, x: number, y: number) => el.dispatchEvent( new PointerEvent(type, { pointerType: 'touch', pointerId: id, isPrimary: id === 1, clientX: x, clientY: y, bubbles: true, cancelable: true, }), ); fire('pointerdown', 1, cx - 20, y0); fire('pointerdown', 2, cx + 20, y0); for (let i = 1; i <= 8; i++) { const d = i * 18; fire('pointermove', 1, cx - 20 - d, y0 + d); fire('pointermove', 2, cx + 20 + d, y0 + d); } fire('pointerup', 1, cx - 164, y0 + 144); fire('pointerup', 2, cx + 164, y0 + 144); }, { cx, y0 }, ); await expect(page.locator('.history')).toHaveCount(0); }); test('a swipe-down on the zoomed-in board does not open the history (native scroll wins)', async ({ page }) => { await openGame(page); // Double-tap an empty cell to zoom in (two synchronous clicks = a double-tap). await page .locator('[data-cell]:not(.filled)') .nth(20) .evaluate((el: HTMLElement) => { el.click(); el.click(); }); await expect(page.locator('.viewport.zoomed')).toBeVisible(); const box = (await page.locator('.boardwrap').boundingBox())!; await touchSwipeDown(page, box.y + 20, box.y + 180); await expect(page.locator('.history')).toHaveCount(0); });