Files
git.stella-ops.org/src/Cli/__Tests/StellaOps.Cli.Tests/Commands/DriftCommandTests.cs

242 lines
7.3 KiB
C#

// -----------------------------------------------------------------------------
// DriftCommandTests.cs
// Sprint: SPRINT_20260105_002_004_CLI (CLI-010)
// Description: Unit tests for facet drift analysis CLI command.
// -----------------------------------------------------------------------------
using System.CommandLine;
using Moq;
using Xunit;
using StellaOps.Cli.Commands;
namespace StellaOps.Cli.Tests.Commands;
/// <summary>
/// Unit tests for the drift command structure.
/// </summary>
[Trait("Category", "Unit")]
public sealed class DriftCommandTests
{
[Fact]
public void DriftCommand_HasCorrectName()
{
// Arrange & Act
var command = BuildDriftCommand();
// Assert
Assert.Equal("drift", command.Name);
}
[Fact]
public void DriftCommand_HasCorrectDescription()
{
// Arrange & Act
var command = BuildDriftCommand();
// Assert
Assert.Contains("drift", command.Description);
Assert.Contains("baseline", command.Description);
}
[Fact]
public void DriftCommand_HasImageArgument()
{
// Arrange
var command = BuildDriftCommand();
// 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 DriftCommand_HasBaselineOption()
{
// Arrange
var command = BuildDriftCommand();
// Act
var baselineOpt = command.Options.FirstOrDefault(o =>
o.Name == "baseline" || o.Name == "--baseline" || o.Aliases.Contains("--baseline"));
// Assert
Assert.NotNull(baselineOpt);
Assert.True(baselineOpt.Aliases.Contains("-b") || baselineOpt.Aliases.Contains("--baseline"));
Assert.Contains("Baseline seal", baselineOpt.Description);
}
[Fact]
public void DriftCommand_HasFormatOption()
{
// Arrange
var command = BuildDriftCommand();
// Act
var formatOpt = command.Options.FirstOrDefault(o =>
o.Name == "format" || o.Name == "--format" || o.Aliases.Contains("--format"));
// Assert
Assert.NotNull(formatOpt);
Assert.Contains("table", formatOpt.Description);
Assert.Contains("json", formatOpt.Description);
Assert.Contains("yaml", formatOpt.Description);
}
[Fact]
public void DriftCommand_HasVerboseFilesOption()
{
// Arrange
var command = BuildDriftCommand();
// Act
var verboseFilesOpt = command.Options.FirstOrDefault(o =>
o.Name == "verbose-files" || o.Name == "--verbose-files" || o.Aliases.Contains("--verbose-files"));
// Assert
Assert.NotNull(verboseFilesOpt);
Assert.Contains("file changes", verboseFilesOpt.Description);
}
[Fact]
public void DriftCommand_HasFailOnBreachOption()
{
// Arrange
var command = BuildDriftCommand();
// Act
var failOnBreachOpt = command.Options.FirstOrDefault(o =>
o.Name == "fail-on-breach" || o.Name == "--fail-on-breach" || o.Aliases.Contains("--fail-on-breach"));
// Assert
Assert.NotNull(failOnBreachOpt);
Assert.Contains("error code", failOnBreachOpt.Description);
}
[Fact]
public void DriftCommand_HasOutputOption()
{
// Arrange
var command = BuildDriftCommand();
// 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 DriftCommand_HasVerboseOption()
{
// Arrange
var command = BuildDriftCommand();
// Act
var verboseOpt = command.Options.FirstOrDefault(o =>
o.Name == "verbose" || o.Name == "--verbose" || o.Aliases.Contains("--verbose"));
// Assert
Assert.NotNull(verboseOpt);
}
[Fact]
public void DriftCommand_AllOptionsAreConfigured()
{
// Arrange
var command = BuildDriftCommand();
var expectedOptions = new[]
{
"baseline", "format", "verbose-files", "fail-on-breach", "output", "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 now an argument, not an option
Assert.Contains("image", actualArgs);
foreach (var expected in expectedOptions)
{
Assert.Contains(expected, actualOptionNames);
}
}
[Fact]
public void DriftCommand_ImageArgument_HasCorrectDescription()
{
// Arrange
var command = BuildDriftCommand();
var imageArg = command.Arguments.First(a => a.Name == "image");
// Assert
Assert.Contains("Image", imageArg.Description);
}
[Fact]
public void DriftCommand_BaselineOption_HasCorrectAliases()
{
// Arrange
var command = BuildDriftCommand();
var baselineOpt = command.Options.First(o =>
o.Name == "baseline" || o.Name == "--baseline" || o.Aliases.Contains("--baseline"));
// Assert
Assert.True(baselineOpt.Aliases.Contains("--baseline") || baselineOpt.Aliases.Contains("-b"));
}
[Fact]
public void DriftCommand_OutputOption_HasCorrectAliases()
{
// Arrange
var command = BuildDriftCommand();
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 DriftCommand_FormatOption_SupportsAllFormats()
{
// Arrange
var command = BuildDriftCommand();
var formatOpt = command.Options.First(o =>
o.Name == "format" || o.Name == "--format" || o.Aliases.Contains("--format"));
// Assert - verify description mentions all supported formats
Assert.Contains("table", formatOpt.Description);
Assert.Contains("json", formatOpt.Description);
Assert.Contains("yaml", formatOpt.Description);
}
[Fact]
public void DriftCommand_FailOnBreachOption_ExplainsBehavior()
{
// Arrange
var command = BuildDriftCommand();
var failOnBreachOpt = command.Options.First(o =>
o.Name == "fail-on-breach" || o.Name == "--fail-on-breach" || o.Aliases.Contains("--fail-on-breach"));
// Assert
Assert.Contains("quota", failOnBreachOpt.Description);
}
private static Command BuildDriftCommand()
{
var mockServices = new Mock<IServiceProvider>();
var verboseOption = new Option<bool>("--verbose");
return DriftCommandGroup.BuildDriftCommand(
mockServices.Object,
verboseOption,
CancellationToken.None);
}
}