//! Quick-toggle routing coverage for client input aggregation. //! //! Scope: include the input aggregator source and exercise swap-key edge //! detection without creating real input devices. //! Targets: `client/src/input/inputs.rs`. //! Why: the swap key must not flap routing when held or bounced. mod layout { pub use lesavka_client::layout::*; } mod keyboard { pub use lesavka_client::input::keyboard::*; } mod mouse { pub use lesavka_client::input::mouse::*; } #[allow(warnings)] mod inputs_toggle_contract { include!(env!("LESAVKA_CLIENT_INPUTS_SRC")); fn new_aggregator() -> InputAggregator { let (kbd_tx, _) = tokio::sync::broadcast::channel(32); let (mou_tx, _) = tokio::sync::broadcast::channel(32); InputAggregator::new(false, kbd_tx, mou_tx, None) } #[test] fn observe_quick_toggle_uses_rising_edge_to_avoid_repeat_toggling() { let mut agg = new_aggregator(); agg.quick_toggle_debounce = Duration::from_millis(0); agg.observe_quick_toggle(true); assert!( agg.pending_release, "first quick-toggle should switch from remote to local pending-release mode" ); assert!(!agg.released); agg.observe_quick_toggle(true); assert!( agg.pending_release, "holding the quick-toggle key should not retrigger mode switching" ); agg.released = true; agg.pending_release = false; agg.observe_quick_toggle(false); agg.observe_quick_toggle(true); assert!( !agg.released, "second rising edge should return to remote mode" ); assert!( !agg.pending_release, "remote-mode transition should clear pending release state" ); } #[test] fn observe_quick_toggle_honors_debounce_window() { let mut agg = new_aggregator(); agg.quick_toggle_debounce = Duration::from_secs(60); agg.released = true; agg.pending_release = false; agg.observe_quick_toggle(true); assert!(!agg.released, "first edge should switch to remote"); agg.released = true; agg.pending_release = false; agg.observe_quick_toggle(false); agg.observe_quick_toggle(true); assert!( agg.released, "second edge inside debounce window should be ignored" ); } }