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 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); });