using NSubstitute; using Shouldly; using Xunit; using JdeScoping.SecureStoreManager.Services; using JdeScoping.SecureStoreManager.ViewModels; namespace JdeScoping.SecureStoreManager.Tests.ViewModels; public class SecretItemViewModelTests { private readonly IClipboardService _mockClipboardService; public SecretItemViewModelTests() { _mockClipboardService = Substitute.For(); } [Fact] public void Constructor_InitializesKey() { // Arrange & Act var sut = new SecretItemViewModel("testKey", "testValue", _mockClipboardService); // Assert sut.Key.ShouldBe("testKey"); } [Fact] public void Constructor_InitializesActualValue() { // Arrange & Act var sut = new SecretItemViewModel("testKey", "testValue", _mockClipboardService); // Assert sut.ActualValue.ShouldBe("testValue"); } [Fact] public void Constructor_InitializesIsValueVisibleToFalse() { // Arrange & Act var sut = new SecretItemViewModel("testKey", "testValue", _mockClipboardService); // Assert sut.IsValueVisible.ShouldBeFalse(); } [Fact] public void DisplayValue_WhenNotVisible_ReturnsMaskedValue() { // Arrange var sut = new SecretItemViewModel("testKey", "testValue", _mockClipboardService); // Act & Assert sut.DisplayValue.ShouldBe("********"); } [Fact] public void DisplayValue_WhenVisible_ReturnsActualValue() { // Arrange var sut = new SecretItemViewModel("testKey", "testValue", _mockClipboardService); // Act sut.IsValueVisible = true; // Assert sut.DisplayValue.ShouldBe("testValue"); } [Fact] public void ToggleVisibilityCommand_TogglesIsValueVisible() { // Arrange var sut = new SecretItemViewModel("testKey", "testValue", _mockClipboardService); sut.IsValueVisible.ShouldBeFalse(); // Act sut.ToggleVisibilityCommand.Execute(null); // Assert sut.IsValueVisible.ShouldBeTrue(); } [Fact] public void ToggleVisibilityCommand_TogglesBackToHidden() { // Arrange var sut = new SecretItemViewModel("testKey", "testValue", _mockClipboardService); sut.IsValueVisible = true; // Act sut.ToggleVisibilityCommand.Execute(null); // Assert sut.IsValueVisible.ShouldBeFalse(); } [Fact] public async Task CopyToClipboardCommand_CallsClipboardService() { // Arrange var sut = new SecretItemViewModel("testKey", "secretPassword", _mockClipboardService); // Act sut.CopyToClipboardCommand.Execute(null); // Assert - need to wait for async handler // Give the async void handler time to complete await Task.Delay(100); await _mockClipboardService.Received(1).SetTextAsync("secretPassword"); } [Fact] public void IsValueVisible_SetterRaisesPropertyChangedForIsValueVisible() { // Arrange var sut = new SecretItemViewModel("testKey", "testValue", _mockClipboardService); var propertyChangedRaised = false; sut.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(sut.IsValueVisible)) propertyChangedRaised = true; }; // Act sut.IsValueVisible = true; // Assert propertyChangedRaised.ShouldBeTrue(); } [Fact] public void IsValueVisible_SetterRaisesPropertyChangedForDisplayValue() { // Arrange var sut = new SecretItemViewModel("testKey", "testValue", _mockClipboardService); var propertyChangedRaised = false; sut.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(sut.DisplayValue)) propertyChangedRaised = true; }; // Act sut.IsValueVisible = true; // Assert propertyChangedRaised.ShouldBeTrue(); } [Fact] public void IsValueVisible_SetToSameValue_DoesNotRaisePropertyChanged() { // Arrange var sut = new SecretItemViewModel("testKey", "testValue", _mockClipboardService); sut.IsValueVisible = false; // Already false, but explicitly set var propertyChangedRaised = false; sut.PropertyChanged += (s, e) => { propertyChangedRaised = true; }; // Act sut.IsValueVisible = false; // Assert propertyChangedRaised.ShouldBeFalse(); } }