Reverses row order in LogVisualizerViewModel.Apply() so the most recent entry sits at index 0, matching the "what just happened" use case; filtering and refresh are unaffected since the reversal happens after the warn/error filter is applied.
89 lines
3.0 KiB
C#
89 lines
3.0 KiB
C#
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<WorkerLogEntry> _logs;
|
|
public FakeClient(IReadOnlyList<WorkerLogEntry> logs) => _logs = logs;
|
|
public override Task<IReadOnlyList<WorkerLogEntry>> 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));
|
|
|
|
private static WorkerLogEntry E(WorkerLogLevel lvl, string msg, DateTime timestampUtc)
|
|
=> new(msg, lvl, timestampUtc);
|
|
|
|
[Fact]
|
|
public async Task Refresh_populates_rows_from_worker_newest_first()
|
|
{
|
|
var vm = new LogVisualizerViewModel(new FakeClient(new[] { E(WorkerLogLevel.Info, "a"), E(WorkerLogLevel.Error, "b") }));
|
|
|
|
await vm.RefreshAsync();
|
|
|
|
Assert.Equal(new[] { "b", "a" }, 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[] { "e", "w" }, 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<WorkerLogEntry>()));
|
|
|
|
await vm.RefreshAsync();
|
|
|
|
Assert.Empty(vm.Rows);
|
|
Assert.False(string.IsNullOrEmpty(vm.StatusText));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Refresh_orders_newest_entry_first()
|
|
{
|
|
var t0 = new DateTime(2026, 6, 23, 8, 0, 0, DateTimeKind.Utc);
|
|
var vm = new LogVisualizerViewModel(new FakeClient(new[]
|
|
{
|
|
E(WorkerLogLevel.Info, "oldest", t0),
|
|
E(WorkerLogLevel.Info, "middle", t0.AddMinutes(1)),
|
|
E(WorkerLogLevel.Info, "newest", t0.AddMinutes(2)),
|
|
}));
|
|
|
|
await vm.RefreshAsync();
|
|
|
|
Assert.Equal(new[] { "newest", "middle", "oldest" }, vm.Rows.Select(r => r.Message));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Refresh_orders_newest_entry_first_with_warn_error_only()
|
|
{
|
|
var t0 = new DateTime(2026, 6, 23, 8, 0, 0, DateTimeKind.Utc);
|
|
var vm = new LogVisualizerViewModel(new FakeClient(new[]
|
|
{
|
|
E(WorkerLogLevel.Warn, "oldest", t0),
|
|
E(WorkerLogLevel.Info, "skipped", t0.AddMinutes(1)),
|
|
E(WorkerLogLevel.Error, "middle", t0.AddMinutes(2)),
|
|
E(WorkerLogLevel.Warn, "newest", t0.AddMinutes(3)),
|
|
}));
|
|
await vm.RefreshAsync();
|
|
|
|
vm.WarnErrorOnly = true;
|
|
|
|
Assert.Equal(new[] { "newest", "middle", "oldest" }, vm.Rows.Select(r => r.Message));
|
|
}
|
|
}
|