import { expect, test, type Page } from './fixtures'; // Behaviour/display coverage for the polished game screen, driven entirely by the mock // transport (no backend). These lock the round-1..4 interactions so future UI edits // surface as a failing assertion — to be re-agreed or fixed. The pure logic behind them // (placement, check-word, board labels, result badges) is unit-tested separately. 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 vs Ann await expect(page.locator('[data-cell]').first()).toBeVisible(); } test('placing a tile and confirming via 🏁 commits the move', async ({ page }) => { await openGame(page); await page.locator('.rack .tile').first().click(); await page.locator('[data-cell]:not(.filled)').nth(30).click(); await expect(page.locator('[data-cell].pending')).toHaveCount(1); await page.locator('.make').click(); // open the MakeMove popover (short tap) await page.locator('.pop.go').click(); // "Make move ✅" // After the commit the placement is cleared: no pending tile, no 🏁 control. await expect(page.locator('[data-cell].pending')).toHaveCount(0); await expect(page.locator('.make')).toBeHidden(); }); test('history slides the board down and closes on a board tap', async ({ page }) => { await openGame(page); await page.locator('.burger').click(); await page.locator('.dropdown button').nth(0).click(); // History await expect(page.locator('.history')).toBeVisible(); await expect(page.locator('.boardwrap.slid')).toBeVisible(); await page.locator('.boardwrap').click(); // tapping the board closes it await expect(page.locator('.history')).toBeHidden(); }); test('Draw opens the exchange dialog and confirms a selection', async ({ page }) => { await openGame(page); await page.locator('button:has-text("🔄")').click(); // Draw tab await expect(page.locator('.exch')).toBeVisible(); await page.locator('.etile').first().click(); await expect(page.locator('.etile.sel')).toHaveCount(1); await page.locator('button.confirm').click(); await expect(page.locator('.exch')).toBeHidden(); }); test('check-word sanitises input and shows a verdict', async ({ page }) => { await openGame(page); await page.locator('.burger').click(); await page.locator('.dropdown button').nth(2).click(); // Check word const input = page.locator('.check input'); await input.fill('qz9!a'); // digits/punctuation dropped, letters upper-cased await expect(input).toHaveValue('QZA'); await page.locator('.check button').click(); // Check (enabled: length 3) await expect(page.locator('.ok, .bad')).toBeVisible(); }); test('dropping the game ends it and shows the result', async ({ page }) => { await openGame(page); await page.locator('.burger').click(); await page.getByRole('button', { name: 'Drop game' }).click(); // robust against menu growth await page.locator('button.danger').click(); // confirm in the modal await expect(page.locator('.status .over')).toBeVisible(); }); test('the board-label mode in Settings changes the on-board labels', async ({ page }) => { await openGame(page); // beginner (default) renders split "3× / word" labels. await expect(page.locator('.bsplit').first()).toBeVisible(); await expect(page.locator('.b1')).toHaveCount(0); // Switch to "classic" in Settings (in-SPA hash nav keeps the guest session). await page.evaluate(() => (location.hash = '/settings')); await page.locator('.seg').nth(2).locator('.opt').nth(1).click(); // board labels -> classic await page.evaluate(() => (location.hash = '/game/g1')); // classic renders single "3W"/"2L" labels and no split labels. await expect(page.locator('.b1').first()).toBeVisible(); await expect(page.locator('.bsplit')).toHaveCount(0); });