/** * Mill — 联机 E2E * * 验证联机模式下 MillBoard 渲染正确(24 个交叉点)。 * 完整下棋流程覆盖在前面的单元测试(vitest + Local master)里。 */ import { test, expect, Browser } from '@playwright/test'; async function setupOnlineGame(browser: Browser, gameKey: string) { const ctx = await browser.newContext(); const page = await ctx.newPage(); await page.goto('/'); await page.getByTestId('game-select').selectOption(gameKey); await page.getByTestId('mode-online').click(); await expect(page.getByTestId('lobby-room-list')).toBeVisible(); return page; } async function joinAsFirstPlayer(page: any, playerSlot: '0' | '1') { if (playerSlot === '0') { await page.getByTestId('lobby-create-room').click(); } else { await expect(async () => { await page.getByTestId('lobby-refresh').click(); const roomChips = await page.locator('[data-testid^="lobby-room-"]').all(); const ids = await Promise.all(roomChips.map((c: any) => c.getAttribute('data-testid'))); const real = ids.filter((id: string | null) => id && !id.endsWith('-list') && !id.endsWith('-refresh') && !id.endsWith('-room'), ); expect(real.length).toBeGreaterThan(0); }).toPass({ timeout: 10_000 }); const rooms = page.locator('[data-testid^="lobby-room-"]:not([data-testid="lobby-room-list"])'); const count = await rooms.count(); expect(count).toBeGreaterThan(0); const firstRoom = rooms.first(); const matchIDAttr = await firstRoom.getAttribute('data-testid'); const matchID = matchIDAttr!.replace(/^lobby-room-/, ''); await page.getByTestId(`lobby-join-1-${matchID}`).click(); } await expect(page.getByTestId('online-need-room')).not.toBeVisible({ timeout: 15_000 }); } test.describe('Mill — 2-player multiplayer E2E', () => { test('both clients see the mill board after joining same room', async ({ browser }) => { const p0 = await setupOnlineGame(browser, 'mill'); const p1 = await setupOnlineGame(browser, 'mill'); await joinAsFirstPlayer(p0, '0'); await joinAsFirstPlayer(p1, '1'); // 两 tab 都应能渲染 SVG 棋盘(MillBoard 用 SVG) const svgCount0 = await p0.locator('svg').count(); const svgCount1 = await p1.locator('svg').count(); expect(svgCount0).toBeGreaterThan(0); expect(svgCount1).toBeGreaterThan(0); }); });