From a35b69896628dd2185295b3fa20364e0744434f7 Mon Sep 17 00:00:00 2001 From: Tim Morgan Date: Mon, 15 Jun 2026 22:59:32 -0700 Subject: [PATCH] Move per-test game reset into a fixture and extract play-word flow Address two e2e structure findings in the gameplay spec: - Replace the inlined per-test reset (goto + clear localStorage + reload) in beforeEach with an injected auto-fixture (resetGame) in fixtures.ts, so lifecycle setup is owned by a Playwright fixture rather than the spec. - Extract the duplicated per-word play loop (find tiles, click them, add, wait for the current word to clear) into a playWord/playWords flow helper composed from the existing GameBoardPage primitives, and use it in both the "all fourtiles" and "all words" beforeEach blocks. The thin star and found-words page objects are left unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) --- e2e/fixtures.ts | 14 ++++++++++++++ e2e/game-flows.ts | 34 ++++++++++++++++++++++++++++++++++ e2e/gameplay.spec.ts | 23 ++++------------------- 3 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 e2e/game-flows.ts diff --git a/e2e/fixtures.ts b/e2e/fixtures.ts index a09071c..422934d 100644 --- a/e2e/fixtures.ts +++ b/e2e/fixtures.ts @@ -7,6 +7,9 @@ interface Fixtures { board: GameBoardPage foundWordsPanel: FoundWordsPanel stars: FourtileStarsPanel + // Auto-fixture that resets game state per test; it exposes no value to specs. + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + resetGame: void } export const test = base.extend({ @@ -19,6 +22,17 @@ export const test = base.extend({ stars: async ({ page }, use) => { await use(new FourtileStarsPanel(page)) }, + resetGame: [ + async ({ page }, use) => { + await page.goto('/') + await page.evaluate(() => { + localStorage.clear() + }) + await page.reload() + await use() + }, + { auto: true }, + ], }) export { expect } from '@playwright/test' diff --git a/e2e/game-flows.ts b/e2e/game-flows.ts new file mode 100644 index 0000000..1eb2273 --- /dev/null +++ b/e2e/game-flows.ts @@ -0,0 +1,34 @@ +import { expect } from '@playwright/test' +import type { Page } from '@playwright/test' +import type { GameBoardPage } from './pages/GameBoardPage' +import { tilesForWordFromPage } from './game-helpers' + +/** + * Plays a single word: resolves the tiles that spell it, clicks them, clicks + * Add, and waits for the current word to clear before returning. + */ +export async function playWord( + page: Page, + board: GameBoardPage, + word: string, + timeout?: number, +): Promise { + const wordTiles = await tilesForWordFromPage(page, word) + await board.clickTiles(wordTiles) + await board.clickAdd() + await expect(board.getCurrentWord()).toHaveText('', timeout ? { timeout } : undefined) +} + +/** + * Plays every word in {@link words} in order, one after another. + */ +export async function playWords( + page: Page, + board: GameBoardPage, + words: string[], + timeout?: number, +): Promise { + for (const word of words) { + await playWord(page, board, word, timeout) + } +} diff --git a/e2e/gameplay.spec.ts b/e2e/gameplay.spec.ts index 85f530f..fe7ee29 100644 --- a/e2e/gameplay.spec.ts +++ b/e2e/gameplay.spec.ts @@ -6,18 +6,13 @@ import { fourtiles, tiles, words, - tilesForWordFromPage, } from './game-helpers' +import { playWords } from './game-flows' test.describe('Gameplay', () => { let wordsRemaining: number - test.beforeEach(async ({ page, foundWordsPanel }) => { - await page.goto('/') - await page.evaluate(() => { - localStorage.clear() - }) - await page.reload() + test.beforeEach(async ({ foundWordsPanel }) => { wordsRemaining = parseInt(await foundWordsPanel.getWordsRemaining().innerText(), 10) }) @@ -114,12 +109,7 @@ test.describe('Gameplay', () => { test.beforeEach(async ({ page, board }) => { fourtileWords = await fourtiles(page) - for (const fourtile of fourtileWords) { - const tiles = await tilesForWordFromPage(page, fourtile) - await board.clickTiles(tiles) - await board.clickAdd() - await expect(board.getCurrentWord()).toHaveText('') - } + await playWords(page, board, fourtileWords) }) test('pops confetti', async ({ page }) => { @@ -152,12 +142,7 @@ test.describe('Gameplay', () => { test.beforeEach(async ({ page, board }) => { const allWords = await words(page) - for (const word of allWords) { - const wordTiles = await tilesForWordFromPage(page, word) - await board.clickTiles(wordTiles) - await board.clickAdd() - await expect(board.getCurrentWord()).toHaveText('', { timeout: 10_000 }) - } + await playWords(page, board, allWords, 10_000) }) test('pops confetti and unicorns', async ({ page }) => {