# lib-core.input-test Test-lib for `lib-core.input` (Tests-as-Libs per ADR-0037). **Version:** 0.1.0 **Lib-ID:** lib-core.input-test **Requires:** lib-core.input v>=0.4.0 **Tags:** test, input ## Topology ```mermaid graph LR this["lib-core.input-test"] lib_core_input["lib-core.input"] this --> lib_core_input engine["engine.*"] this --> engine ``` ## Coverage Statement Per Fault-Injection-Audit-Convention (2026-05-16): | Section | Assertion-Count | Coverage | |---|---|---| | Engine surface presence | 7 | `MOUSE_LEFT/RIGHT/MIDDLE` constants, `is_mouse_down`, `was_mouse_pressed`, `was_released`, `was_mouse_released` | | `bind` mouse-strings | 1 | `action_count == 1` after `bind("click", {"mouse_left"})` | | `bind` mixed key+mouse | 1 | `action_count == 2` after mixed bind `{"e", "mouse_left"}` | | `bind` rejects unknown mouse-name | 3 | Lua error raised, message mentions bad string, no partial state mutation | | Headless query stubs | 4 | `is_action_down`, `was_action_pressed`, `was_action_released` return false; `was_action_released` for unknown returns false | | Key-only regression | 1 | `bind("walk_left", {"a","left"})` still works after BIND_MAP refactor | | **TOTAL** | **17** | | ### Tested-Surface - `input.bind` (mouse-string acceptance, mixed key+mouse, unknown-name rejection, atomicity) - `input.action_count` - `input.is_action_down` (bound action headless = false) - `input.was_action_pressed` - `input.was_action_released` (bound action headless = false; unknown action = false) - Engine surface: `MOUSE_LEFT/RIGHT/MIDDLE`, `is_mouse_down`, `was_mouse_pressed`, `was_released`, `was_mouse_released` function presence ### Fault-Injection Audit (2026-05-16) Verified via deliberate-mutation in fixture-mirror; mutations reverted after observation. #### Caught Mutations | # | Mutation | Caught by | |---|---|---| | M1 | `function M.was_action_released` renamed (API-break) | Runtime error "attempt to call a nil value (field 'was_action_released')" — test aborts after assertion 14 | | M2 | `if not entries then return false end` changed to `return nil` | `was_action_released for unknown action returns false` fails (`not ok`, got nil) | #### Uncaught Mutations (Gaps) | # | Mutation | Why uncaught | Severity | |---|---|---|---| | M3 | Dispatch-swap in `was_action_released` for-loop (key-kind ↔ mouse-kind) | Headless: all input queries return false regardless of swapped dispatch — no real events differentiate the paths | Med | **Resolution:** Headless-unreachable. Requires real key/mouse events. Future-Slice B: integration test with simulated input events. No cheap headless fill possible. ### Structurally Untestable - Real keyboard/mouse event delivery — headless mode never produces input events. - `was_action_released` dispatch correctness for key-kind vs mouse-kind binding — see Gap M3. ### Deferred - Integration test with simulated input events (Future-Slice B). ## Running Via `--test-libs=lib-core.input-test` (Smoke P0-S-batch Stage): ```bash Sporel.exe --libs-dir= --test-libs=lib-core.input-test ``` Output is TAP version 13 on stdout; exit-code = failure-count (0 = all pass). ## References - ADR-0037 (Tests-as-Libs Convention) - ADR-0038 (API-Doc-Convention) - Production-Lib: `~/Projects/Sporel/sporel-libs/lib-core/input/README.md` - Spec: `meta/docs/superpowers/specs/2026-05-12-p3-3-mouse-input-design.md`