refactor(securestoremanager): add platform service abstractions and constants
Implement deferred code review findings: - Add IDialogService/IClipboardService interfaces for testable platform operations - Create AvaloniaDialogService and AvaloniaClipboardService implementations - Extract dialog strings and file extensions to centralized Constants classes - Refactor ViewModels to use DI instead of event delegates - Update tests to use mock services
This commit is contained in:
@@ -12,14 +12,27 @@ namespace JdeScoping.SecureStoreManager.Tests.Views;
|
||||
|
||||
public class MainWindowTests
|
||||
{
|
||||
private static MainWindowViewModel CreateViewModel(ISecureStoreManager? storeManager = null)
|
||||
{
|
||||
var mockStoreManager = storeManager ?? Substitute.For<ISecureStoreManager>();
|
||||
var mockDialogService = Substitute.For<IDialogService>();
|
||||
var mockClipboardService = Substitute.For<IClipboardService>();
|
||||
return new MainWindowViewModel(mockStoreManager, mockDialogService, mockClipboardService);
|
||||
}
|
||||
|
||||
[AvaloniaFact]
|
||||
public void MainWindow_ShowsWithCorrectDefaultTitle()
|
||||
{
|
||||
// Arrange & Act
|
||||
var window = new MainWindow();
|
||||
// Arrange
|
||||
var storeManager = Substitute.For<ISecureStoreManager>();
|
||||
storeManager.IsStoreOpen.Returns(false);
|
||||
var viewModel = CreateViewModel(storeManager);
|
||||
var window = new MainWindow { DataContext = viewModel };
|
||||
|
||||
// Act
|
||||
window.Show();
|
||||
|
||||
// Assert
|
||||
// Assert - Title is bound to WindowTitle which is "SecureStore Manager" when no store is open
|
||||
window.Title.ShouldBe("SecureStore Manager");
|
||||
}
|
||||
|
||||
@@ -48,11 +61,14 @@ public class MainWindowTests
|
||||
[AvaloniaFact]
|
||||
public void MainWindow_DataContextIsMainWindowViewModel()
|
||||
{
|
||||
// Arrange & Act
|
||||
var window = new MainWindow();
|
||||
// Arrange
|
||||
var viewModel = CreateViewModel();
|
||||
|
||||
// Act
|
||||
var window = new MainWindow { DataContext = viewModel };
|
||||
window.Show();
|
||||
|
||||
// Assert
|
||||
// Assert - DataContext is set via DI in production, but must be set manually in tests
|
||||
window.DataContext.ShouldBeOfType<MainWindowViewModel>();
|
||||
}
|
||||
|
||||
@@ -103,31 +119,36 @@ public class MainWindowTests
|
||||
[AvaloniaFact]
|
||||
public void MainWindow_NewButtonCommand_IsBoundToViewModel()
|
||||
{
|
||||
// Arrange & Act
|
||||
var window = new MainWindow();
|
||||
// Arrange
|
||||
var storeManager = Substitute.For<ISecureStoreManager>();
|
||||
var viewModel = CreateViewModel(storeManager);
|
||||
var window = new MainWindow { DataContext = viewModel };
|
||||
|
||||
// Act
|
||||
window.Show();
|
||||
|
||||
var viewModel = window.DataContext as MainWindowViewModel;
|
||||
var buttons = window.GetVisualDescendants().OfType<Button>().ToList();
|
||||
var newButton = buttons.FirstOrDefault(b => b.Content?.ToString() == "New");
|
||||
|
||||
// Assert
|
||||
newButton.ShouldNotBeNull();
|
||||
newButton.Command.ShouldBe(viewModel?.NewStoreCommand);
|
||||
newButton.Command.ShouldBe(viewModel.NewStoreCommand);
|
||||
}
|
||||
|
||||
[AvaloniaFact]
|
||||
public void MainWindow_StatusBar_DisplaysStatusMessage()
|
||||
{
|
||||
// Arrange & Act
|
||||
var window = new MainWindow();
|
||||
window.Show();
|
||||
// Arrange
|
||||
var storeManager = Substitute.For<ISecureStoreManager>();
|
||||
var viewModel = CreateViewModel(storeManager);
|
||||
var window = new MainWindow { DataContext = viewModel };
|
||||
|
||||
var viewModel = window.DataContext as MainWindowViewModel;
|
||||
// Act
|
||||
window.Show();
|
||||
|
||||
// Assert - Find status bar text blocks
|
||||
var textBlocks = window.GetVisualDescendants().OfType<TextBlock>().ToList();
|
||||
// Status message should be "Ready" by default
|
||||
textBlocks.Any(tb => tb.Text == viewModel?.StatusMessage).ShouldBeTrue();
|
||||
textBlocks.Any(tb => tb.Text == viewModel.StatusMessage).ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user