feat(configmanager): integrate SecureStore for credential management

Add SecureStore integration to ConfigManager for secure handling of connection
strings and sensitive configuration values. Includes store/secret management
UI, encrypted .store file support, and comprehensive test coverage.
This commit is contained in:
Joseph Doherty
2026-01-20 02:51:16 -05:00
parent d49330e697
commit 94d5a864e0
44 changed files with 6220 additions and 4 deletions
@@ -0,0 +1,399 @@
using JdeScoping.ConfigManager.Constants;
using JdeScoping.ConfigManager.ViewModels.Dialogs;
namespace JdeScoping.ConfigManager.Tests.ViewModels.Dialogs;
public class NewStoreDialogViewModelTests
{
[Fact]
public void Constructor_DefaultsToUseKeyFile()
{
// Arrange & Act
var sut = new NewStoreDialogViewModel();
// Assert
sut.UseKeyFile.ShouldBeTrue();
sut.UsePassword.ShouldBeFalse();
}
[Fact]
public void StorePath_WhenEmpty_IsValidReturnsFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "",
KeyFilePath = "/path/to/key.key"
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void StorePath_WhenEmpty_ValidationErrorReturnsStorePathRequired()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "",
KeyFilePath = "/path/to/key.key"
};
// Act & Assert
sut.ValidationError.ShouldBe(SecureStoreStrings.StorePathRequired);
}
[Fact]
public void StorePath_WhenWhitespace_IsValidReturnsFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = " ",
KeyFilePath = "/path/to/key.key"
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
sut.ValidationError.ShouldBe(SecureStoreStrings.StorePathRequired);
}
[Fact]
public void KeyFilePath_WhenRequiredAndEmpty_IsValidReturnsFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "/path/to/store.secure",
UseKeyFile = true,
KeyFilePath = ""
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void KeyFilePath_WhenRequiredAndEmpty_ValidationErrorReturnsKeyFilePathRequired()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "/path/to/store.secure",
UseKeyFile = true,
KeyFilePath = ""
};
// Act & Assert
sut.ValidationError.ShouldBe(SecureStoreStrings.KeyFilePathRequired);
}
[Fact]
public void KeyFilePath_WhenRequiredAndProvided_IsValidReturnsTrue()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "/path/to/store.secure",
UseKeyFile = true,
KeyFilePath = "/path/to/key.key"
};
// Act & Assert
sut.IsValid.ShouldBeTrue();
sut.ValidationError.ShouldBeNull();
}
[Fact]
public void Password_WhenRequiredAndEmpty_IsValidReturnsFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "/path/to/store.secure",
UsePassword = true,
Password = ""
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void Password_WhenRequiredAndEmpty_ValidationErrorReturnsPasswordRequired()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "/path/to/store.secure",
UsePassword = true,
Password = ""
};
// Act & Assert
sut.ValidationError.ShouldBe(SecureStoreStrings.PasswordRequired);
}
[Fact]
public void ConfirmPassword_WhenRequiredAndDoesNotMatch_IsValidReturnsFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "/path/to/store.secure",
UsePassword = true,
Password = "password123",
ConfirmPassword = "differentPassword"
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void ConfirmPassword_WhenRequiredAndDoesNotMatch_ValidationErrorReturnsPasswordsDoNotMatch()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "/path/to/store.secure",
UsePassword = true,
Password = "password123",
ConfirmPassword = "differentPassword"
};
// Act & Assert
sut.ValidationError.ShouldBe(SecureStoreStrings.PasswordsDoNotMatch);
}
[Fact]
public void Password_WhenRequiredAndMatchesConfirmPassword_IsValidReturnsTrue()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "/path/to/store.secure",
UsePassword = true,
Password = "password123",
ConfirmPassword = "password123"
};
// Act & Assert
sut.IsValid.ShouldBeTrue();
sut.ValidationError.ShouldBeNull();
}
[Fact]
public void UseKeyFile_WhenSetToTrue_SetsUsePasswordToFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
UsePassword = true
};
// Act
sut.UseKeyFile = true;
// Assert
sut.UseKeyFile.ShouldBeTrue();
sut.UsePassword.ShouldBeFalse();
}
[Fact]
public void UsePassword_WhenSetToTrue_SetsUseKeyFileToFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
UseKeyFile = true
};
// Act
sut.UsePassword = true;
// Assert
sut.UsePassword.ShouldBeTrue();
sut.UseKeyFile.ShouldBeFalse();
}
[Fact]
public void IsValid_WhenNeitherKeyFileNorPasswordSelected_ReturnsFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel
{
StorePath = "/path/to/store.secure"
};
// Manually set both to false (shouldn't happen in UI, but test edge case)
sut.UseKeyFile = false;
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void StorePath_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new NewStoreDialogViewModel();
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(NewStoreDialogViewModel.StorePath))
propertyChangedRaised = true;
};
// Act
sut.StorePath = "/new/path";
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void StorePath_WhenChanged_RaisesIsValidPropertyChanged()
{
// Arrange
var sut = new NewStoreDialogViewModel();
var isValidPropertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(NewStoreDialogViewModel.IsValid))
isValidPropertyChangedRaised = true;
};
// Act
sut.StorePath = "/new/path";
// Assert
isValidPropertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void StorePath_WhenChanged_RaisesValidationErrorPropertyChanged()
{
// Arrange
var sut = new NewStoreDialogViewModel();
var validationErrorPropertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(NewStoreDialogViewModel.ValidationError))
validationErrorPropertyChangedRaised = true;
};
// Act
sut.StorePath = "/new/path";
// Assert
validationErrorPropertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void KeyFilePath_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new NewStoreDialogViewModel();
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(NewStoreDialogViewModel.KeyFilePath))
propertyChangedRaised = true;
};
// Act
sut.KeyFilePath = "/new/key/path";
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void Password_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new NewStoreDialogViewModel();
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(NewStoreDialogViewModel.Password))
propertyChangedRaised = true;
};
// Act
sut.Password = "newpassword";
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void ConfirmPassword_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new NewStoreDialogViewModel();
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(NewStoreDialogViewModel.ConfirmPassword))
propertyChangedRaised = true;
};
// Act
sut.ConfirmPassword = "newpassword";
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void UseKeyFile_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new NewStoreDialogViewModel { UseKeyFile = false };
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(NewStoreDialogViewModel.UseKeyFile))
propertyChangedRaised = true;
};
// Act
sut.UseKeyFile = true;
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void UsePassword_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new NewStoreDialogViewModel();
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(NewStoreDialogViewModel.UsePassword))
propertyChangedRaised = true;
};
// Act
sut.UsePassword = true;
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void Commands_AreInitialized()
{
// Arrange & Act
var sut = new NewStoreDialogViewModel();
// Assert
sut.BrowseStorePathCommand.ShouldNotBeNull();
sut.BrowseKeyFilePathCommand.ShouldNotBeNull();
sut.GenerateKeyFileCommand.ShouldNotBeNull();
}
}
@@ -0,0 +1,343 @@
using JdeScoping.ConfigManager.Constants;
using JdeScoping.ConfigManager.ViewModels.Dialogs;
namespace JdeScoping.ConfigManager.Tests.ViewModels.Dialogs;
public class SecretEditDialogViewModelTests
{
[Fact]
public void DefaultConstructor_SetsIsNewSecretToTrue()
{
// Arrange & Act
var sut = new SecretEditDialogViewModel();
// Assert
sut.IsNewSecret.ShouldBeTrue();
}
[Fact]
public void DefaultConstructor_SetsKeyToEmpty()
{
// Arrange & Act
var sut = new SecretEditDialogViewModel();
// Assert
sut.Key.ShouldBeEmpty();
}
[Fact]
public void DefaultConstructor_SetsValueToEmpty()
{
// Arrange & Act
var sut = new SecretEditDialogViewModel();
// Assert
sut.Value.ShouldBeEmpty();
}
[Fact]
public void EditConstructor_SetsKeyFromParameter()
{
// Arrange & Act
var sut = new SecretEditDialogViewModel("myKey", "myValue");
// Assert
sut.Key.ShouldBe("myKey");
}
[Fact]
public void EditConstructor_SetsValueFromParameter()
{
// Arrange & Act
var sut = new SecretEditDialogViewModel("myKey", "myValue");
// Assert
sut.Value.ShouldBe("myValue");
}
[Fact]
public void EditConstructor_SetsIsNewSecretToFalse()
{
// Arrange & Act
var sut = new SecretEditDialogViewModel("myKey", "myValue");
// Assert
sut.IsNewSecret.ShouldBeFalse();
}
[Fact]
public void Key_WhenEmpty_IsValidReturnsFalse()
{
// Arrange
var sut = new SecretEditDialogViewModel
{
Key = ""
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void Key_WhenEmpty_ValidationErrorReturnsKeyRequired()
{
// Arrange
var sut = new SecretEditDialogViewModel
{
Key = ""
};
// Act & Assert
sut.ValidationError.ShouldBe(SecureStoreStrings.KeyRequired);
}
[Fact]
public void Key_WhenWhitespace_IsValidReturnsFalse()
{
// Arrange
var sut = new SecretEditDialogViewModel
{
Key = " "
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
sut.ValidationError.ShouldBe(SecureStoreStrings.KeyRequired);
}
[Fact]
public void Key_WhenProvided_IsValidReturnsTrue()
{
// Arrange
var sut = new SecretEditDialogViewModel
{
Key = "validKey"
};
// Act & Assert
sut.IsValid.ShouldBeTrue();
sut.ValidationError.ShouldBeNull();
}
[Fact]
public void IsKeyEditable_WhenIsNewSecretIsTrue_ReturnsTrue()
{
// Arrange
var sut = new SecretEditDialogViewModel();
// Act & Assert
sut.IsKeyEditable.ShouldBeTrue();
}
[Fact]
public void IsKeyEditable_WhenIsNewSecretIsFalse_ReturnsFalse()
{
// Arrange
var sut = new SecretEditDialogViewModel("existingKey", "existingValue");
// Act & Assert
sut.IsKeyEditable.ShouldBeFalse();
}
[Fact]
public void DialogTitle_WhenIsNewSecretIsTrue_ReturnsAddSecret()
{
// Arrange
var sut = new SecretEditDialogViewModel();
// Act & Assert
sut.DialogTitle.ShouldBe("Add Secret");
}
[Fact]
public void DialogTitle_WhenIsNewSecretIsFalse_ReturnsEditSecret()
{
// Arrange
var sut = new SecretEditDialogViewModel("existingKey", "existingValue");
// Act & Assert
sut.DialogTitle.ShouldBe("Edit Secret");
}
[Fact]
public void IsNewSecret_WhenChanged_RaisesIsKeyEditablePropertyChanged()
{
// Arrange
var sut = new SecretEditDialogViewModel();
var isKeyEditablePropertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretEditDialogViewModel.IsKeyEditable))
isKeyEditablePropertyChangedRaised = true;
};
// Act
sut.IsNewSecret = false;
// Assert
isKeyEditablePropertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void IsNewSecret_WhenChanged_RaisesDialogTitlePropertyChanged()
{
// Arrange
var sut = new SecretEditDialogViewModel();
var dialogTitlePropertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretEditDialogViewModel.DialogTitle))
dialogTitlePropertyChangedRaised = true;
};
// Act
sut.IsNewSecret = false;
// Assert
dialogTitlePropertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void Key_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new SecretEditDialogViewModel();
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretEditDialogViewModel.Key))
propertyChangedRaised = true;
};
// Act
sut.Key = "newKey";
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void Key_WhenChanged_RaisesIsValidPropertyChanged()
{
// Arrange
var sut = new SecretEditDialogViewModel();
var isValidPropertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretEditDialogViewModel.IsValid))
isValidPropertyChangedRaised = true;
};
// Act
sut.Key = "newKey";
// Assert
isValidPropertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void Key_WhenChanged_RaisesValidationErrorPropertyChanged()
{
// Arrange
var sut = new SecretEditDialogViewModel();
var validationErrorPropertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretEditDialogViewModel.ValidationError))
validationErrorPropertyChangedRaised = true;
};
// Act
sut.Key = "newKey";
// Assert
validationErrorPropertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void Value_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new SecretEditDialogViewModel();
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretEditDialogViewModel.Value))
propertyChangedRaised = true;
};
// Act
sut.Value = "newValue";
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void Value_CanBeEmpty_IsValidStillReturnsTrue()
{
// Arrange
var sut = new SecretEditDialogViewModel
{
Key = "validKey",
Value = ""
};
// Act & Assert
sut.IsValid.ShouldBeTrue();
sut.ValidationError.ShouldBeNull();
}
[Fact]
public void Value_CanBeNull_IsValidStillReturnsTrue()
{
// Arrange
var sut = new SecretEditDialogViewModel
{
Key = "validKey",
Value = null!
};
// Act & Assert
sut.IsValid.ShouldBeTrue();
sut.ValidationError.ShouldBeNull();
}
[Fact]
public void IsNewSecret_WhenSetToSameValue_DoesNotRaisePropertyChanged()
{
// Arrange
var sut = new SecretEditDialogViewModel();
var propertyChangedCount = 0;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretEditDialogViewModel.IsNewSecret))
propertyChangedCount++;
};
// Act
sut.IsNewSecret = true; // Same value as default
// Assert
propertyChangedCount.ShouldBe(0);
}
[Fact]
public void Key_WhenSetToSameValue_DoesNotRaisePropertyChanged()
{
// Arrange
var sut = new SecretEditDialogViewModel { Key = "testKey" };
var propertyChangedCount = 0;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretEditDialogViewModel.Key))
propertyChangedCount++;
};
// Act
sut.Key = "testKey"; // Same value
// Assert
propertyChangedCount.ShouldBe(0);
}
}
@@ -0,0 +1,347 @@
using JdeScoping.ConfigManager.Constants;
using JdeScoping.ConfigManager.ViewModels.Dialogs;
namespace JdeScoping.ConfigManager.Tests.ViewModels.Dialogs;
public class UnlockStoreDialogViewModelTests
{
[Fact]
public void Constructor_SetsStorePathFromParameter()
{
// Arrange
var storePath = "/path/to/store.secure";
// Act
var sut = new UnlockStoreDialogViewModel(storePath);
// Assert
sut.StorePath.ShouldBe(storePath);
}
[Fact]
public void Constructor_ThrowsOnNullStorePath()
{
// Act & Assert
Should.Throw<ArgumentNullException>(() => new UnlockStoreDialogViewModel(null!));
}
[Fact]
public void Constructor_DefaultsToUseKeyFile()
{
// Arrange & Act
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure");
// Assert
sut.UseKeyFile.ShouldBeTrue();
sut.UsePassword.ShouldBeFalse();
}
[Fact]
public void StorePath_IsReadOnly()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure");
// Assert - StorePath property has no setter, verified by checking it returns what was passed
sut.StorePath.ShouldBe("/path/to/store.secure");
}
[Fact]
public void KeyFilePath_WhenRequiredAndEmpty_IsValidReturnsFalse()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UseKeyFile = true,
KeyFilePath = ""
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void KeyFilePath_WhenRequiredAndEmpty_ValidationErrorReturnsKeyFilePathRequired()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UseKeyFile = true,
KeyFilePath = ""
};
// Act & Assert
sut.ValidationError.ShouldBe(SecureStoreStrings.KeyFilePathRequired);
}
[Fact]
public void KeyFilePath_WhenRequiredAndWhitespace_IsValidReturnsFalse()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UseKeyFile = true,
KeyFilePath = " "
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
sut.ValidationError.ShouldBe(SecureStoreStrings.KeyFilePathRequired);
}
[Fact]
public void KeyFilePath_WhenRequiredAndFileDoesNotExist_IsValidReturnsFalse()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UseKeyFile = true,
KeyFilePath = "/nonexistent/path/to/key.key"
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void KeyFilePath_WhenRequiredAndFileDoesNotExist_ValidationErrorReturnsKeyFileNotFound()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UseKeyFile = true,
KeyFilePath = "/nonexistent/path/to/key.key"
};
// Act & Assert
sut.ValidationError.ShouldBe(SecureStoreStrings.KeyFileNotFound);
}
[Fact]
public void Password_WhenRequiredAndEmpty_IsValidReturnsFalse()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UsePassword = true,
Password = ""
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void Password_WhenRequiredAndEmpty_ValidationErrorReturnsPasswordRequired()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UsePassword = true,
Password = ""
};
// Act & Assert
sut.ValidationError.ShouldBe(SecureStoreStrings.PasswordRequired);
}
[Fact]
public void Password_WhenRequiredAndWhitespace_IsValidReturnsFalse()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UsePassword = true,
Password = " "
};
// Act & Assert
sut.IsValid.ShouldBeFalse();
sut.ValidationError.ShouldBe(SecureStoreStrings.PasswordRequired);
}
[Fact]
public void Password_WhenRequiredAndProvided_IsValidReturnsTrue()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UsePassword = true,
Password = "password123"
};
// Act & Assert
sut.IsValid.ShouldBeTrue();
sut.ValidationError.ShouldBeNull();
}
[Fact]
public void UseKeyFile_WhenSetToTrue_SetsUsePasswordToFalse()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UsePassword = true
};
// Act
sut.UseKeyFile = true;
// Assert
sut.UseKeyFile.ShouldBeTrue();
sut.UsePassword.ShouldBeFalse();
}
[Fact]
public void UsePassword_WhenSetToTrue_SetsUseKeyFileToFalse()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure")
{
UseKeyFile = true
};
// Act
sut.UsePassword = true;
// Assert
sut.UsePassword.ShouldBeTrue();
sut.UseKeyFile.ShouldBeFalse();
}
[Fact]
public void IsValid_WhenNeitherKeyFileNorPasswordSelected_ReturnsFalse()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure");
// Manually set both to false (shouldn't happen in UI, but test edge case)
sut.UseKeyFile = false;
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void KeyFilePath_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure");
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(UnlockStoreDialogViewModel.KeyFilePath))
propertyChangedRaised = true;
};
// Act
sut.KeyFilePath = "/new/key/path";
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void KeyFilePath_WhenChanged_RaisesIsValidPropertyChanged()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure");
var isValidPropertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(UnlockStoreDialogViewModel.IsValid))
isValidPropertyChangedRaised = true;
};
// Act
sut.KeyFilePath = "/new/key/path";
// Assert
isValidPropertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void KeyFilePath_WhenChanged_RaisesValidationErrorPropertyChanged()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure");
var validationErrorPropertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(UnlockStoreDialogViewModel.ValidationError))
validationErrorPropertyChangedRaised = true;
};
// Act
sut.KeyFilePath = "/new/key/path";
// Assert
validationErrorPropertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void Password_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure");
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(UnlockStoreDialogViewModel.Password))
propertyChangedRaised = true;
};
// Act
sut.Password = "newpassword";
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void UseKeyFile_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure") { UseKeyFile = false };
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(UnlockStoreDialogViewModel.UseKeyFile))
propertyChangedRaised = true;
};
// Act
sut.UseKeyFile = true;
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void UsePassword_WhenChanged_RaisesPropertyChanged()
{
// Arrange
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure");
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(UnlockStoreDialogViewModel.UsePassword))
propertyChangedRaised = true;
};
// Act
sut.UsePassword = true;
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void BrowseKeyFilePathCommand_IsInitialized()
{
// Arrange & Act
var sut = new UnlockStoreDialogViewModel("/path/to/store.secure");
// Assert
sut.BrowseKeyFilePathCommand.ShouldNotBeNull();
}
}