Skip to content

test(pwa): migrate keyboard-shortcut logic from e2e to unit tests#247

Merged
korbinian90 merged 3 commits into
mainfrom
claude/migrate-keyboard-shortcuts-to-unit
Jun 17, 2026
Merged

test(pwa): migrate keyboard-shortcut logic from e2e to unit tests#247
korbinian90 merged 3 commits into
mainfrom
claude/migrate-keyboard-shortcuts-to-unit

Conversation

@korbinian90

Copy link
Copy Markdown
Collaborator

First migration under the unit-first test-placement policy from #241 (and documented in #245). The keyboard-shortcuts e2e was the clearest offender: 16 specs, each paying for a full WebGL image load in beforeEach, just to assert that a keypress flips a signal - pure handler logic that needs no GPU.

What moved

To unit tests (packages/niivue-react/src/test/):

  • useKeyboardShortcuts.test.tsx (new): mounts the hook and dispatches real KeyboardEvents in jsdom, asserting
    • every key → handler mapping (1-6, v, c, arrows, r, i, b, x, m, z, s, u, Shift+U/D, Ctrl+L, Ctrl+Shift+O/H);
    • exactly-one routing, so modifier disambiguation is proven (e.g. u → hide UI vs Shift+u → crosshair superior);
    • the INPUT / TEXTAREA / contentEditable focus guard;
    • the enabled flag, listener cleanup on unmount, and missing-handler no-ops.
  • keyboardShortcuts.test.ts (extended): formatShortcut, plus a real-registry disambiguation check for the shared u key.

Kept in e2e (apps/pwa/tests/keyboard-shortcuts.spec.ts): a single end-to-end smoke - a real keypress drives sliceType, and focus in a text input suppresses it. That is the one claim a unit test can't make: the hook is actually mounted and wired in the running app.

Why

Per the placement policy: the key→action mapping and the focus guard are pure/component-local logic; only "the hook is wired in the real app" is genuine integration. The smell test in the README literally named this file.

Impact

  • ~15 real WebGL loads removed from the serial e2e lane.
  • Keyboard coverage is now deterministic and millisecond-scale (the unit test bodies run in ~80ms) instead of seconds-per-test under software WebGL.
  • Coverage is also more precise: the unit tests assert exactly-one-handler routing, which the e2e never did.

Verification

  • @niivue/react: 120 unit tests pass (10 files).
  • turbo lint type-check: green.
  • e2e smoke passes on SwiftShader (same backend as CI).

Relationship to other PRs

🤖 Generated with Claude Code

…low-up)

First migration under the unit-first test-placement policy. The keyboard
shortcuts e2e paid for a full WebGL image load in every test just to assert that
a keypress flips a signal - pure handler logic that needs no GPU.

- Add useKeyboardShortcuts.test.tsx: mounts the hook and dispatches real
  KeyboardEvents in jsdom, asserting every key -> handler mapping (1-6, v, c,
  arrows, r, i, b, x, m, z, s, u, Shift+U/D, Ctrl+L, Ctrl+Shift+O/H), exactly-one
  routing (modifier disambiguation, e.g. u vs Shift+U), the input/textarea/
  contentEditable focus guard, the enabled flag, listener cleanup on unmount, and
  missing-handler no-ops. The test bodies run in ~80ms.
- Extend keyboardShortcuts.test.ts: formatShortcut, plus a real-registry
  disambiguation check for the shared "u" key.
- Slim keyboard-shortcuts.spec.ts from 16 WebGL-loading specs to a single
  end-to-end smoke: a real keypress drives sliceType, and focus in a text input
  suppresses it. That is the one claim a unit test cannot make (the hook is
  actually mounted and wired in the running app); the logic itself is now covered
  far faster and more precisely by the unit tests above.

Net: ~15 real WebGL loads removed from the serial e2e lane; comprehensive
keyboard coverage moved to deterministic millisecond-scale unit tests.

Verified: @niivue/react 120 unit tests pass; lint + type-check green; the e2e
smoke passes on SwiftShader.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

🚀 PWA Preview Deployment

Your PWA preview has been deployed!

Preview URL: https://niivue.github.io/niivue-vscode/pr-247/


This preview will be updated automatically when you push new commits to this PR.

github-actions Bot added a commit that referenced this pull request Jun 14, 2026
@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

coverage

Overall line coverage: 40.7% (+2.2) vs main

Package Statements Branches Functions Lines
Shared core (packages/niivue-react) 44.1% (+2.9) 45.8% (+3.1) 44.7% (−1.1) 44.7% (+3)
apps/pwa 28.9% 33.3% 52.9% 30.2%
apps/jupyter 14.4% 15.9% 14.9% 14.5%
apps/streamlit 17.8% 5.3% 18.5% 17.7%
apps/vscode 38.7% 39.6% 18.9% 38.1%
apps/desktop-tauri 81.8% 59.1% 78.9% 84.3%

📊 View full report →

…-up)

Addresses critical-review feedback on the keyboard migration:
- The hook test asserts key->handler, and the e2e smoke only checked 1->AXIAL,
  so the handler->value wiring (4->RENDER, 5->MULTIPLANAR, the cycleViewMode %5
  wrap, cycleUIVisibility 3->2->0->3) was asserted nowhere. Add Menu.test.tsx
  cases that dispatch keydowns at a rendered <Menu> and assert the resulting
  sliceType / hideUI values - no WebGL load.
- Fix an off-by-one in the smoke comment (the replaced matrix was 15 specs).

@niivue/react: 123 unit tests pass; type-check green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
github-actions Bot added a commit that referenced this pull request Jun 14, 2026
Resolve the conflict in apps/pwa/tests/keyboard-shortcuts.spec.ts. Keep the e2e->unit migration (the single wiring smoke test) and preserve #242's #224 clip-plane regression as an integration test: that NiiVue's built-in clipPlaneHotKey is disabled so one 'c' press is one step is a claim the jsdom hook unit test cannot make (it has no real NiiVue canvas).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
github-actions Bot added a commit that referenced this pull request Jun 17, 2026
@korbinian90 korbinian90 merged commit 8453d09 into main Jun 17, 2026
13 checks passed
github-actions Bot added a commit that referenced this pull request Jun 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🧹 PWA Preview Cleanup

The preview deployment for this PR has been removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant