using System; using System.Collections.Generic; using Xunit; using ytLive.Services; namespace ytLive.Tests; /// /// TASK 20 step 2 integration: custom hotkey bindings survive a DB round-trip. /// Save a mix of modifier chords and unbound actions to a temp LayoutStore, /// load them back, and verify that (a) custom chords match, (b) unbound actions /// are absent, and (c) actions the user didn't touch retain their defaults. /// public sealed class HotkeyConfigTests : IDisposable { private readonly string _tempDb; public HotkeyConfigTests() { _tempDb = System.IO.Path.Combine( System.IO.Path.GetTempPath(), $"ytLlive-hotkeycfg-{Guid.NewGuid():N}.db"); } [Fact] public void HotkeyBindings_Persist_RoundTrip() { // Arrange: create a fresh DB using (new LayoutStore(_tempDb)) { } Microsoft.Data.Sqlite.SqliteConnection.ClearAllPools(); var bindings = new Dictionary { [HotkeyId.SceneStarting] = new HotkeyChord(HotkeyChord.MOD_CONTROL, 0x79), // Ctrl+F10 [HotkeyId.ToggleMicMute] = null, // explicitly unbound [HotkeyId.StartStopStream] = new HotkeyChord(HotkeyChord.MOD_ALT | HotkeyChord.MOD_SHIFT, 0x7B), // Alt+Shift+F12 }; // Act: save then load using (var store = new LayoutStore(_tempDb)) { store.SaveHotkeyBindings(bindings); } Microsoft.Data.Sqlite.SqliteConnection.ClearAllPools(); Dictionary loaded; using (var store = new LayoutStore(_tempDb)) { loaded = store.LoadHotkeyBindings(); } // Assert: custom modifier chord round-trips correctly Assert.True(loaded.TryGetValue(HotkeyId.SceneStarting, out var sceneStarting)); Assert.Equal(HotkeyChord.MOD_CONTROL, sceneStarting!.Modifiers); Assert.Equal(0x79u, sceneStarting.VirtualKey); // Assert: explicitly unbound action is absent Assert.False(loaded.ContainsKey(HotkeyId.ToggleMicMute)); // Assert: multi-modifier chord round-trips correctly Assert.True(loaded.TryGetValue(HotkeyId.StartStopStream, out var startStop)); Assert.Equal(HotkeyChord.MOD_ALT | HotkeyChord.MOD_SHIFT, startStop!.Modifiers); Assert.Equal(0x7Bu, startStop.VirtualKey); // Assert: untouched actions are absent (caller fills defaults) Assert.False(loaded.ContainsKey(HotkeyId.SceneBrb)); Assert.False(loaded.ContainsKey(HotkeyId.TraxPlayPause)); } [Fact] public void HotkeyChord_DisplayString_FormatsModifiers() { var ctrlF10 = new HotkeyChord(HotkeyChord.MOD_CONTROL, 0x79); Assert.Equal("Ctrl+F10", ctrlF10.ToDisplayString()); var altShiftF12 = new HotkeyChord(HotkeyChord.MOD_ALT | HotkeyChord.MOD_SHIFT, 0x7B); Assert.Equal("Alt+Shift+F12", altShiftF12.ToDisplayString()); var bareF5 = new HotkeyChord(0, 0x74); Assert.Equal("F5", bareF5.ToDisplayString()); var none = HotkeyChord.DisplayString(null); Assert.Equal("None", none); } [Fact] public void HotkeyChord_StorageRoundTrip() { var original = new HotkeyChord(HotkeyChord.MOD_CONTROL | HotkeyChord.MOD_WIN, 0x7B); var stored = original.ToString(); var parsed = HotkeyChord.ParseStorage(stored); Assert.Equal(original, parsed); } public void Dispose() { Microsoft.Data.Sqlite.SqliteConnection.ClearAllPools(); try { System.IO.File.Delete(_tempDb); } catch { } } }