feat(configmanager): add config set and connection update CLI commands

Add missing CLI commands to match UI capabilities: config set commands for
all configuration sections (datasync, dataaccess, auth, ldap, search,
excelexport) and connection update command. Also adds unit tests for
SecretCommands, ValidateCommand, and TestConnectionCommand.
This commit is contained in:
Joseph Doherty
2026-01-28 15:10:22 -05:00
parent bad0102af1
commit 61694ca50b
11 changed files with 2172 additions and 2 deletions
@@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection;
namespace JdeScoping.ConfigManager.Cli.Tests.Commands;
[Collection("Console Tests")]
public class ConnectionCommandsTests
{
private readonly IServiceProvider _serviceProvider;
@@ -416,4 +417,246 @@ public class ConnectionCommandsTests
Directory.Delete(tempDir, true);
}
}
// ===== Connection Update Command Tests =====
[Fact]
public void CreateUpdateCommand_ReturnsCommandWithOptions()
{
// Act
var command = ConnectionCommands.CreateUpdateCommand(
_serviceProvider, _configPathOption, _verboseOption, _quietOption);
// Assert
command.ShouldNotBeNull();
command.Name.ShouldBe("update");
command.Arguments.ShouldContain(a => a.Name == "name");
command.Options.ShouldContain(o => o.Name == "provider");
command.Options.ShouldContain(o => o.Name == "server");
command.Options.ShouldContain(o => o.Name == "database");
command.Options.ShouldContain(o => o.Name == "user");
command.Options.ShouldContain(o => o.Name == "password");
command.Options.ShouldContain(o => o.Name == "port");
command.Options.ShouldContain(o => o.Name == "service-name");
command.Options.ShouldContain(o => o.Name == "raw");
}
[Fact]
public void UpdateCommand_HasCorrectDescription()
{
// Arrange & Act
var command = ConnectionCommands.CreateUpdateCommand(
_serviceProvider, _configPathOption, _verboseOption, _quietOption);
// Assert
command.Description.ShouldBe("Update an existing connection");
}
[Fact]
public async Task UpdateCommand_WithNonExistentConnection_ReturnsError()
{
// Arrange
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempDir);
var appSettingsPath = Path.Combine(tempDir, "appsettings.json");
File.WriteAllText(appSettingsPath, "{}");
try
{
_autoDiscoveryService.FindConfigFolderAsync(Arg.Any<CancellationToken>())
.Returns(Task.FromResult<string?>(tempDir));
var config = new ConfigModel();
_configFileService.LoadAppSettingsAsync(appSettingsPath, Arg.Any<CancellationToken>())
.Returns(Task.FromResult(config));
var command = ConnectionCommands.CreateUpdateCommand(
_serviceProvider, _configPathOption, _verboseOption, _quietOption);
var rootCommand = new RootCommand { command };
rootCommand.AddGlobalOption(_configPathOption);
rootCommand.AddGlobalOption(_verboseOption);
rootCommand.AddGlobalOption(_quietOption);
// Capture console error output
var originalErr = Console.Error;
using var writer = new StringWriter();
Console.SetError(writer);
try
{
// Act
await rootCommand.InvokeAsync(["update", "NonExistent", "--server", "newhost"]);
// Assert
var output = writer.ToString();
output.ShouldContain("not found");
}
finally
{
Console.SetError(originalErr);
}
}
finally
{
Directory.Delete(tempDir, true);
}
}
[Fact]
public void UpdateCommand_AllOptionsExist()
{
// Arrange & Act
var command = ConnectionCommands.CreateUpdateCommand(
_serviceProvider, _configPathOption, _verboseOption, _quietOption);
// Assert - Verify all options exist
command.Options.ShouldContain(o => o.Name == "provider");
command.Options.ShouldContain(o => o.Name == "server");
command.Options.ShouldContain(o => o.Name == "database");
command.Options.ShouldContain(o => o.Name == "user");
command.Options.ShouldContain(o => o.Name == "password");
command.Options.ShouldContain(o => o.Name == "port");
command.Options.ShouldContain(o => o.Name == "service-name");
command.Options.ShouldContain(o => o.Name == "raw");
}
[Fact]
public async Task UpdateCommand_WithValidChange_UpdatesAndSaves()
{
// Arrange
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempDir);
var appSettingsPath = Path.Combine(tempDir, "appsettings.json");
File.WriteAllText(appSettingsPath, "{}");
try
{
_autoDiscoveryService.FindConfigFolderAsync(Arg.Any<CancellationToken>())
.Returns(Task.FromResult<string?>(tempDir));
var config = new ConfigModel
{
ConnectionStrings = new ConnectionStringsSection
{
Entries =
[
new ConnectionStringEntry
{
Name = "TestConnection",
Provider = ConnectionProvider.SqlServer,
Server = "localhost",
Database = "OldDb"
}
]
}
};
_configFileService.LoadAppSettingsAsync(appSettingsPath, Arg.Any<CancellationToken>())
.Returns(Task.FromResult(config));
var command = ConnectionCommands.CreateUpdateCommand(
_serviceProvider, _configPathOption, _verboseOption, _quietOption);
var rootCommand = new RootCommand { command };
rootCommand.AddGlobalOption(_configPathOption);
rootCommand.AddGlobalOption(_verboseOption);
rootCommand.AddGlobalOption(_quietOption);
// Capture console output
var originalOut = Console.Out;
using var writer = new StringWriter();
Console.SetOut(writer);
try
{
// Act
await rootCommand.InvokeAsync(["update", "TestConnection", "--database", "NewDb"]);
// Assert
var output = writer.ToString();
output.ShouldContain("updated successfully");
await _configFileService.Received(1).SaveAppSettingsAsync(appSettingsPath, Arg.Any<ConfigModel>(), Arg.Any<CancellationToken>());
}
finally
{
Console.SetOut(originalOut);
}
}
finally
{
Directory.Delete(tempDir, true);
}
}
[Fact]
public async Task UpdateCommand_WithMultipleChanges_UpdatesAllProperties()
{
// Arrange
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempDir);
var appSettingsPath = Path.Combine(tempDir, "appsettings.json");
File.WriteAllText(appSettingsPath, "{}");
try
{
_autoDiscoveryService.FindConfigFolderAsync(Arg.Any<CancellationToken>())
.Returns(Task.FromResult<string?>(tempDir));
var config = new ConfigModel
{
ConnectionStrings = new ConnectionStringsSection
{
Entries =
[
new ConnectionStringEntry
{
Name = "TestConnection",
Provider = ConnectionProvider.SqlServer,
Server = "localhost",
Database = "OldDb",
UserId = "olduser"
}
]
}
};
_configFileService.LoadAppSettingsAsync(appSettingsPath, Arg.Any<CancellationToken>())
.Returns(Task.FromResult(config));
var command = ConnectionCommands.CreateUpdateCommand(
_serviceProvider, _configPathOption, _verboseOption, _quietOption);
var rootCommand = new RootCommand { command };
rootCommand.AddGlobalOption(_configPathOption);
rootCommand.AddGlobalOption(_verboseOption);
rootCommand.AddGlobalOption(_quietOption);
// Capture console output
var originalOut = Console.Out;
using var writer = new StringWriter();
Console.SetOut(writer);
try
{
// Act
await rootCommand.InvokeAsync(["update", "TestConnection", "--server", "newhost", "--database", "NewDb", "--user", "newuser"]);
// Assert
var output = writer.ToString();
output.ShouldContain("updated successfully");
// Verify the config was updated
config.ConnectionStrings.Entries[0].Server.ShouldBe("newhost");
config.ConnectionStrings.Entries[0].Database.ShouldBe("NewDb");
config.ConnectionStrings.Entries[0].UserId.ShouldBe("newuser");
}
finally
{
Console.SetOut(originalOut);
}
}
finally
{
Directory.Delete(tempDir, true);
}
}
}