using System.CommandLine; using ScadaLink.CLI.Commands; namespace ScadaLink.CLI.Tests.Commands; /// /// Tests for the audit-logaudit-config rename (Audit Log #23 M8-T7): /// the new name parses, the deprecated audit-log alias still resolves the full /// subcommand tree and emits a stderr deprecation warning, and the renamed group does /// not collide with the distinct audit group from Bundle A. /// public class AuditConfigDeprecationTests { private static readonly Option Url = new("--url") { Recursive = true }; private static readonly Option Username = new("--username") { Recursive = true }; private static readonly Option Password = new("--password") { Recursive = true }; private static readonly Option Format = CliOptions.CreateFormatOption(); private static RootCommand BuildRoot() { var root = new RootCommand(); root.Add(Url); root.Add(Username); root.Add(Password); root.Add(Format); root.Add(AuditCommands.Build(Url, Format, Username, Password)); root.Add(AuditLogCommands.Build(Url, Format, Username, Password)); return root; } [Fact] public void AuditConfig_Query_Works() { // The new `audit-config query` name parses cleanly with no errors. var root = BuildRoot(); var parse = root.Parse(new[] { "audit-config", "query", "--user", "alice" }); Assert.Empty(parse.Errors); } [Fact] public void AuditLog_Query_StillWorks_ButEmitsDeprecationWarning_ToStderr() { // The deprecated `audit-log` alias still resolves the full subcommand tree... var root = BuildRoot(); var parse = root.Parse(new[] { "audit-log", "query", "--user", "alice" }); Assert.Empty(parse.Errors); // ...and invoking via the old name emits the deprecation warning to stderr. var stderr = new StringWriter(); AuditLogCommands.WriteDeprecationWarningIfNeeded( new[] { "audit-log", "query" }, stderr); var warning = stderr.ToString(); Assert.Contains("deprecated", warning); Assert.Contains("audit-config", warning); } [Fact] public void DeprecationWarning_NotEmitted_ForNewName() { // The new `audit-config` name must not trigger the deprecation warning. var stderr = new StringWriter(); AuditLogCommands.WriteDeprecationWarningIfNeeded( new[] { "audit-config", "query" }, stderr); Assert.Equal("", stderr.ToString()); } [Fact] public void DeprecationWarning_NotEmitted_ForUnrelatedCommand() { var stderr = new StringWriter(); AuditLogCommands.WriteDeprecationWarningIfNeeded( new[] { "audit", "query" }, stderr); Assert.Equal("", stderr.ToString()); } [Fact] public void Audit_And_AuditConfig_AreDistinctCommands_NoConflict() { var root = BuildRoot(); var auditNames = new[] { "audit", "audit-config" }; foreach (var name in auditNames) { var match = root.Subcommands.SingleOrDefault(c => c.Name == name); Assert.NotNull(match); } // The two groups are distinct objects with distinct subcommand sets: // `audit` has query/export/verify-chain; `audit-config` has only query. var audit = root.Subcommands.Single(c => c.Name == "audit"); var auditConfig = root.Subcommands.Single(c => c.Name == "audit-config"); Assert.NotSame(audit, auditConfig); Assert.Contains(audit.Subcommands, c => c.Name == "verify-chain"); Assert.DoesNotContain(auditConfig.Subcommands, c => c.Name == "verify-chain"); // `audit-config` carries the deprecated `audit-log` alias; `audit` does not. Assert.Contains(AuditLogCommands.DeprecatedAlias, auditConfig.Aliases); Assert.DoesNotContain(AuditLogCommands.DeprecatedAlias, audit.Aliases); } }