Files
jdescopingtool/NEW/tests/JdeScoping.ConfigManager.Tests/ViewModels/Forms/SecretFormViewModelTests.cs
T
Joseph Doherty 94d5a864e0 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.
2026-01-20 02:51:16 -05:00

413 lines
11 KiB
C#

using JdeScoping.ConfigManager.Services;
using JdeScoping.ConfigManager.ViewModels.Forms;
namespace JdeScoping.ConfigManager.Tests.ViewModels.Forms;
public class SecretFormViewModelTests
{
private readonly IClipboardService _clipboardService;
public SecretFormViewModelTests()
{
_clipboardService = Substitute.For<IClipboardService>();
}
[Fact]
public void Constructor_SetsPropertiesCorrectly()
{
// Arrange & Act
var sut = new SecretFormViewModel(
"API_KEY",
"secret-value-123",
_clipboardService,
_ => { },
() => { });
// Assert
sut.Key.ShouldBe("API_KEY");
sut.Value.ShouldBe("secret-value-123");
sut.IsValueVisible.ShouldBeFalse();
}
[Fact]
public void Constructor_WithNullValue_SetsEmptyString()
{
// Arrange & Act
var sut = new SecretFormViewModel(
"API_KEY",
null!,
_clipboardService,
_ => { },
() => { });
// Assert
sut.Value.ShouldBe(string.Empty);
}
[Fact]
public void Value_Setter_InvokesCallback()
{
// Arrange
string? changedValue = null;
var sut = new SecretFormViewModel(
"API_KEY",
"initial",
_clipboardService,
v => changedValue = v,
() => { });
// Act
sut.Value = "new-value";
// Assert
changedValue.ShouldBe("new-value");
}
[Fact]
public void Value_Setter_RaisesPropertyChanged()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"initial",
_clipboardService,
_ => { },
() => { });
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretFormViewModel.Value))
propertyChangedRaised = true;
};
// Act
sut.Value = "new-value";
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void Value_Setter_RaisesDisplayValuePropertyChanged()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"initial",
_clipboardService,
_ => { },
() => { });
var displayValueChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretFormViewModel.DisplayValue))
displayValueChangedRaised = true;
};
// Act
sut.Value = "new-value";
// Assert
displayValueChangedRaised.ShouldBeTrue();
}
[Fact]
public void IsValueVisible_Toggle_Works()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"secret",
_clipboardService,
_ => { },
() => { });
// Act & Assert - Initial state
sut.IsValueVisible.ShouldBeFalse();
// Act - Toggle on
sut.IsValueVisible = true;
sut.IsValueVisible.ShouldBeTrue();
// Act - Toggle off
sut.IsValueVisible = false;
sut.IsValueVisible.ShouldBeFalse();
}
[Fact]
public void IsValueVisible_RaisesPropertyChanged()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"secret",
_clipboardService,
_ => { },
() => { });
var propertyChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretFormViewModel.IsValueVisible))
propertyChangedRaised = true;
};
// Act
sut.IsValueVisible = true;
// Assert
propertyChangedRaised.ShouldBeTrue();
}
[Fact]
public void IsValueVisible_RaisesDisplayValueAndVisibilityButtonTextPropertyChanged()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"secret",
_clipboardService,
_ => { },
() => { });
var displayValueChangedRaised = false;
var visibilityButtonTextChangedRaised = false;
sut.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SecretFormViewModel.DisplayValue))
displayValueChangedRaised = true;
if (e.PropertyName == nameof(SecretFormViewModel.VisibilityButtonText))
visibilityButtonTextChangedRaised = true;
};
// Act
sut.IsValueVisible = true;
// Assert
displayValueChangedRaised.ShouldBeTrue();
visibilityButtonTextChangedRaised.ShouldBeTrue();
}
[Fact]
public void DisplayValue_ShowsMaskedValue_WhenNotVisible()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"secret123",
_clipboardService,
_ => { },
() => { });
// Act & Assert
sut.IsValueVisible.ShouldBeFalse();
sut.DisplayValue.ShouldBe("\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"); // 9 bullet points
}
[Fact]
public void DisplayValue_ShowsActualValue_WhenVisible()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"secret123",
_clipboardService,
_ => { },
() => { });
// Act
sut.IsValueVisible = true;
// Assert
sut.DisplayValue.ShouldBe("secret123");
}
[Fact]
public void DisplayValue_LimitsMaskedLength_ToTwentyCharacters()
{
// Arrange
var longValue = new string('x', 50);
var sut = new SecretFormViewModel(
"API_KEY",
longValue,
_clipboardService,
_ => { },
() => { });
// Act & Assert
sut.DisplayValue.Length.ShouldBe(20);
sut.DisplayValue.ShouldBe(new string('\u2022', 20));
}
[Fact]
public void DisplayValue_HandlesEmptyValue()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"",
_clipboardService,
_ => { },
() => { });
// Act & Assert
sut.DisplayValue.ShouldBe("");
}
[Fact]
public void VisibilityButtonText_ShowsShow_WhenHidden()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"secret",
_clipboardService,
_ => { },
() => { });
// Act & Assert
sut.VisibilityButtonText.ShouldBe("Show");
}
[Fact]
public void VisibilityButtonText_ShowsHide_WhenVisible()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"secret",
_clipboardService,
_ => { },
() => { });
// Act
sut.IsValueVisible = true;
// Assert
sut.VisibilityButtonText.ShouldBe("Hide");
}
[Fact]
public void ToggleVisibilityCommand_TogglesVisibility()
{
// Arrange
var sut = new SecretFormViewModel(
"API_KEY",
"secret",
_clipboardService,
_ => { },
() => { });
// Act & Assert - Toggle on
sut.ToggleVisibilityCommand.Execute(null);
sut.IsValueVisible.ShouldBeTrue();
// Act & Assert - Toggle off
sut.ToggleVisibilityCommand.Execute(null);
sut.IsValueVisible.ShouldBeFalse();
}
[Fact]
public async Task CopyToClipboardCommand_CopiesValueToClipboard()
{
// Arrange
_clipboardService.SetTextAsync(Arg.Any<string>()).Returns(Task.CompletedTask);
var sut = new SecretFormViewModel(
"API_KEY",
"secret-to-copy",
_clipboardService,
_ => { },
() => { });
// Act
sut.CopyToClipboardCommand.Execute(null);
// Small delay to allow async command to complete
await Task.Delay(50);
// Assert
await _clipboardService.Received(1).SetTextAsync("secret-to-copy");
}
[Fact]
public void DeleteCommand_InvokesCallback()
{
// Arrange
var deleteCalled = false;
var sut = new SecretFormViewModel(
"API_KEY",
"secret",
_clipboardService,
_ => { },
() => deleteCalled = true);
// Act
sut.DeleteCommand.Execute(null);
// Assert
deleteCalled.ShouldBeTrue();
}
[Fact]
public void Constructor_ThrowsOnNullKey()
{
// Act & Assert
Should.Throw<ArgumentNullException>(() =>
new SecretFormViewModel(null!, "value", _clipboardService, _ => { }, () => { }));
}
[Fact]
public void Constructor_ThrowsOnNullClipboardService()
{
// Act & Assert
Should.Throw<ArgumentNullException>(() =>
new SecretFormViewModel("key", "value", null!, _ => { }, () => { }));
}
[Fact]
public void Constructor_ThrowsOnNullValueChangedCallback()
{
// Act & Assert
Should.Throw<ArgumentNullException>(() =>
new SecretFormViewModel("key", "value", _clipboardService, null!, () => { }));
}
[Fact]
public void Constructor_ThrowsOnNullDeleteCallback()
{
// Act & Assert
Should.Throw<ArgumentNullException>(() =>
new SecretFormViewModel("key", "value", _clipboardService, _ => { }, null!));
}
[Fact]
public void Key_IsReadOnly()
{
// Assert - Verify Key property is get-only
var keyProperty = typeof(SecretFormViewModel).GetProperty(nameof(SecretFormViewModel.Key));
keyProperty!.CanWrite.ShouldBeFalse();
}
[Fact]
public void Value_DoesNotInvokeCallback_WhenValueUnchanged()
{
// Arrange
var callbackCount = 0;
var sut = new SecretFormViewModel(
"API_KEY",
"same-value",
_clipboardService,
_ => callbackCount++,
() => { });
// Act
sut.Value = "same-value"; // Same as initial value
// Assert
callbackCount.ShouldBe(0);
}
}