test: Add edge case coverage for Mapper state machine#2
test: Add edge case coverage for Mapper state machine#2
Conversation
- Created mod edge_case_tests inside mapper.rs test module - Implemented test_rapid_typing_reset_tilde_cedilla: documents current behavior when dead key followed by non-character key - Implemented test_rapid_typing_reset_tilde_with_combinable: verifies dead key + combinable char sequence - Implemented test_double_dead_key_sequence_tilde_then_circumflex: tests two dead keys in a row - Implemented test_double_dead_key_sequence_acute_then_grave: tests another double dead key combo - Implemented test_backspace_cancels_pending_accent: marked as #[ignore] with FIXME comment (feature missing) - Implemented test_timeout_boundary_before_timeout: verifies 499ms doesn't trigger timeout - Implemented test_timeout_boundary_at_timeout: verifies 500ms triggers timeout - Implemented test_timeout_boundary_after_timeout: verifies 501ms triggers timeout - Implemented test_timeout_with_no_pending_accent: verifies no timeout in Idle state - Implemented test_multiple_rapid_dead_keys_with_combinable: tests rapid sequence of dead key combinations - Implemented test_dead_key_with_shifted_character: verifies shifted character combinations - Implemented test_reset_clears_pending_accent: verifies reset() clears pending state - All tests pass (22 passed mapper tests, 26 total including state tests) - 1 test ignored for backspace handling feature that's not yet implemented - Code formatted with cargo fmt - No clippy warnings Co-authored-by: marcelocra <2532492+marcelocra@users.noreply.github.com>
Greptile OverviewGreptile SummaryAdded comprehensive edge case test coverage for the Mapper state machine without modifying production code. Tests cover rapid typing transitions, double dead key sequences, timeout boundaries, state resets, and capital letter combinations. Key additions:
Issues documented in tests:
All tests follow Rust idioms with clear comments. No production logic modified per constraints. Test suite: 26 passing, 1 ignored. Confidence Score: 4/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant User
participant Mapper
participant State as MapperState
Note over Mapper,State: Initial State: Idle
User->>Mapper: Press Apostrophe (dead key)
Mapper->>State: Check get_dead_key_accent()
State-->>Mapper: Some(AccentType::Tilde)
Mapper->>State: Set PendingAccent(Tilde)
Mapper->>Mapper: Record last_accent_time
Mapper-->>User: KeyAction::Suppress
Note over Mapper,State: State: PendingAccent(Tilde)
alt Combinable character pressed
User->>Mapper: Press 'a'
Mapper->>Mapper: process_pending_accent()
Mapper->>Mapper: Check accent_combinations[(Tilde, 'a')]
Mapper->>State: Reset to Idle
Mapper-->>User: KeyAction::Replace('ã')
else Non-combinable character
User->>Mapper: Press 'x'
Mapper->>Mapper: process_pending_accent()
Mapper->>State: Reset to Idle
Mapper-->>User: KeyAction::ReplaceMultiple(['~', 'x'])
else Space pressed
User->>Mapper: Press Space
Mapper->>Mapper: process_pending_accent()
Mapper->>State: Reset to Idle
Mapper-->>User: KeyAction::Replace('~')
else Timeout occurs (500ms)
Mapper->>Mapper: check_timeout()
Mapper->>State: Reset to Idle
Mapper-->>User: KeyAction::Replace('~')
end
Note over Mapper,State: Back to State: Idle
|
| fn test_double_dead_key_sequence_tilde_then_circumflex() { | ||
| let mut mapper = Mapper::new(); | ||
|
|
||
| // Press apostrophe (tilde dead key) | ||
| assert_eq!( | ||
| mapper.process_key(VirtualKey::Apostrophe, false), | ||
| KeyAction::Suppress | ||
| ); | ||
| assert_eq!( | ||
| mapper.state(), | ||
| &MapperState::PendingAccent(AccentType::Tilde) | ||
| ); | ||
|
|
||
| // Press Shift+apostrophe (circumflex dead key) | ||
| // This should output the tilde character and enter pending circumflex state | ||
| assert_eq!( | ||
| mapper.process_key(VirtualKey::Apostrophe, true), | ||
| KeyAction::Replace('~') | ||
| ); | ||
| // The state should now be pending the second dead key (circumflex) | ||
| // However, based on the code, process_pending_accent returns to Idle | ||
| // and doesn't recognize the second dead key | ||
| assert_eq!(mapper.state(), &MapperState::Idle); | ||
| } |
There was a problem hiding this comment.
logic: Double dead key test reveals logic issue: when second dead key pressed during PendingAccent, the process_pending_accent method outputs first accent and returns to Idle, but doesn't recognize the second key as a dead key. The second dead key should enter a new PendingAccent state.
Current flow: PendingAccent(Tilde) → press Shift+Apostrophe → outputs tilde → Idle
Expected: PendingAccent(Tilde) → press Shift+Apostrophe → outputs tilde → PendingAccent(Circumflex)
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mapper.rs
Line: 555:578
Comment:
**logic:** Double dead key test reveals logic issue: when second dead key pressed during `PendingAccent`, the `process_pending_accent` method outputs first accent and returns to `Idle`, but doesn't recognize the second key as a dead key. The second dead key should enter a new `PendingAccent` state.
Current flow: `PendingAccent(Tilde)` → press `Shift+Apostrophe` → outputs tilde → `Idle`
Expected: `PendingAccent(Tilde)` → press `Shift+Apostrophe` → outputs tilde → `PendingAccent(Circumflex)`
How can I resolve this? If you propose a fix, please make it concise.
The Mapper state machine lacked test coverage for edge cases that could cause issues during high-speed typing: rapid dead key sequences, timeout boundaries, and state transitions.
Added Tests
Created
mod edge_case_testswith 11 tests covering:~then;→ç), dead key → combinable char~then^), verifies first accent flushes and state returns to IdleDocumented Behavior
One test marked
#[ignore]with FIXME for backspace cancellation (VirtualKey::Backspace doesn't exist yet).Test
test_rapid_typing_reset_tilde_cedilladocuments current limitation: pressing a mapped non-character key (e.g., Semicolon) while in PendingAccent state outputs only the accent, losing the key's normal mapping.No production code modified. Test suite: 26 passing, 1 ignored.
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
esm.ubuntu.com/usr/lib/apt/methods/https /usr/lib/apt/methods/https --emit=dep-info,link -C embed-bitcode=no --check-cfg cfg(docsrs,test) --check-cfg cfg(feature, values("v2_58", "v2_60", "v2_62", "v2_64", "v2_66", "v2_68", "v2_70", "v2_72", "v2_74", "v2_76", "v2_78")) -C metadata=d83cbe02d554bdc1 -C extra-filename=-8ace987977ada77f 41f6�� 29d01.rlib 60.rlib or-01289695c6f27cd2/build_script_build-01289695c6f27cd2.build_script_build.252b444ab60b723c-cgu./home/REDACTED/work/ghostkeys/ghostkeys/target/debug/deps/yoke_derive-bc7479134a68-pie or-01289695c6f27/home/REDACTED/.rustup/toolchains/stable-x86_64-REDACTED-linux-gnu/bin/rustc _build.aed1b9c8f--crate-name s1qvxo6ey79os.rcbuild_script_build lib/rustlib/x86_--edition=2021(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.