| 1 | using Avalonia.Controls; |
| 2 | using Avalonia.Headless.XUnit; |
| 3 | using Avalonia.Input; |
| 4 | using Avalonia.VisualTree; |
| 5 | using CascadeIDE.Models.Shell; |
| 6 | using CascadeIDE.Services; |
| 7 | using CascadeIDE.ViewModels; |
| 8 | using CascadeIDE.Views; |
| 9 | using Xunit; |
| 10 | |
| 11 | namespace CascadeIDE.Tests; |
| 12 | |
| 13 | public sealed class MainWindowHotkeyRoutingHeadlessTests |
| 14 | { |
| 15 | [AvaloniaFact] |
| 16 | public void CtrlQ_FromFocusedChild_ReachesMainWindowTunnelHandler() |
| 17 | { |
| 18 | MainWindowHotkeyService.ReplaceMergedMapForTests( |
| 19 | new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) |
| 20 | { |
| 21 | ["toggle_command_palette"] = "Ctrl+Q" |
| 22 | }); |
| 23 | |
| 24 | try |
| 25 | { |
| 26 | var vm = new MainWindowViewModel(); |
| 27 | var window = new MainWindow |
| 28 | { |
| 29 | DataContext = vm |
| 30 | }; |
| 31 | |
| 32 | window.Show(); |
| 33 | |
| 34 | var mainGrid = window.FindControl<Grid>("MainGrid"); |
| 35 | Assert.NotNull(mainGrid); |
| 36 | |
| 37 | var e = new KeyEventArgs |
| 38 | { |
| 39 | RoutedEvent = InputElement.KeyDownEvent, |
| 40 | Source = mainGrid, |
| 41 | Key = Key.Q, |
| 42 | KeyModifiers = KeyModifiers.Control, |
| 43 | PhysicalKey = PhysicalKey.Q |
| 44 | }; |
| 45 | |
| 46 | mainGrid.RaiseEvent(e); |
| 47 | |
| 48 | Assert.True(e.Handled); |
| 49 | Assert.True(vm.IsCommandPaletteOpen); |
| 50 | } |
| 51 | finally |
| 52 | { |
| 53 | MainWindowHotkeyService.ReplaceMergedMapForTests(null); |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | [AvaloniaFact] |
| 58 | public void CommandPalette_IsVisibleOnlyInMatchingHostWindow() |
| 59 | { |
| 60 | var vm = new MainWindowViewModel(); |
| 61 | var mainWindow = new MainWindow { DataContext = vm }; |
| 62 | var pfdWindow = new PfdHostWindow { DataContext = vm }; |
| 63 | var mfdWindow = new MfdHostWindow { DataContext = vm }; |
| 64 | |
| 65 | mainWindow.Show(); |
| 66 | pfdWindow.Show(); |
| 67 | mfdWindow.Show(); |
| 68 | |
| 69 | var mainPalette = FindDescendant<CommandPaletteView>(mainWindow); |
| 70 | var pfdPalette = FindDescendant<CommandPaletteView>(pfdWindow); |
| 71 | var mfdPalette = FindDescendant<CommandPaletteView>(mfdWindow); |
| 72 | |
| 73 | Assert.NotNull(mainPalette); |
| 74 | Assert.NotNull(pfdPalette); |
| 75 | Assert.NotNull(mfdPalette); |
| 76 | |
| 77 | vm.IsCommandPaletteOpen = true; |
| 78 | vm.CommandPaletteHost = CommandPaletteHost.MainWindow; |
| 79 | Assert.True(mainPalette!.IsVisible); |
| 80 | Assert.False(pfdPalette!.IsVisible); |
| 81 | Assert.False(mfdPalette!.IsVisible); |
| 82 | |
| 83 | vm.CommandPaletteHost = CommandPaletteHost.PfdHost; |
| 84 | Assert.False(mainPalette.IsVisible); |
| 85 | Assert.True(pfdPalette.IsVisible); |
| 86 | Assert.False(mfdPalette.IsVisible); |
| 87 | |
| 88 | vm.CommandPaletteHost = CommandPaletteHost.MfdHost; |
| 89 | Assert.False(mainPalette.IsVisible); |
| 90 | Assert.False(pfdPalette.IsVisible); |
| 91 | Assert.True(mfdPalette.IsVisible); |
| 92 | |
| 93 | mainWindow.Close(); |
| 94 | pfdWindow.Close(); |
| 95 | mfdWindow.Close(); |
| 96 | } |
| 97 | |
| 98 | private static T? FindDescendant<T>(TopLevel root) |
| 99 | where T : class |
| 100 | { |
| 101 | return root.GetVisualDescendants().OfType<T>().FirstOrDefault(); |
| 102 | } |
| 103 | |
| 104 | } |
| 105 | |