using CursorLang.Models; using CursorLang.Services; using CursorLang.Tests.Infrastructure; namespace CursorLang.Tests.Services; /// /// What happens on Caps Lock presses and how the interception follows the setting. /// public sealed class CapsLockSwitchCoordinatorTests { [Fact] public void With_the_setting_on_the_interception_starts_at_once() { var hotkey = new FakeCapsLockHotkeyService(); using CapsLockSwitchCoordinator coordinator = Create(hotkey, new AppSettings { UseCapsLockHotkey = true }); coordinator.Start(); Assert.True(hotkey.IsRunning); Assert.Equal(1, hotkey.StartCalls); } [Fact] public void With_the_setting_off_there_is_no_interception() { var hotkey = new FakeCapsLockHotkeyService(); using CapsLockSwitchCoordinator coordinator = Create(hotkey, new AppSettings { UseCapsLockHotkey = false }); coordinator.Start(); Assert.False(hotkey.IsRunning); Assert.Equal(1, hotkey.StopCalls); } [Fact] public void Ticking_the_setting_turns_the_interception_on_live() { var hotkey = new FakeCapsLockHotkeyService(); var settings = new AppSettings { UseCapsLockHotkey = false }; using CapsLockSwitchCoordinator coordinator = Create(hotkey, settings); coordinator.Start(); settings.UseCapsLockHotkey = true; Assert.True(hotkey.IsRunning); } [Fact] public void Unticking_the_setting_gives_the_key_its_usual_behaviour_back() { var hotkey = new FakeCapsLockHotkeyService(); var settings = new AppSettings { UseCapsLockHotkey = true }; using CapsLockSwitchCoordinator coordinator = Create(hotkey, settings); coordinator.Start(); settings.UseCapsLockHotkey = false; Assert.False(hotkey.IsRunning); } // The interception only follows its own setting [Fact] public void Other_settings_leave_the_interception_alone() { var hotkey = new FakeCapsLockHotkeyService(); var settings = new AppSettings { UseCapsLockHotkey = true }; using CapsLockSwitchCoordinator coordinator = Create(hotkey, settings); coordinator.Start(); int startsBefore = hotkey.StartCalls; int stopsBefore = hotkey.StopCalls; settings.FontSize = 44; settings.CapsLockHoldMilliseconds = 700; Assert.Equal(startsBefore, hotkey.StartCalls); Assert.Equal(stopsBefore, hotkey.StopCalls); } [Fact] public void A_short_press_switches_the_layout() { var hotkey = new FakeCapsLockHotkeyService(); var layouts = new FakeKeyboardLayoutService(); var popup = new FakeLayoutPopupService(); using var coordinator = new CapsLockSwitchCoordinator( hotkey, layouts, popup, new AppSettings { UseCapsLockHotkey = true }); coordinator.Start(); hotkey.RaiseTapped(); Assert.Equal(1, layouts.SwitchCalls); Assert.Empty(popup.Shown); Assert.Empty(popup.ShownUntilHidden); } // The layout stays put, but staying silent is not an option either: without // a tooltip a long press looks like a key that did not work [Fact] public void A_long_press_shows_the_current_layout() { var hotkey = new FakeCapsLockHotkeyService(); var layouts = new FakeKeyboardLayoutService { CurrentLayout = KeyboardLayout.FromLocaleId(0x0419), }; var popup = new FakeLayoutPopupService(); using var coordinator = new CapsLockSwitchCoordinator( hotkey, layouts, popup, new AppSettings { UseCapsLockHotkey = true }); coordinator.Start(); hotkey.RaiseHoldStarted(); Assert.Equal([layouts.CurrentLayout], popup.ShownUntilHidden); Assert.Equal(0, layouts.SwitchCalls); } [Fact] public void When_the_hold_ends_the_tooltip_goes_away() { var hotkey = new FakeCapsLockHotkeyService(); var layouts = new FakeKeyboardLayoutService(); var popup = new FakeLayoutPopupService(); using var coordinator = new CapsLockSwitchCoordinator( hotkey, layouts, popup, new AppSettings { UseCapsLockHotkey = true }); coordinator.Start(); hotkey.RaiseHoldStarted(); hotkey.RaiseHoldEnded(); Assert.Equal(1, popup.HideCalls); Assert.Equal(0, layouts.SwitchCalls); } [Fact] public void Before_the_start_presses_do_nothing() { var hotkey = new FakeCapsLockHotkeyService(); var layouts = new FakeKeyboardLayoutService(); var popup = new FakeLayoutPopupService(); using var coordinator = new CapsLockSwitchCoordinator( hotkey, layouts, popup, new AppSettings { UseCapsLockHotkey = true }); hotkey.RaiseTapped(); hotkey.RaiseHoldStarted(); Assert.Equal(0, layouts.SwitchCalls); Assert.Empty(popup.ShownUntilHidden); } [Fact] public void Closing_removes_the_interception_and_unsubscribes_from_presses() { var hotkey = new FakeCapsLockHotkeyService(); var layouts = new FakeKeyboardLayoutService(); var settings = new AppSettings { UseCapsLockHotkey = true }; var coordinator = new CapsLockSwitchCoordinator( hotkey, layouts, new FakeLayoutPopupService(), settings); coordinator.Start(); coordinator.Dispose(); Assert.False(hotkey.IsRunning); Assert.False(hotkey.HasSubscribers); hotkey.RaiseTapped(); Assert.Equal(0, layouts.SwitchCalls); } [Fact] public void After_closing_the_setting_no_longer_turns_the_interception_on() { var hotkey = new FakeCapsLockHotkeyService(); var settings = new AppSettings { UseCapsLockHotkey = false }; CapsLockSwitchCoordinator coordinator = Create(hotkey, settings); coordinator.Start(); coordinator.Dispose(); settings.UseCapsLockHotkey = true; Assert.False(hotkey.IsRunning); } private static CapsLockSwitchCoordinator Create(FakeCapsLockHotkeyService hotkey, AppSettings settings) => new(hotkey, new FakeKeyboardLayoutService(), new FakeLayoutPopupService(), settings); }