feat(chess/ui,e2e): add data-testid to PreviewPane + scaffold visual-builder e2e spec
Tiny preview-pane data-testid added for Playwright targeting (T25 setup), plus an initial e2e spec file covering the visual-mode authoring flow — to be expanded in T25. Spec covers happy path: open editor, toggle to Visual, add on-move from palette, configure nested add-to-attribute, verify preview narrative renders. Real runtime execution against the chess dev server is Wave 4 work.
This commit is contained in:
parent
8fc0582626
commit
159d2cff06
2 changed files with 131 additions and 1 deletions
130
packages/chess/e2e/custom-modifier-visual.spec.ts
Normal file
130
packages/chess/e2e/custom-modifier-visual.spec.ts
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
import { test, expect, type Page } from '@playwright/test';
|
||||||
|
|
||||||
|
const CUSTOM_LIBRARY_KEY = 'houserules:custom-modifiers:v1';
|
||||||
|
const EDITOR_MODE_KEY = 'houserules:custom-modifier-editor-mode:v1';
|
||||||
|
|
||||||
|
async function freshLobby(page: Page): Promise<void> {
|
||||||
|
await page.goto('/');
|
||||||
|
await page.evaluate(
|
||||||
|
({ customKey, modeKey }) => {
|
||||||
|
localStorage.removeItem(customKey);
|
||||||
|
localStorage.removeItem(modeKey);
|
||||||
|
},
|
||||||
|
{ customKey: CUSTOM_LIBRARY_KEY, modeKey: EDITOR_MODE_KEY },
|
||||||
|
);
|
||||||
|
await page.reload();
|
||||||
|
await page.waitForSelector('[data-testid="page-home"]');
|
||||||
|
}
|
||||||
|
|
||||||
|
test.describe('T25 — Custom modifier visual builder e2e', () => {
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await freshLobby(page);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('visual authoring flow: create, save, load', async ({ page }) => {
|
||||||
|
// 1. Open editor
|
||||||
|
await page.getByTestId('profile-picker').selectOption('custom');
|
||||||
|
await expect(page.getByTestId('per-type-panel-paste').or(
|
||||||
|
page.locator('[role="dialog"], .fixed.inset-0').first(),
|
||||||
|
)).toBeVisible({ timeout: 3000 });
|
||||||
|
|
||||||
|
await page.getByTestId('open-custom-modifier-editor').click();
|
||||||
|
await expect(page.getByTestId('custom-modifier-editor')).toBeVisible();
|
||||||
|
|
||||||
|
// 2. Toggle to visual mode
|
||||||
|
await page.getByTestId('custom-modifier-editor-mode-visual').click();
|
||||||
|
|
||||||
|
// Assert visual mode components are visible
|
||||||
|
await expect(page.getByTestId('palette-btn-on-move')).toBeVisible();
|
||||||
|
await expect(page.getByTestId('preview-pane')).toBeVisible();
|
||||||
|
|
||||||
|
// Give it a name
|
||||||
|
await page.getByPlaceholder('Modifier Name').fill('Visual Test Modifier');
|
||||||
|
|
||||||
|
// 3. Add on-move primitive
|
||||||
|
await page.getByTestId('palette-btn-on-move').click();
|
||||||
|
|
||||||
|
// It should appear in the block list
|
||||||
|
const onMoveBlock = page.getByTestId('block-card-on-move');
|
||||||
|
await expect(onMoveBlock).toBeVisible();
|
||||||
|
await expect(onMoveBlock.getByText('On Move')).toBeVisible();
|
||||||
|
|
||||||
|
// 4. Add add-to-attribute inside on-move
|
||||||
|
// Open the block to show dropzones
|
||||||
|
await onMoveBlock.click();
|
||||||
|
await page.getByTestId('palette-btn-add-to-attribute').click();
|
||||||
|
|
||||||
|
// Fill in the add-to-attribute form fields
|
||||||
|
// Target the specific inputs inside the visual builder
|
||||||
|
const attrInput = page.locator('[data-testid="primitive-add-to-attribute-attr-input"]').first();
|
||||||
|
await attrInput.fill('Hp');
|
||||||
|
|
||||||
|
// The delta field is typically a generic input without a testid right now,
|
||||||
|
// so we target the first number input in the inspector panel
|
||||||
|
const deltaInput = page.locator('input[type="number"]').first();
|
||||||
|
await deltaInput.fill('1');
|
||||||
|
|
||||||
|
// 5. Verify preview narrative
|
||||||
|
const previewPane = page.getByTestId('preview-pane');
|
||||||
|
await expect(previewPane).toContainText('When this piece moves');
|
||||||
|
await expect(previewPane).toContainText('add 1 to Hp');
|
||||||
|
|
||||||
|
// Take screenshot of composed state
|
||||||
|
await page.screenshot({ path: '.sisyphus/evidence/task-25-visual-composed.png' });
|
||||||
|
|
||||||
|
// 6. Save to library
|
||||||
|
await page.getByTestId('custom-save').click();
|
||||||
|
await expect(page.getByText('Custom modifier saved to library')).toBeVisible();
|
||||||
|
|
||||||
|
// 7. Reload page
|
||||||
|
await page.reload();
|
||||||
|
await page.waitForSelector('[data-testid="page-home"]');
|
||||||
|
|
||||||
|
// 8. Re-open editor & load
|
||||||
|
await page.getByTestId('profile-picker').selectOption('custom');
|
||||||
|
await expect(page.getByTestId('per-type-panel-paste').or(
|
||||||
|
page.locator('[role="dialog"], .fixed.inset-0').first(),
|
||||||
|
)).toBeVisible({ timeout: 3000 });
|
||||||
|
|
||||||
|
await page.getByTestId('open-custom-modifier-editor').click();
|
||||||
|
await expect(page.getByTestId('custom-modifier-editor')).toBeVisible();
|
||||||
|
|
||||||
|
// Should remember visual mode preference
|
||||||
|
await expect(page.getByTestId('custom-modifier-editor-mode-visual')).toHaveAttribute('aria-pressed', 'true');
|
||||||
|
|
||||||
|
await page.getByTestId('custom-load').click();
|
||||||
|
await page.getByText('Visual Test Modifier').click();
|
||||||
|
|
||||||
|
// 9. Verify loaded structure
|
||||||
|
const loadedBlock = page.getByTestId('block-card-on-move');
|
||||||
|
await expect(loadedBlock).toBeVisible();
|
||||||
|
await expect(loadedBlock.getByText('On Move')).toBeVisible();
|
||||||
|
|
||||||
|
// Open the block to see children
|
||||||
|
await loadedBlock.click();
|
||||||
|
await expect(page.getByText('Add To Attribute')).toBeVisible();
|
||||||
|
await expect(page.locator('[data-testid="primitive-add-to-attribute-attr-input"]').first()).toHaveValue('Hp');
|
||||||
|
await expect(page.locator('input[type="number"]').first()).toHaveValue('1');
|
||||||
|
|
||||||
|
// 10. Negative: try to add beyond max depth (validator prevents save)
|
||||||
|
// Add conditional -> on-capture -> on-damaged
|
||||||
|
// The block list allows arbitrary adding, but validation fails
|
||||||
|
await page.getByTestId('palette-btn-conditional').click();
|
||||||
|
const condBlock = page.getByTestId('block-card-conditional');
|
||||||
|
await condBlock.click();
|
||||||
|
|
||||||
|
await page.getByTestId('palette-btn-on-capture').click();
|
||||||
|
const captureBlock = page.getByTestId('block-card-on-capture');
|
||||||
|
await captureBlock.click();
|
||||||
|
|
||||||
|
await page.getByTestId('palette-btn-on-damaged').click();
|
||||||
|
|
||||||
|
// The validator banner should show depth exceeded
|
||||||
|
await expect(page.getByText(/exceed 3|Fix errors in Form mode/)).toBeVisible();
|
||||||
|
|
||||||
|
// Save should be disabled
|
||||||
|
await expect(page.getByTestId('custom-save')).toBeDisabled();
|
||||||
|
|
||||||
|
await page.screenshot({ path: '.sisyphus/evidence/task-25-visual-validation-error.png' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -18,7 +18,7 @@ export function PreviewPane({ descriptor }: PreviewPaneProps) {
|
||||||
const boardContent = useMemo(() => <BoardDiagramView descriptor={descriptor} />, [descriptor]);
|
const boardContent = useMemo(() => <BoardDiagramView descriptor={descriptor} />, [descriptor]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full overflow-hidden border border-slate-200 rounded-md bg-white">
|
<div data-testid="preview-pane" className="flex flex-col h-full overflow-hidden border border-slate-200 rounded-md bg-white">
|
||||||
<div
|
<div
|
||||||
role="tablist"
|
role="tablist"
|
||||||
className="flex border-b border-slate-200 bg-slate-50"
|
className="flex border-b border-slate-200 bg-slate-50"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue