import { test, expect } from '@playwright/test'; /** * Fully deterministic end-to-end test. The Playwright webServer boots the real * stack (Vite :5173 → Express :4321) with LLM_STUB=1, so the backend uses the * deterministic turn simulator in server/stub.ts: the player nation's `military` * stat is set to (current + 5, clamped) each turn and exactly one event is * emitted (action → military, chat → diplomatic, jump → political). There is no * live LLM and no flakiness — every assertion below is an exact, predicted value. */ test.describe('History — deterministic simulation (LLM_STUB=1)', () => { test('scenario → nation → action → jump, with predicted stat changes', async ({ page }) => { await page.goto('/'); // Home: the scenario grid loads with all 5 presets. const presetCards = page.getByTestId('preset-card'); await expect(presetCards.first()).toBeVisible(); await expect(presetCards).toHaveCount(5); // Start the first scenario (World War II, 1939). await presetCards.first().getByRole('button', { name: 'Play' }).click(); // Nation select: the world brief is shown, then we lead the United Kingdom. await expect(page.getByTestId('world-background')).toBeVisible(); await page .getByTestId('nation-card-uk') .getByRole('button', { name: 'Play as United Kingdom' }) .click(); // Game screen mounts: map, command deck, and event feed all present; turn 1. await expect(page.getByTestId('world-map')).toBeVisible(); await expect(page.getByTestId('action-panel')).toBeVisible(); await expect(page.getByTestId('event-feed-panel')).toBeVisible(); await expect(page.getByTestId('turn-count')).toHaveText('1'); // The player (UK) starts at military 80, with no events yet. const military = page.getByTestId('stat-military'); await expect(military).toHaveText('80'); await expect(page.getByTestId('event-item')).toHaveCount(0); // Take an action: the stub bumps UK military to 85 and emits a military event. await page.getByTestId('action-textarea').fill('Mobilize the home guard and fortify Dover'); await page.getByTestId('action-submit').click(); await expect(page.getByTestId('turn-count')).toHaveText('2', { timeout: 20000 }); await expect(military).toHaveText('85', { timeout: 20000 }); await expect(page.getByTestId('event-item')).toHaveCount(1); await expect( page.getByTestId('event-feed').getByText('Mobilize the home guard and fortify Dover').first(), ).toBeVisible(); // Jump forward (no action): a "world moves on" political event, military → 90. await page.getByTestId('jump-forward').click(); await expect(page.getByTestId('turn-count')).toHaveText('3', { timeout: 20000 }); await expect(military).toHaveText('90', { timeout: 20000 }); await expect(page.getByTestId('event-item')).toHaveCount(2); await expect(page.getByTestId('event-feed').getByText('The world moves on').first()).toBeVisible(); }); });