Files
ClaudeDo/tests/ClaudeDo.Ui.Tests/IslandsShellViewModelWorkerLogTests.cs
T
2026-10-01 17:35:03 +02:00

108 lines
3.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ClaudeDo.Data.Models;
using ClaudeDo.Ui.Services;
using ClaudeDo.Ui.ViewModels;
using ClaudeDo.Ui.ViewModels.Modals;
using Xunit;
namespace ClaudeDo.Ui.Tests;
public class IslandsShellViewModelWorkerLogTests
{
[Fact]
public void Receiving_event_sets_text_level_and_visible()
{
var vm = new IslandsShellViewModel();
var at = new DateTime(2026, 4, 23, 14, 32, 0, DateTimeKind.Utc);
vm.OnWorkerLogReceived(new WorkerLogEntry("Created worktree for \"X\"", WorkerLogLevel.Info, at));
Assert.True(vm.IsWorkerLogVisible);
Assert.Equal(WorkerLogLevel.Info, vm.WorkerLogLevel);
Assert.Contains("Created worktree for \"X\"", vm.WorkerLogText);
}
[Fact]
public void Second_event_replaces_first()
{
var vm = new IslandsShellViewModel();
vm.OnWorkerLogReceived(new WorkerLogEntry("first", WorkerLogLevel.Info, DateTime.UtcNow));
vm.OnWorkerLogReceived(new WorkerLogEntry("second", WorkerLogLevel.Success, DateTime.UtcNow));
Assert.Contains("second", vm.WorkerLogText);
Assert.Equal(WorkerLogLevel.Success, vm.WorkerLogLevel);
}
[Fact]
public void ClearWorkerLog_hides_line()
{
var vm = new IslandsShellViewModel();
vm.OnWorkerLogReceived(new WorkerLogEntry("msg", WorkerLogLevel.Info, DateTime.UtcNow));
vm.ClearWorkerLog();
Assert.False(vm.IsWorkerLogVisible);
Assert.Null(vm.WorkerLogText);
}
[Fact]
public void Text_is_formatted_as_HHmm_dot_message_local_time()
{
var vm = new IslandsShellViewModel();
var utc = new DateTime(2026, 4, 23, 12, 0, 0, DateTimeKind.Utc);
var expectedLocalHhmm = utc.ToLocalTime().ToString("HH:mm");
vm.OnWorkerLogReceived(new WorkerLogEntry("hello", WorkerLogLevel.Info, utc));
Assert.StartsWith(expectedLocalHhmm + " · ", vm.WorkerLogText);
}
[Fact]
public async Task Visualizer_shows_flashed_and_received_footer_lines_with_their_levels()
{
var shell = new IslandsShellViewModel();
shell.FlashFooterInfo("claude 2.0 updating");
shell.OnWorkerLogReceived(new WorkerLogEntry("task merged", WorkerLogLevel.Success, DateTime.UtcNow.AddSeconds(1)));
var vm = new LogVisualizerViewModel(new BufferClient(), shell.FooterHistorySnapshot);
await vm.RefreshAsync();
Assert.Equal(new[] { ("task merged", WorkerLogLevel.Success), ("claude 2.0 updating", WorkerLogLevel.Info) },
vm.Rows.Select(r => (r.Message, r.Level)));
}
[Fact]
public async Task Footer_line_arriving_while_visualizer_is_open_shows_on_next_refresh()
{
var shell = new IslandsShellViewModel();
var vm = new LogVisualizerViewModel(new BufferClient(), shell.FooterHistorySnapshot);
await vm.RefreshAsync();
shell.FlashFooterError("boom");
await vm.RefreshAsync();
Assert.Equal(("boom", WorkerLogLevel.Error), (vm.Rows.Single().Message, vm.Rows.Single().Level));
}
[Fact]
public async Task Worker_warn_in_both_footer_history_and_buffer_appears_once()
{
var shell = new IslandsShellViewModel();
var warn = new WorkerLogEntry("disk low", WorkerLogLevel.Warn, DateTime.UtcNow);
shell.OnWorkerLogReceived(warn);
var vm = new LogVisualizerViewModel(new BufferClient(warn), shell.FooterHistorySnapshot);
await vm.RefreshAsync();
Assert.Single(vm.Rows);
}
private sealed class BufferClient(params WorkerLogEntry[] logs) : StubWorkerClient
{
public override Task<IReadOnlyList<WorkerLogEntry>> GetRecentLogsAsync() => Task.FromResult<IReadOnlyList<WorkerLogEntry>>(logs);
}
}