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:
@@ -218,4 +218,180 @@ public class TreeNodeViewModelTests
|
||||
// Assert
|
||||
propertyChangedRaised.ShouldBeFalse();
|
||||
}
|
||||
|
||||
#region SecureStore Node Type Tests
|
||||
|
||||
[Theory]
|
||||
[InlineData(TreeNodeType.SecureStoresFolder)]
|
||||
[InlineData(TreeNodeType.SecureStore)]
|
||||
[InlineData(TreeNodeType.Secret)]
|
||||
public void Constructor_WithSecureStoreNodeTypes_SetsNodeTypeCorrectly(TreeNodeType nodeType)
|
||||
{
|
||||
// Arrange & Act
|
||||
var sut = new TreeNodeViewModel("Test", "icon", nodeType);
|
||||
|
||||
// Assert
|
||||
sut.NodeType.ShouldBe(nodeType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsUnlocked_DefaultsToFalse()
|
||||
{
|
||||
// Arrange & Act
|
||||
var sut = new TreeNodeViewModel("Store", "🔒", TreeNodeType.SecureStore);
|
||||
|
||||
// Assert
|
||||
sut.IsUnlocked.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsUnlocked_WhenSet_RaisesPropertyChanged()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new TreeNodeViewModel("Store", "🔒", TreeNodeType.SecureStore);
|
||||
var propertyChangedRaised = false;
|
||||
sut.PropertyChanged += (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(TreeNodeViewModel.IsUnlocked))
|
||||
propertyChangedRaised = true;
|
||||
};
|
||||
|
||||
// Act
|
||||
sut.IsUnlocked = true;
|
||||
|
||||
// Assert
|
||||
propertyChangedRaised.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsUnlocked_WhenSet_RaisesPropertyChangedForLockIcon()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new TreeNodeViewModel("Store", "🔒", TreeNodeType.SecureStore);
|
||||
var lockIconChanged = false;
|
||||
sut.PropertyChanged += (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(TreeNodeViewModel.LockIcon))
|
||||
lockIconChanged = true;
|
||||
};
|
||||
|
||||
// Act
|
||||
sut.IsUnlocked = true;
|
||||
|
||||
// Assert
|
||||
lockIconChanged.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LockIcon_WhenLocked_ReturnsLockedIcon()
|
||||
{
|
||||
// Arrange & Act
|
||||
var sut = new TreeNodeViewModel("Store", "🔒", TreeNodeType.SecureStore);
|
||||
|
||||
// Assert
|
||||
sut.LockIcon.ShouldBe("🔒");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LockIcon_WhenUnlocked_ReturnsUnlockedIcon()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new TreeNodeViewModel("Store", "🔒", TreeNodeType.SecureStore);
|
||||
|
||||
// Act
|
||||
sut.IsUnlocked = true;
|
||||
|
||||
// Assert
|
||||
sut.LockIcon.ShouldBe("🔓");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsLocked_WhenUnlocked_ReturnsFalse()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new TreeNodeViewModel("Store", "🔒", TreeNodeType.SecureStore);
|
||||
|
||||
// Act
|
||||
sut.IsUnlocked = true;
|
||||
|
||||
// Assert
|
||||
sut.IsLocked.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsLocked_WhenLocked_ReturnsTrue()
|
||||
{
|
||||
// Arrange & Act
|
||||
var sut = new TreeNodeViewModel("Store", "🔒", TreeNodeType.SecureStore);
|
||||
|
||||
// Assert
|
||||
sut.IsLocked.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsUnlocked_WhenSet_RaisesPropertyChangedForIsLocked()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new TreeNodeViewModel("Store", "🔒", TreeNodeType.SecureStore);
|
||||
var isLockedChanged = false;
|
||||
sut.PropertyChanged += (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(TreeNodeViewModel.IsLocked))
|
||||
isLockedChanged = true;
|
||||
};
|
||||
|
||||
// Act
|
||||
sut.IsUnlocked = true;
|
||||
|
||||
// Assert
|
||||
isLockedChanged.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StorePath_CanBeSetViaInitializer()
|
||||
{
|
||||
// Arrange & Act
|
||||
var sut = new TreeNodeViewModel("Store", "🔒", TreeNodeType.SecureStore)
|
||||
{
|
||||
StorePath = "/path/to/store.secrets"
|
||||
};
|
||||
|
||||
// Assert
|
||||
sut.StorePath.ShouldBe("/path/to/store.secrets");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StorePath_DefaultsToNull()
|
||||
{
|
||||
// Arrange & Act
|
||||
var sut = new TreeNodeViewModel("Store", "🔒", TreeNodeType.SecureStore);
|
||||
|
||||
// Assert
|
||||
sut.StorePath.ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SecretKey_CanBeSetViaInitializer()
|
||||
{
|
||||
// Arrange & Act
|
||||
var sut = new TreeNodeViewModel("MySecret", "🔑", TreeNodeType.Secret)
|
||||
{
|
||||
SecretKey = "ConnectionStrings:Database"
|
||||
};
|
||||
|
||||
// Assert
|
||||
sut.SecretKey.ShouldBe("ConnectionStrings:Database");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SecretKey_DefaultsToNull()
|
||||
{
|
||||
// Arrange & Act
|
||||
var sut = new TreeNodeViewModel("MySecret", "🔑", TreeNodeType.Secret);
|
||||
|
||||
// Assert
|
||||
sut.SecretKey.ShouldBeNull();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user