using JdeScoping.ConfigManager.ViewModels; namespace JdeScoping.ConfigManager.Tests.ViewModels; public class TreeNodeViewModelTests { [Fact] public void Constructor_SetsProperties() { // Arrange & Act var node = new TreeNodeViewModel("DataSync", "⟳", TreeNodeType.SettingsSection); // Assert node.Name.ShouldBe("DataSync"); node.Icon.ShouldBe("⟳"); node.NodeType.ShouldBe(TreeNodeType.SettingsSection); } [Fact] public void IsModified_WhenSet_RaisesPropertyChanged() { // Arrange var node = new TreeNodeViewModel("Test", "📁", TreeNodeType.Folder); var propertyChangedRaised = false; node.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(TreeNodeViewModel.IsModified)) propertyChangedRaised = true; }; // Act node.IsModified = true; // Assert propertyChangedRaised.ShouldBeTrue(); } [Fact] public void IsExpanded_WhenSet_RaisesPropertyChanged() { // Arrange var node = new TreeNodeViewModel("Test", "📁", TreeNodeType.Folder); var propertyChangedRaised = false; node.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(TreeNodeViewModel.IsExpanded)) propertyChangedRaised = true; }; // Act node.IsExpanded = true; // Assert propertyChangedRaised.ShouldBeTrue(); node.IsExpanded.ShouldBeTrue(); } [Fact] public void IsSelected_WhenSet_RaisesPropertyChanged() { // Arrange var node = new TreeNodeViewModel("Test", "📁", TreeNodeType.Folder); var propertyChangedRaised = false; node.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(TreeNodeViewModel.IsSelected)) propertyChangedRaised = true; }; // Act node.IsSelected = true; // Assert propertyChangedRaised.ShouldBeTrue(); node.IsSelected.ShouldBeTrue(); } [Fact] public void ValidationState_WhenSetToValid_StatusIconIsCheckmark() { // Arrange var node = new TreeNodeViewModel("Test", "📁", TreeNodeType.Folder); // Act node.ValidationState = ValidationState.Valid; // Assert node.StatusIcon.ShouldBe("✓"); } [Fact] public void ValidationState_WhenSetToWarning_StatusIconIsWarning() { // Arrange var node = new TreeNodeViewModel("Test", "📁", TreeNodeType.Folder); // Act node.ValidationState = ValidationState.Warning; // Assert node.StatusIcon.ShouldBe("⚠"); } [Fact] public void ValidationState_WhenSetToError_StatusIconIsX() { // Arrange var node = new TreeNodeViewModel("Test", "📁", TreeNodeType.Folder); // Act node.ValidationState = ValidationState.Error; // Assert node.StatusIcon.ShouldBe("✗"); } [Fact] public void ValidationState_WhenSetToUnknown_StatusIconIsEmpty() { // Arrange var node = new TreeNodeViewModel("Test", "📁", TreeNodeType.Folder); // Act node.ValidationState = ValidationState.Unknown; // Assert node.StatusIcon.ShouldBe(""); } [Fact] public void ValidationState_WhenChanged_RaisesPropertyChangedForStatusIcon() { // Arrange var node = new TreeNodeViewModel("Test", "📁", TreeNodeType.Folder); var statusIconPropertyChanged = false; node.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(TreeNodeViewModel.StatusIcon)) statusIconPropertyChanged = true; }; // Act node.ValidationState = ValidationState.Valid; // Assert statusIconPropertyChanged.ShouldBeTrue(); } [Fact] public void SectionKey_CanBeSetViaInitializer() { // Arrange & Act var node = new TreeNodeViewModel("DataSync", "⟳", TreeNodeType.SettingsSection) { SectionKey = "DataSync" }; // Assert node.SectionKey.ShouldBe("DataSync"); } [Fact] public void Children_IsInitialized() { // Arrange & Act var node = new TreeNodeViewModel("Test", "📁", TreeNodeType.Folder); // Assert node.Children.ShouldNotBeNull(); node.Children.ShouldBeEmpty(); } [Fact] public void Children_CanAddChildNodes() { // Arrange var parent = new TreeNodeViewModel("Settings", "📁", TreeNodeType.Folder); var child = new TreeNodeViewModel("DataSync", "⟳", TreeNodeType.SettingsSection); // Act parent.Children.Add(child); // Assert parent.Children.Count.ShouldBe(1); parent.Children[0].ShouldBe(child); } [Theory] [InlineData(TreeNodeType.Folder)] [InlineData(TreeNodeType.SettingsSection)] [InlineData(TreeNodeType.Pipeline)] public void NodeType_CanBeSetForAllTypes(TreeNodeType nodeType) { // Arrange & Act var node = new TreeNodeViewModel("Test", "📁", nodeType); // Assert node.NodeType.ShouldBe(nodeType); } [Fact] public void IsModified_WhenSetToSameValue_DoesNotRaisePropertyChanged() { // Arrange var node = new TreeNodeViewModel("Test", "📁", TreeNodeType.Folder); node.IsModified = true; var propertyChangedRaised = false; node.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(TreeNodeViewModel.IsModified)) propertyChangedRaised = true; }; // Act node.IsModified = true; // Same value // 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 }