test(app): add docker and main window view model tests

This commit is contained in:
dualfroz committed 2026-08-28 18:49:19 +02:00
1 parent 1f1b78e50b
commit 36fbba0250
3 files changed
+179

No files matched your search

@@ -0,0 +1,47 @@
using Vantage.App.ViewModels;
using Vantage.Core.Docker;
using Vantage.Core.Models;
using Xunit;
namespace Vantage.App.Tests;
public class DockerViewModelTests
{
[Fact]
public async Task RefreshAsync_PopulatesContainersForHost()
{
var viewModel = new DockerViewModel(new MockDockerProvider());
viewModel.SetHost(new HostConfig { Id = "h1" });
await viewModel.RefreshAsync(CancellationToken.None);
Assert.NotEmpty(viewModel.Containers);
}
[Fact]
public async Task RefreshAsync_WithoutHostDoesNothing()
{
var viewModel = new DockerViewModel(new MockDockerProvider());
await viewModel.RefreshAsync(CancellationToken.None);
Assert.Empty(viewModel.Containers);
}
[Fact]
public async Task StopCommand_TransitionsSelectedContainerToExited()
{
var viewModel = new DockerViewModel(new MockDockerProvider());
viewModel.SetHost(new HostConfig { Id = "h2" });
await viewModel.RefreshAsync(CancellationToken.None);
var running = viewModel.Containers.First(c => c.IsRunning);
viewModel.SelectedContainer = running;
await viewModel.StopCommand.ExecuteAsync(running);
var reloaded = viewModel.Containers.First(c => c.Id == running.Id);
Assert.Equal(ContainerState.Exited, reloaded.State);
Assert.False(reloaded.IsRunning);
}
}
@@ -0,0 +1,70 @@
using Vantage.App.Tests.Fakes;
using Vantage.App.ViewModels;
using Vantage.Core.Configuration;
using Vantage.Core.Docker;
using Vantage.Core.Health;
using Vantage.Core.Metrics;
using Xunit;
namespace Vantage.App.Tests;
public class MainWindowViewModelTests
{
private static IConfigStore EmptyStore() =>
new JsonConfigStore(Path.Combine(Path.GetTempPath(), "vantage-vm-" + Guid.NewGuid().ToString("N"), "config.json"));
private static MainWindowViewModel Build(IMetricsProvider metrics, IHealthChecker? health = null) =>
new(metrics, new MockDockerProvider(), health ?? new HealthChecker(new HttpClient()), EmptyStore());
[Fact]
public async Task InitializeAsync_FallsBackToDemoDataWhenConfigEmpty()
{
var viewModel = Build(new MockMetricsProvider());
await viewModel.InitializeAsync();
Assert.NotEmpty(viewModel.Hosts);
Assert.NotEmpty(viewModel.HealthChecks);
Assert.NotNull(viewModel.SelectedHost);
Assert.Same(viewModel.Hosts[0].Config, viewModel.Docker.Host);
}
[Fact]
public async Task RefreshSelectedHostAsync_PopulatesMetricsAndHistory()
{
var viewModel = Build(new MockMetricsProvider());
await viewModel.InitializeAsync();
await viewModel.RefreshSelectedHostAsync(CancellationToken.None);
Assert.True(viewModel.SelectedHost!.IsOnline);
Assert.NotEmpty(viewModel.SelectedHost.CpuPoints);
Assert.StartsWith("Updated", viewModel.StatusLine);
}
[Fact]
public async Task RefreshSelectedHostAsync_MarksHostUnreachableOnFailure()
{
var viewModel = Build(new ThrowingMetricsProvider());
await viewModel.InitializeAsync();
await viewModel.RefreshSelectedHostAsync(CancellationToken.None);
Assert.False(viewModel.SelectedHost!.IsOnline);
Assert.Equal(ThrowingMetricsProvider.Message, viewModel.SelectedHost.LastError);
Assert.Contains(ThrowingMetricsProvider.Message, viewModel.StatusLine);
}
[Fact]
public async Task RunAllHealthAsync_RunsEveryConfiguredCheck()
{
var health = new FakeHealthChecker(Vantage.Core.Models.HealthCheckResult.Up(5, "ok"));
var viewModel = Build(new MockMetricsProvider(), health);
await viewModel.InitializeAsync();
await viewModel.RunAllHealthAsync(CancellationToken.None);
Assert.Equal(viewModel.HealthChecks.Count, health.Calls);
Assert.All(viewModel.HealthChecks, check => Assert.StartsWith("Up", check.StatusText));
}
}
@@ -0,0 +1,62 @@
using Vantage.App.Tests.Fakes;
using Vantage.App.ViewModels;
using Vantage.Core.Models;
using Xunit;
namespace Vantage.App.Tests;
public class ViewModelBindingTests
{
[Fact]
public void HostViewModel_ApplyMetricsUpdatesTextsAndHistory()
{
var host = new HostViewModel(new HostConfig { Name = "node", Address = "10.0.0.5", Username = "root", Port = 22 }, historyLength: 10);
host.ApplyMetrics(new HostMetrics
{
CpuUsagePercent = 42.5,
MemoryUsedBytes = 4L * 1024 * 1024 * 1024,
MemoryTotalBytes = 8L * 1024 * 1024 * 1024,
DiskUsedBytes = 50L * 1024 * 1024 * 1024,
DiskTotalBytes = 100L * 1024 * 1024 * 1024,
Load1 = 0.8,
Load5 = 0.6,
Load15 = 0.4,
Uptime = TimeSpan.FromHours(50)
});
Assert.Equal(42.5, host.CpuUsagePercent);
Assert.Equal(50.0, host.MemoryUsedPercent);
Assert.Single(host.CpuPoints);
Assert.Equal("4.0 GiB / 8.0 GiB", host.MemoryText);
Assert.True(host.IsOnline);
Assert.Equal("node", host.Name);
Assert.Equal("root@10.0.0.5:22", host.Endpoint);
}
[Fact]
public void HostViewModel_ApplyErrorMarksOffline()
{
var host = new HostViewModel(new HostConfig { Name = "node" }, historyLength: 10);
host.ApplyError("connection refused");
Assert.False(host.IsOnline);
Assert.Equal("connection refused", host.LastError);
Assert.Equal("Unreachable", host.StatusText);
}
[Fact]
public async Task HealthCheckViewModel_RunAppliesResult()
{
var config = new HealthCheckConfig { Name = "web", Kind = HealthKind.Http, Target = "https://x" };
var checker = new FakeHealthChecker(HealthCheckResult.Up(12.4, "HTTP 200 OK"));
var viewModel = new HealthCheckViewModel(config, checker);
await viewModel.RunCommand.ExecuteAsync(null);
Assert.Equal(HealthStatus.Up, viewModel.Status);
Assert.StartsWith("Up", viewModel.StatusText);
Assert.Equal("12 ms", viewModel.LatencyText);
}
}