239 lines
6.9 KiB
C#
239 lines
6.9 KiB
C#
// -----------------------------------------------------------------------------
|
|
// SealCommandTests.cs
|
|
// Sprint: SPRINT_20260105_002_004_CLI (CLI-006)
|
|
// Description: Unit tests for facet seal CLI command.
|
|
// -----------------------------------------------------------------------------
|
|
|
|
using System.CommandLine;
|
|
using Moq;
|
|
using Xunit;
|
|
using StellaOps.Cli.Commands;
|
|
|
|
namespace StellaOps.Cli.Tests.Commands;
|
|
|
|
/// <summary>
|
|
/// Unit tests for the seal command structure.
|
|
/// </summary>
|
|
[Trait("Category", "Unit")]
|
|
public sealed class SealCommandTests
|
|
{
|
|
[Fact]
|
|
public void SealCommand_HasCorrectName()
|
|
{
|
|
// Arrange & Act
|
|
var command = BuildSealCommand();
|
|
|
|
// Assert
|
|
Assert.Equal("seal", command.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_HasCorrectDescription()
|
|
{
|
|
// Arrange & Act
|
|
var command = BuildSealCommand();
|
|
|
|
// Assert
|
|
Assert.Contains("facet seal", command.Description);
|
|
Assert.Contains("drift detection", command.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_HasImageArgument()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
|
|
// Act
|
|
var imageArg = command.Arguments.FirstOrDefault(a => a.Name == "image");
|
|
|
|
// Assert
|
|
Assert.NotNull(imageArg);
|
|
// Arguments are required by default in System.CommandLine
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_HasOutputOption()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
|
|
// Act
|
|
var outputOpt = command.Options.FirstOrDefault(o =>
|
|
o.Name == "output" || o.Name == "--output" || o.Aliases.Contains("--output"));
|
|
|
|
// Assert
|
|
Assert.NotNull(outputOpt);
|
|
Assert.True(outputOpt.Aliases.Contains("-o") || outputOpt.Aliases.Contains("--output"));
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_HasStoreOption()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
|
|
// Act
|
|
var storeOpt = command.Options.FirstOrDefault(o =>
|
|
o.Name == "store" || o.Name == "--store" || o.Aliases.Contains("--store"));
|
|
|
|
// Assert
|
|
Assert.NotNull(storeOpt);
|
|
Assert.Contains("Store seal", storeOpt.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_HasSignOption()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
|
|
// Act
|
|
var signOpt = command.Options.FirstOrDefault(o =>
|
|
o.Name == "sign" || o.Name == "--sign" || o.Aliases.Contains("--sign"));
|
|
|
|
// Assert
|
|
Assert.NotNull(signOpt);
|
|
Assert.Contains("Sign", signOpt.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_HasKeyOption()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
|
|
// Act
|
|
var keyOpt = command.Options.FirstOrDefault(o =>
|
|
o.Name == "key" || o.Name == "--key" || o.Aliases.Contains("--key"));
|
|
|
|
// Assert
|
|
Assert.NotNull(keyOpt);
|
|
Assert.True(keyOpt.Aliases.Contains("-k") || keyOpt.Aliases.Contains("--key"));
|
|
Assert.Contains("Private key", keyOpt.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_HasFacetsOption()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
|
|
// Act
|
|
var facetsOpt = command.Options.FirstOrDefault(o =>
|
|
o.Name == "facets" || o.Name == "--facets" || o.Aliases.Contains("--facets"));
|
|
|
|
// Assert
|
|
Assert.NotNull(facetsOpt);
|
|
Assert.True(facetsOpt.Aliases.Contains("-f") || facetsOpt.Aliases.Contains("--facets"));
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_HasFormatOption()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
|
|
// Act
|
|
var formatOpt = command.Options.FirstOrDefault(o =>
|
|
o.Name == "format" || o.Name == "--format" || o.Aliases.Contains("--format"));
|
|
|
|
// Assert
|
|
Assert.NotNull(formatOpt);
|
|
Assert.Contains("json", formatOpt.Description);
|
|
Assert.Contains("yaml", formatOpt.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_HasVerboseOption()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
|
|
// Act
|
|
var verboseOpt = command.Options.FirstOrDefault(o =>
|
|
o.Name == "verbose" || o.Name == "--verbose" || o.Aliases.Contains("--verbose"));
|
|
|
|
// Assert
|
|
Assert.NotNull(verboseOpt);
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_AllOptionsAreConfigured()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
var expectedOptions = new[] { "output", "store", "sign", "key", "facets", "format", "verbose" };
|
|
|
|
// Act - normalize all option names by stripping leading dashes
|
|
var actualOptionNames = command.Options
|
|
.SelectMany(o => new[] { o.Name.TrimStart('-') }.Concat(o.Aliases.Select(a => a.TrimStart('-'))))
|
|
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
|
var actualArgs = command.Arguments.Select(a => a.Name).ToHashSet();
|
|
|
|
// Assert - image is an argument
|
|
Assert.Contains("image", actualArgs);
|
|
foreach (var expected in expectedOptions)
|
|
{
|
|
Assert.Contains(expected, actualOptionNames);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_ImageArgument_HasCorrectDescription()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
var imageArg = command.Arguments.First(a => a.Name == "image");
|
|
|
|
// Assert
|
|
Assert.Contains("Image", imageArg.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_OutputOption_HasCorrectAliases()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
var outputOpt = command.Options.First(o =>
|
|
o.Name == "output" || o.Name == "--output" || o.Aliases.Contains("--output"));
|
|
|
|
// Assert
|
|
Assert.True(outputOpt.Aliases.Contains("--output") || outputOpt.Aliases.Contains("-o"));
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_KeyOption_HasCorrectAliases()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
var keyOpt = command.Options.First(o =>
|
|
o.Name == "key" || o.Name == "--key" || o.Aliases.Contains("--key"));
|
|
|
|
// Assert
|
|
Assert.True(keyOpt.Aliases.Contains("--key") || keyOpt.Aliases.Contains("-k"));
|
|
}
|
|
|
|
[Fact]
|
|
public void SealCommand_FacetsOption_HasCorrectAliases()
|
|
{
|
|
// Arrange
|
|
var command = BuildSealCommand();
|
|
var facetsOpt = command.Options.First(o =>
|
|
o.Name == "facets" || o.Name == "--facets" || o.Aliases.Contains("--facets"));
|
|
|
|
// Assert
|
|
Assert.True(facetsOpt.Aliases.Contains("--facets") || facetsOpt.Aliases.Contains("-f"));
|
|
}
|
|
|
|
private static Command BuildSealCommand()
|
|
{
|
|
var mockServices = new Mock<IServiceProvider>();
|
|
var verboseOption = new Option<bool>("--verbose");
|
|
return SealCommandGroup.BuildSealCommand(
|
|
mockServices.Object,
|
|
verboseOption,
|
|
CancellationToken.None);
|
|
}
|
|
}
|