242 lines
7.3 KiB
C#
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);
|
|
}
|
|
}
|