using System.CommandLine;
using ScadaLink.CLI.Commands;
using ScadaLink.Commons.Messages.Management;
namespace ScadaLink.CLI.Tests.Commands;
///
/// Tests for the scadalink notification smtp update subcommand. The command
/// gained two optional flags — --tls-mode and --credentials — that plumb
/// through to . These tests pin that the flags
/// parse, are genuinely optional (non-breaking), and that --tls-mode rejects
/// values outside the canonical {None, StartTLS, SSL} set.
///
public class SmtpUpdateCommandTests
{
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 Command SmtpUpdateCommand()
{
var notification = NotificationCommands.Build(Url, Format, Username, Password);
var smtp = notification.Subcommands.Single(c => c.Name == "smtp");
return smtp.Subcommands.Single(c => c.Name == "update");
}
private static ParseResult ParseUpdate(params string[] args)
=> SmtpUpdateCommand().Parse(args);
[Fact]
public void Update_WithTlsModeAndCredentials_ProducesCommandCarryingThem()
{
var parse = ParseUpdate(
"--id", "1", "--server", "smtp.example.com", "--port", "587",
"--auth-mode", "Basic", "--from-address", "noreply@example.com",
"--tls-mode", "None", "--credentials", "user:pass");
Assert.Empty(parse.Errors);
var cmd = NotificationCommands.BuildUpdateSmtpConfigCommand(parse);
Assert.Equal(1, cmd.SmtpConfigId);
Assert.Equal("smtp.example.com", cmd.Server);
Assert.Equal(587, cmd.Port);
Assert.Equal("Basic", cmd.AuthMode);
Assert.Equal("noreply@example.com", cmd.FromAddress);
Assert.Equal("None", cmd.TlsMode);
Assert.Equal("user:pass", cmd.Credentials);
}
[Fact]
public void Update_WithoutTlsModeAndCredentials_ProducesCommandWithNulls()
{
var parse = ParseUpdate(
"--id", "2", "--server", "smtp.example.com", "--port", "25",
"--auth-mode", "OAuth2", "--from-address", "noreply@example.com");
Assert.Empty(parse.Errors);
var cmd = NotificationCommands.BuildUpdateSmtpConfigCommand(parse);
Assert.Equal(2, cmd.SmtpConfigId);
Assert.Null(cmd.TlsMode);
Assert.Null(cmd.Credentials);
}
[Theory]
[InlineData("None")]
[InlineData("StartTLS")]
[InlineData("SSL")]
public void Update_TlsModeOption_AcceptsCanonicalValues(string value)
{
var parse = ParseUpdate(
"--id", "1", "--server", "smtp.example.com", "--port", "587",
"--auth-mode", "Basic", "--from-address", "noreply@example.com",
"--tls-mode", value);
Assert.Empty(parse.Errors);
}
[Theory]
[InlineData("Bogus")]
[InlineData("tls")]
[InlineData("none")] // AcceptOnlyFromAmong is case-sensitive: constrain to canonical spelling
public void Update_TlsModeOption_RejectsValuesOutsideCanonicalSet(string value)
{
var parse = ParseUpdate(
"--id", "1", "--server", "smtp.example.com", "--port", "587",
"--auth-mode", "Basic", "--from-address", "noreply@example.com",
"--tls-mode", value);
Assert.NotEmpty(parse.Errors);
}
[Fact]
public void Update_TlsModeAndCredentials_AreNotRequired()
{
var update = SmtpUpdateCommand();
var tls = update.Options.Single(o => o.Name == "--tls-mode");
var creds = update.Options.Single(o => o.Name == "--credentials");
Assert.False(tls.Required, "--tls-mode must be optional (preserve-if-omitted).");
Assert.False(creds.Required, "--credentials must be optional (preserve-if-omitted).");
}
}