using ClaudeDo.Data.Models; using ClaudeDo.Ui.Services; using ClaudeDo.Ui.ViewModels.Modals; namespace ClaudeDo.Ui.Tests.ViewModels; public class LogVisualizerViewModelTests { private sealed class FakeClient : StubWorkerClient { private readonly IReadOnlyList _logs; public FakeClient(IReadOnlyList logs) => _logs = logs; public override Task> GetRecentLogsAsync() => Task.FromResult(_logs); } private static WorkerLogEntry E(WorkerLogLevel lvl, string msg) => new(msg, lvl, new DateTime(2026, 6, 23, 8, 0, 0, DateTimeKind.Utc)); [Fact] public async Task Refresh_populates_rows_from_worker() { var vm = new LogVisualizerViewModel(new FakeClient(new[] { E(WorkerLogLevel.Info, "a"), E(WorkerLogLevel.Error, "b") })); await vm.RefreshAsync(); Assert.Equal(new[] { "a", "b" }, vm.Rows.Select(r => r.Message)); } [Fact] public async Task WarnErrorOnly_filters_out_info() { var vm = new LogVisualizerViewModel(new FakeClient(new[] { E(WorkerLogLevel.Info, "a"), E(WorkerLogLevel.Warn, "w"), E(WorkerLogLevel.Error, "e") })); await vm.RefreshAsync(); vm.WarnErrorOnly = true; Assert.Equal(new[] { "w", "e" }, vm.Rows.Select(r => r.Message)); } [Fact] public async Task Empty_logs_yield_no_rows_and_a_status() { var vm = new LogVisualizerViewModel(new FakeClient(Array.Empty())); await vm.RefreshAsync(); Assert.Empty(vm.Rows); Assert.False(string.IsNullOrEmpty(vm.StatusText)); } }