Testing¶
The project uses Node’s built-in test runner, Python’s unittest, and browser-based visual QA. Runtime code has no third-party packages, so a clean checkout can run both automated suites without installing dependencies.
Automated checks¶
Run all JavaScript and Python unit and contract tests:
npm test
Run CSS-bundle, JavaScript-syntax, asset-reference, and release-hygiene checks:
npm run check
Run every automated check and test together:
npm run verify
Documentation dependencies are isolated from the runtime. After installing
docs/requirements.txt in a virtual environment, build the complete site with
warnings treated as errors:
npm run docs:build
The dedicated documentation workflow runs that strict build for relevant pull
requests and main updates, then stores the generated HTML as a private
workflow artifact.
The check command also confirms that styles/app.css matches its ordered sources, local assets resolve, and generated review output or private workspace paths have not entered the release tree. npm test runs test:js first and then test:feedback; a failure in either suite fails npm run verify.
Run one suite while developing a focused change:
node --test tests/chess.test.js
node --test tests/hints.test.js
node --test tests/hints-css.test.js
node --test tests/board-input.test.js
node --test tests/endgame-choreography.test.js
node --test tests/feedback.test.js
python3 -m unittest discover -s feedback/tests -p 'test_*.py'
Coverage by suite¶
tests/chess.test.js: FEN parsing, legal move generation, standard move-tree counts, king safety, clocks, history, defensive snapshots, castling, en passant, promotion, terminal states, deterministic hint analysis, legal principal variations, search, and undo.tests/hints.test.js: factual hint wording, searched-line notation, score perspective, terminal continuations, and themed vocabulary.tests/hints-css.test.js: 3D-safe FROM/TO markers, distinct source and destination treatment, and untruncated counsel layout.tests/board-input.test.js: SVG event delegation, piece overhangs, perspective seams, enlarged legal targets, touch slop, and focus restoration.tests/pieces.test.js: public renderer fallbacks and unique role output.tests/readability.test.js: large-scale silhouette markers and geometric distinction.tests/structural-live.test.js: structural SVG hooks, unique paint identifiers, articulation, and weapon-contact contracts.tests/endgame-choreography.test.js: pure outcome descriptions for wins, losses, local games, stalemate, and non-terminal positions.tests/feedback.test.js: client normalization, request shape, validation, rate-limit copy, focus, cancellation, duplicate-submit protection, error recovery, accessible markup, and nonintrusive placement.tests/documentation.test.js: complete Sphinx source, mixed Markdown/reStructuredText configuration, pinned dependencies, strict local and CI entry points, private artifact handling, and generated-output exclusions.feedback/tests/test_server.py: strict HTTP and JSON contracts, Unicode sanitization, private database files, privacy-preserving storage, retention, real storage limits, deduplication, multi-window rate limits, health, and periodic maintenance.feedback/tests/test_manage.py: counts, privacy-safe JSON Lines export, scrubbed online backups, integrity failures, and retention pruning.tests/deployment*.test.js: private routing, immutable deployment, isolated networkless backup jobs, read-only live-data access during backup, rollback safety, and container hardening.
The markup tests intentionally verify stable classes and data attributes used by CSS and animation code. If a structural hook changes, update the renderer, every consumer, and the relevant contract assertion together.
Manual browser checklist¶
Start the app with npm start, then check the following before publishing a visual or interaction change:
Begin a computer duel as Ivory and as Obsidian; confirm the arrival starts only after Begin the duel.
Start a local two-player duel and verify board orientation, rail labels, move status, and Undo.
Select and move each role in 3D and flat views. Confirm source and destination targets remain easy to activate.
Trigger a melee capture and a magical capture. Check approach, weapon contact, defender reaction, matchup text, and Skip duel.
Skip movement and combat with Escape and with the visible button; verify the final engine position and keyboard focus.
Exercise castling, en passant, and each promotion choice.
Reveal a hint and confirm distinct FROM/TO markers, a three-ply explanation, and unchanged 3D piece structure. Select FROM, flip the board, and toggle flat view; the roles and persistent counsel must remain. A different selection or move attempt must clear them.
Reach check, checkmate, and stalemate positions; verify announcements and closing-scene skip behavior.
Fill both captured-piece courts beyond eight pieces and check that the pieces remain inside the board frame.
Resize during movement and inspect desktop, tablet, and 320-pixel-wide phone layouts for clipping or overlap.
Enable the operating system’s reduced-motion preference and confirm long cinematics are bypassed or settled.
Find Provide feedback in the footer at desktop and 320-pixel phone widths; confirm it never floats over the board, combat controls, or toast.
Open the feedback dialog with a keyboard, move through every labeled control, then close it with both the close button and Escape. Confirm focus returns to the footer trigger and an active game animation is not skipped behind the dialog.
Exercise the category choices, live character count, too-short input, 2,000-character boundary, slow submit, duplicate click, and offline failure. Errors must keep the draft and remain announced without rendering server response content.
Against a disposable local API or controlled test deployment, submit successfully and confirm the dialog resets, closes, and announces success. Do not use production feedback data as a manual test fixture.
Visual QA script¶
scripts/visual-qa.mjs runs the responsive browser checks, captures representative combat phases, and records layout and depth diagnostics in the chosen output directory. It requires Node.js 22 or newer and Google Chrome, and talks to Chrome DevTools directly without a browser-automation package:
npm start
node scripts/visual-qa.mjs --out /tmp/enchanted-board-qa --viewport all --combat --hud-stress
node scripts/visual-qa.mjs --out /tmp/enchanted-board-hints --viewport all --hint
The --hint pass asserts exact d2-to-d4 endpoints, stable structural source nodes,
visible and accessible FROM/TO roles, untruncated explanatory counsel, source-selection
persistence, board-flip persistence, and flat-view persistence.
If Chrome is installed somewhere other than /usr/bin/google-chrome, pass its executable path with --chrome. Run node scripts/visual-qa.mjs --help for viewport, intro, hint, casualty, and stress options.
Screenshots are review artifacts, not assertions by themselves. Pair them with the JSON metrics and inspect representative approach, parry, impact, and aftermath frames. Keep generated output outside the repository.
Adding tests¶
Prefer an externally observable result over a private method assertion.
Assert that rejected operations do not mutate FEN, history, or focus state.
Cover both colors for asymmetric chess rules such as pawn movement and castling.
Verify undo whenever a move touches more than its source and destination squares.
Keep DOM-free logic in pure functions where practical so it can run under Node without a simulated browser.
Treat any feedback schema change as a client, service, SQLite constraint, test, and documentation change.
Test feedback suppression without asserting a distinguishable public response; honeypot, duplicate, and rate-limit no-ops intentionally share the generic
202response.Name regressions after the behavior a user relies on, not after implementation details.