97 lines
3.1 KiB
C#
97 lines
3.1 KiB
C#
using ClaudeDo.Data.Models;
|
|
using ClaudeDo.Ui.ViewModels.Modals.Settings;
|
|
|
|
namespace ClaudeDo.Ui.Tests.ViewModels;
|
|
|
|
public sealed class SshSettingsTabViewModelTests
|
|
{
|
|
private sealed class Worker : StubWorkerClient
|
|
{
|
|
public List<SshWorkspace> Stored = new();
|
|
public override Task<List<SshWorkspace>> GetSshWorkspacesAsync() => Task.FromResult(Stored.ToList());
|
|
public override Task SetSshWorkspacesAsync(List<SshWorkspace> workspaces) { Stored = workspaces; return Task.CompletedTask; }
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseHosts_SkipsWildcardsAndComments_SplitsMultiAlias()
|
|
{
|
|
var text = """
|
|
# comment
|
|
Host *
|
|
User root
|
|
Host vps vps-alt
|
|
HostName 1.2.3.4
|
|
host gitea
|
|
Host *.internal
|
|
Match host foo
|
|
""";
|
|
Assert.Equal(["vps", "vps-alt", "gitea"], SshSettingsTabViewModel.ParseHosts(text));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task LoadAddSave_RoundTripsRows()
|
|
{
|
|
var worker = new Worker { Stored = [new SshWorkspace("w1", "VPS", "vps", "/srv/app")] };
|
|
var vm = new SshSettingsTabViewModel(worker, () => "Host vps");
|
|
|
|
await vm.LoadAsync();
|
|
Assert.Single(vm.Workspaces);
|
|
Assert.Equal(["vps"], vm.Hosts);
|
|
|
|
vm.AddCommand.Execute(null);
|
|
vm.Workspaces[1].Name = "Box";
|
|
vm.Workspaces[1].Host = "box";
|
|
vm.Workspaces[1].RemotePath = "~/code";
|
|
Assert.Null(vm.Validate());
|
|
|
|
await vm.SaveAsync();
|
|
Assert.Equal(2, worker.Stored.Count);
|
|
Assert.Equal("w1", worker.Stored[0].Id); // existing id preserved
|
|
Assert.False(string.IsNullOrEmpty(worker.Stored[1].Id)); // new row got an id
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_ReportsInvalidRow_AndRemoveDropsIt()
|
|
{
|
|
var vm = new SshSettingsTabViewModel(new Worker(), () => "");
|
|
await vm.LoadAsync();
|
|
vm.AddCommand.Execute(null);
|
|
vm.Workspaces[0].Name = "Bad";
|
|
vm.Workspaces[0].Host = "-oProxyCommand=calc";
|
|
vm.Workspaces[0].RemotePath = "/x";
|
|
|
|
Assert.NotNull(vm.Validate());
|
|
|
|
vm.Workspaces[0].RemoveCommand.Execute(null);
|
|
Assert.Empty(vm.Workspaces);
|
|
Assert.Null(vm.Validate());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task MissingSshConfig_YieldsNoHosts()
|
|
{
|
|
var vm = new SshSettingsTabViewModel(new Worker(), () => throw new FileNotFoundException());
|
|
await vm.LoadAsync();
|
|
Assert.Empty(vm.Hosts);
|
|
}
|
|
|
|
private sealed class OfflineWorker : StubWorkerClient
|
|
{
|
|
public bool SetCalled;
|
|
public override Task<List<SshWorkspace>> GetSshWorkspacesAsync() => throw new InvalidOperationException("offline");
|
|
public override Task SetSshWorkspacesAsync(List<SshWorkspace> workspaces) { SetCalled = true; return Task.CompletedTask; }
|
|
}
|
|
|
|
[Fact]
|
|
public async Task WorkerOffline_LoadDoesNotThrow_AndSaveDoesNotWipe()
|
|
{
|
|
var worker = new OfflineWorker();
|
|
var vm = new SshSettingsTabViewModel(worker, () => "");
|
|
|
|
await vm.LoadAsync();
|
|
await vm.SaveAsync();
|
|
|
|
Assert.False(worker.SetCalled);
|
|
}
|
|
}
|