+ Board preview (T22) +
+diff --git a/packages/chess/e2e/modifier-profiles.spec.ts b/packages/chess/e2e/modifier-profiles.spec.ts new file mode 100644 index 0000000..a9c5240 --- /dev/null +++ b/packages/chess/e2e/modifier-profiles.spec.ts @@ -0,0 +1,55 @@ +/** + * E2E — Modifier Profile Editor shell (T18). + * + * Verifies: + * 1. The editor modal opens from the Rules drawer. + * 2. Pressing Escape closes the editor. + * + * Runs against the local dev server (no WS server needed — solo play only). + */ +import { test, expect } from '@playwright/test'; + +test.describe('Modifier Profiles', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/'); + + // Clear any stale autosave so Play Solo starts a fresh game. + await page.evaluate(() => { + for (let i = localStorage.length - 1; i >= 0; i--) { + const key = localStorage.key(i); + if (key !== null && key.startsWith('paratype-chess:v2:autosave:')) { + localStorage.removeItem(key); + } + } + localStorage.removeItem('paratype-chess:v1:autosave'); + }); + + // Navigate into the game view. + await page.locator('[data-action="play-solo"]').click(); + await page.waitForURL('**/game'); + + // Open the rules drawer so the modifier editor button is accessible. + await page.locator('[data-action="open-rules-drawer"]').click(); + await expect(page.getByTestId('rules-drawer')).toBeVisible(); + }); + + test('editor opens from rules drawer', async ({ page }) => { + await page.click('[data-testid="open-modifier-editor"]'); + await expect( + page.locator('[data-testid="modifier-editor-modal"]'), + ).toBeVisible({ timeout: 1000 }); + }); + + test('esc closes modifier editor', async ({ page }) => { + await page.click('[data-testid="open-modifier-editor"]'); + await expect( + page.locator('[data-testid="modifier-editor-modal"]'), + ).toBeVisible(); + + await page.keyboard.press('Escape'); + + await expect( + page.locator('[data-testid="modifier-editor-modal"]'), + ).not.toBeVisible({ timeout: 500 }); + }); +}); diff --git a/packages/chess/src/ui/ModifierProfileEditor.tsx b/packages/chess/src/ui/ModifierProfileEditor.tsx new file mode 100644 index 0000000..c431811 --- /dev/null +++ b/packages/chess/src/ui/ModifierProfileEditor.tsx @@ -0,0 +1,80 @@ +/** + * Modifier Profile Editor — modal shell. + * + * Shell only: three placeholder panels filled by later tasks: + * T21 — modifier catalog (left panel) + * T22 — board preview (center panel) + * T23 — profile list (right panel) + * + * Follows the same overlay/close pattern as LayoutEditor.tsx. + */ +import { useEffect } from 'react'; + +interface Props { + isOpen: boolean; + onClose: () => void; +} + +export function ModifierProfileEditor({ isOpen, onClose }: Props) { + // Register Esc listener only while the modal is visible. + useEffect(() => { + if (!isOpen) return; + function handleKeyDown(e: KeyboardEvent) { + if (e.key === 'Escape') onClose(); + } + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [isOpen, onClose]); + + if (!isOpen) return null; + + return ( +
+ Board preview (T22) +
+