build: make release restore reproducible

This commit is contained in:
Erik 2026-08-18 10:29:00 +02:00
parent b459e0cf0c
commit c38f6b8852
129 changed files with 16810 additions and 188 deletions

View file

@ -114,52 +114,57 @@ public sealed class MainWindowViewTests
}
}
[AvaloniaTheory]
[InlineData(ProfileEditorKind.AddServer, "ServerNameTextBox")]
[InlineData(ProfileEditorKind.EditServer, "ServerNameTextBox")]
[InlineData(ProfileEditorKind.AddAccount, "AccountNameTextBox")]
[InlineData(ProfileEditorKind.EditAccount, "AccountNameTextBox")]
[InlineData(ProfileEditorKind.AddCharacter, "CharacterNameTextBox")]
[InlineData(ProfileEditorKind.EditCharacter, "CharacterNameTextBox")]
[InlineData(ProfileEditorKind.Remove, "EditorSubmitButton")]
public void OpeningEachEditorKindFocusesItsPrimaryFieldAndClosingRunsTheFallbackWithoutThrowing(
ProfileEditorKind kind,
string expectedFocusFieldName)
[AvaloniaFact]
public void OpeningEveryEditorKindFocusesItsPrimaryFieldAndClosingRunsTheFallbackWithoutThrowing()
{
using LauncherWindowViewModel viewModel = CreateViewModel();
var window = new MainWindow { DataContext = viewModel };
try
(ProfileEditorKind Kind, string FocusFieldName)[] cases =
[
(ProfileEditorKind.AddServer, "ServerNameTextBox"),
(ProfileEditorKind.EditServer, "ServerNameTextBox"),
(ProfileEditorKind.AddAccount, "AccountNameTextBox"),
(ProfileEditorKind.EditAccount, "AccountNameTextBox"),
(ProfileEditorKind.AddCharacter, "CharacterNameTextBox"),
(ProfileEditorKind.EditCharacter, "CharacterNameTextBox"),
(ProfileEditorKind.Remove, "EditorSubmitButton"),
];
foreach ((ProfileEditorKind kind, string expectedFocusFieldName) in cases)
{
window.Show();
using LauncherWindowViewModel viewModel = CreateViewModel();
var window = new MainWindow { DataContext = viewModel };
try
{
window.Show();
viewModel.EditorDialog.Open(kind, "Fixture title", _ => { });
Assert.True(viewModel.EditorDialog.IsOpen);
Dispatcher.UIThread.RunJobs();
viewModel.EditorDialog.Open(kind, "Fixture title", _ => { });
Assert.True(viewModel.EditorDialog.IsOpen);
Dispatcher.UIThread.RunJobs();
Control expectedFocus = (Control)GetNamedField(window, expectedFocusFieldName)!;
Assert.Same(expectedFocus, CurrentFocus(window));
Control expectedFocus = (Control)GetNamedField(window, expectedFocusFieldName)!;
Assert.Same(expectedFocus, CurrentFocus(window));
viewModel.EditorDialog.Close();
Assert.False(viewModel.EditorDialog.IsOpen);
viewModel.EditorDialog.Close();
Assert.False(viewModel.EditorDialog.IsOpen);
// Nothing held focus before the dialog opened, so
// OnViewModelPropertyChanged's close branch posts the fallback
// (ProfilesTree.Focus()). Pumping the dispatcher is what actually
// *runs* FocusActiveModal's caller and its ProfilesTree
// dereference — this is the #398 defect class: with
// AvaloniaXamlLoader.Load(this) instead of InitializeComponent(),
// ProfilesTree is null here and this throws
// NullReferenceException out of the dispatcher. TreeView's Fluent
// template sets Focusable="False" (focus lives on TreeViewItem
// rows, not the tree itself), so a successful, non-throwing
// ProfilesTree.Focus() call still leaves focus at null — that is
// expected, not a failure.
Dispatcher.UIThread.RunJobs();
Assert.NotSame(expectedFocus, CurrentFocus(window));
}
finally
{
CloseTestWindow(window);
// Nothing held focus before the dialog opened, so
// OnViewModelPropertyChanged's close branch posts the fallback
// (ProfilesTree.Focus()). Pumping the dispatcher is what actually
// *runs* FocusActiveModal's caller and its ProfilesTree
// dereference — this is the #398 defect class: with
// AvaloniaXamlLoader.Load(this) instead of InitializeComponent(),
// ProfilesTree is null here and this throws
// NullReferenceException out of the dispatcher. TreeView's Fluent
// template sets Focusable="False" (focus lives on TreeViewItem
// rows, not the tree itself), so a successful, non-throwing
// ProfilesTree.Focus() call still leaves focus at null — that is
// expected, not a failure.
Dispatcher.UIThread.RunJobs();
Assert.NotSame(expectedFocus, CurrentFocus(window));
}
finally
{
CloseTestWindow(window);
}
}
}