|
| 1 | +using System.ComponentModel; |
1 | 2 | using Avalonia.Controls; |
2 | 3 | using Avalonia.Controls.Primitives; |
3 | 4 | using Avalonia.Data; |
4 | 5 | using Avalonia.Headless.XUnit; |
5 | 6 | using Avalonia.Interactivity; |
6 | 7 | using Avalonia.LogicalTree; |
| 8 | +using Avalonia.Threading; |
7 | 9 | using Avalonia.VisualTree; |
8 | 10 | using Avalonia.Controls.Shapes; |
9 | 11 | using DirectorPrompt.Domain.Enums; |
| 12 | +using DirectorPrompt.Services; |
10 | 13 | using DirectorPrompt.ViewModels; |
11 | 14 | using DirectorPrompt.Views; |
12 | 15 | using DirectorPrompt.Views.Components; |
@@ -52,6 +55,105 @@ public void SettingsNavigationSwitchesVisiblePanel() |
52 | 55 | window.Close(); |
53 | 56 | } |
54 | 57 |
|
| 58 | + [AvaloniaFact] |
| 59 | + public void SettingsOthersPanelContainsLanSharingToggle() |
| 60 | + { |
| 61 | + var window = new SettingsWindow(); |
| 62 | + |
| 63 | + Assert.NotNull(window.FindControl<ToggleSwitch>("LanSharingToggle")); |
| 64 | + } |
| 65 | + |
| 66 | + [AvaloniaFact] |
| 67 | + public void RemoteMainWindowUsesMobileLayout() |
| 68 | + { |
| 69 | + var viewModel = new MainViewModel |
| 70 | + ( |
| 71 | + null!, |
| 72 | + null!, |
| 73 | + null!, |
| 74 | + null!, |
| 75 | + null!, |
| 76 | + null!, |
| 77 | + null!, |
| 78 | + null!, |
| 79 | + null!, |
| 80 | + null!, |
| 81 | + null!, |
| 82 | + null!, |
| 83 | + null!, |
| 84 | + new LanSharingStub() |
| 85 | + ); |
| 86 | + var entry = new DialogEntryViewModel { Content = "Message" }; |
| 87 | + viewModel.Dialog.Entries.Add(entry); |
| 88 | + var remoteWindow = new MainWindow(viewModel, false); |
| 89 | + var content = Assert.IsAssignableFrom<Control>(remoteWindow.Content); |
| 90 | + remoteWindow.Content = null; |
| 91 | + content.DataContext = viewModel; |
| 92 | + |
| 93 | + var host = new Window { Width = 390, Height = 700, Content = content }; |
| 94 | + host.Show(); |
| 95 | + Dispatcher.UIThread.RunJobs(); |
| 96 | + |
| 97 | + string[] controlNames = |
| 98 | + [ |
| 99 | + "MobileNavigation", |
| 100 | + "EditProjectButton", |
| 101 | + "DetailsPanel", |
| 102 | + "MobileDetailsButton", |
| 103 | + "MobileSessionsButton", |
| 104 | + "SessionSidebar", |
| 105 | + "MobileConversationButton", |
| 106 | + "MobileMessageRail", |
| 107 | + "DialogListBox", |
| 108 | + "MobileProjectToolbar" |
| 109 | + ]; |
| 110 | + var controls = content.GetLogicalDescendants() |
| 111 | + .OfType<Control>() |
| 112 | + .Where(control => control.Name is not null && controlNames.Contains(control.Name)) |
| 113 | + .ToDictionary(static control => control.Name!); |
| 114 | + |
| 115 | + Assert.True(controls["MobileNavigation"].IsVisible); |
| 116 | + Assert.False(controls["EditProjectButton"].IsVisible); |
| 117 | + Assert.False(controls["DetailsPanel"].IsVisible); |
| 118 | + Assert.True(controls["MobileProjectToolbar"].IsVisible); |
| 119 | + Assert.Equal(1, Grid.GetColumn(controls["MobileMessageRail"])); |
| 120 | + |
| 121 | + ((ListBox)controls["DialogListBox"]).ScrollIntoView(entry); |
| 122 | + Dispatcher.UIThread.RunJobs(); |
| 123 | + var messageMenuButton = content.GetVisualDescendants() |
| 124 | + .OfType<Button>() |
| 125 | + .First(button => button.Name == "MessageMenuButton"); |
| 126 | + Assert.True(messageMenuButton.IsEnabled); |
| 127 | + messageMenuButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); |
| 128 | + Assert.True(entry.IsMenuOpen); |
| 129 | + var messageActionsPanel = content.GetVisualDescendants() |
| 130 | + .OfType<Border>() |
| 131 | + .First(border => border.Name == "MessageActionsPanel"); |
| 132 | + Assert.True(messageActionsPanel.IsHitTestVisible); |
| 133 | + Assert.Contains("open", messageActionsPanel.Classes); |
| 134 | + Assert.Same(messageActionsPanel.Parent, messageMenuButton.Parent); |
| 135 | + |
| 136 | + var sessionsWidth = controls["MobileSessionsButton"].Bounds.Width; |
| 137 | + var conversationWidth = controls["MobileConversationButton"].Bounds.Width; |
| 138 | + var detailsWidth = controls["MobileDetailsButton"].Bounds.Width; |
| 139 | + Assert.InRange(Math.Abs(sessionsWidth - conversationWidth), 0, 1); |
| 140 | + Assert.InRange(Math.Abs(conversationWidth - detailsWidth), 0, 1); |
| 141 | + |
| 142 | + controls["MobileDetailsButton"].RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); |
| 143 | + Assert.True(controls["DetailsPanel"].IsVisible); |
| 144 | + |
| 145 | + controls["MobileSessionsButton"].RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); |
| 146 | + Assert.True(controls["SessionSidebar"].IsVisible); |
| 147 | + |
| 148 | + controls["MobileConversationButton"].RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); |
| 149 | + Assert.False(controls["SessionSidebar"].IsVisible); |
| 150 | + Assert.False(controls["DetailsPanel"].IsVisible); |
| 151 | + Assert.True(controls["MobileMessageRail"].IsVisible); |
| 152 | + Assert.True(((ToggleButton)controls["MobileConversationButton"]).IsChecked); |
| 153 | + |
| 154 | + host.Close(); |
| 155 | + } |
| 156 | + |
55 | 157 | [AvaloniaFact] |
56 | 158 | public void ProjectNavigationSwitchesVisiblePanel() |
57 | 159 | { |
@@ -149,4 +251,20 @@ public void CharacterAndMemoryFiltersRestoreDefaultSelections() |
149 | 251 |
|
150 | 252 | window.Close(); |
151 | 253 | } |
| 254 | + |
| 255 | + private sealed class LanSharingStub : ILanSharingService |
| 256 | + { |
| 257 | + public Uri? Endpoint => null; |
| 258 | + |
| 259 | + public bool IsActive => false; |
| 260 | + |
| 261 | + public event PropertyChangedEventHandler? PropertyChanged |
| 262 | + { |
| 263 | + add { } |
| 264 | + remove { } |
| 265 | + } |
| 266 | + |
| 267 | + public Task ApplyAsync(bool enabled, CancellationToken cancellationToken = default) => |
| 268 | + Task.CompletedTask; |
| 269 | + } |
152 | 270 | } |
0 commit comments