feat(ui): add copy-last-40-lines button to log visualizer
This commit is contained in:
@@ -85,4 +85,95 @@ public class LogVisualizerViewModelTests
|
||||
|
||||
Assert.Equal(new[] { "newest", "middle", "oldest" }, vm.Rows.Select(r => r.Message));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CopyLast_orders_chronologically_oldest_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.Warn, "middle", t0.AddMinutes(1)),
|
||||
E(WorkerLogLevel.Error, "newest", t0.AddMinutes(2)),
|
||||
}));
|
||||
await vm.RefreshAsync();
|
||||
|
||||
var text = vm.BuildCopyText();
|
||||
|
||||
var lines = text.Split('\n');
|
||||
Assert.Equal(3, lines.Length);
|
||||
Assert.EndsWith("INFO oldest", lines[0]);
|
||||
Assert.EndsWith("WARN middle", lines[1]);
|
||||
Assert.EndsWith("ERROR newest", lines[2]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CopyLast_caps_at_40_most_recent_entries()
|
||||
{
|
||||
var t0 = new DateTime(2026, 6, 23, 8, 0, 0, DateTimeKind.Utc);
|
||||
var entries = Enumerable.Range(0, 50)
|
||||
.Select(i => E(WorkerLogLevel.Info, $"line{i}", t0.AddMinutes(i)))
|
||||
.ToArray();
|
||||
var vm = new LogVisualizerViewModel(new FakeClient(entries));
|
||||
await vm.RefreshAsync();
|
||||
|
||||
var lines = vm.BuildCopyText().Split('\n');
|
||||
|
||||
Assert.Equal(40, lines.Length);
|
||||
Assert.EndsWith("line10", lines[0]);
|
||||
Assert.EndsWith("line49", lines[^1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CopyLast_respects_active_warn_error_filter()
|
||||
{
|
||||
var t0 = new DateTime(2026, 6, 23, 8, 0, 0, DateTimeKind.Utc);
|
||||
var vm = new LogVisualizerViewModel(new FakeClient(new[]
|
||||
{
|
||||
E(WorkerLogLevel.Info, "skipped", t0),
|
||||
E(WorkerLogLevel.Warn, "kept", t0.AddMinutes(1)),
|
||||
}));
|
||||
await vm.RefreshAsync();
|
||||
vm.WarnErrorOnly = true;
|
||||
|
||||
var lines = vm.BuildCopyText().Split('\n');
|
||||
|
||||
Assert.Single(lines);
|
||||
Assert.EndsWith("WARN kept", lines[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CopyLastCommand_disabled_when_no_rows()
|
||||
{
|
||||
var vm = new LogVisualizerViewModel(new FakeClient(Array.Empty<WorkerLogEntry>()));
|
||||
await vm.RefreshAsync();
|
||||
|
||||
Assert.False(vm.CopyLastCommand.CanExecute(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CopyLastCommand_copies_and_reports_count_on_success()
|
||||
{
|
||||
string? copied = null;
|
||||
var vm = new LogVisualizerViewModel(new FakeClient(new[] { E(WorkerLogLevel.Info, "a") }),
|
||||
text => { copied = text; return Task.FromResult(true); });
|
||||
await vm.RefreshAsync();
|
||||
|
||||
await vm.CopyLastCommand.ExecuteAsync(null);
|
||||
|
||||
Assert.EndsWith("INFO a", copied);
|
||||
Assert.Contains("1", vm.StatusText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CopyLastCommand_reports_failure_when_clipboard_unavailable()
|
||||
{
|
||||
var vm = new LogVisualizerViewModel(new FakeClient(new[] { E(WorkerLogLevel.Info, "a") }),
|
||||
_ => Task.FromResult(false));
|
||||
await vm.RefreshAsync();
|
||||
|
||||
await vm.CopyLastCommand.ExecuteAsync(null);
|
||||
|
||||
Assert.False(string.IsNullOrEmpty(vm.StatusText));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user