97 lines
3.0 KiB
C#
97 lines
3.0 KiB
C#
using ClaudeDo.Ui.ViewModels.Islands;
|
|
|
|
namespace ClaudeDo.Ui.Tests.ViewModels;
|
|
|
|
public class PrepPanelViewModelTests
|
|
{
|
|
private sealed class Worker : StubWorkerClient
|
|
{
|
|
public TaskCompletionSource<bool> Gate { get; } = new();
|
|
public bool Throw { get; set; }
|
|
|
|
public override Task<bool> RunDailyPrepNowAsync() =>
|
|
Throw ? Task.FromException<bool>(new InvalidOperationException("boom")) : Gate.Task;
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PlanDay_sets_PrepOperation_IsRunning_before_the_started_broadcast_arrives()
|
|
{
|
|
var worker = new Worker();
|
|
var vm = new PrepPanelViewModel(worker);
|
|
|
|
var plan = vm.PlanDayCommand.ExecuteAsync(null);
|
|
|
|
Assert.True(vm.PrepOperation.IsRunning);
|
|
Assert.False(vm.IsPrepRunning); // the broadcast hasn't fired yet
|
|
|
|
worker.Gate.SetResult(true);
|
|
await plan;
|
|
|
|
Assert.False(vm.PrepOperation.IsRunning);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PlanDayCommand_CanExecute_is_locked_while_running()
|
|
{
|
|
var worker = new Worker();
|
|
var vm = new PrepPanelViewModel(worker);
|
|
|
|
var plan = vm.PlanDayCommand.ExecuteAsync(null);
|
|
Assert.False(vm.PlanDayCommand.CanExecute(null));
|
|
Assert.False(vm.IsPlanDayEnabled);
|
|
|
|
worker.Gate.SetResult(true);
|
|
await plan;
|
|
|
|
Assert.True(vm.PlanDayCommand.CanExecute(null));
|
|
Assert.True(vm.IsPlanDayEnabled);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PlanDay_ends_the_operation_when_the_worker_call_throws()
|
|
{
|
|
var worker = new Worker { Throw = true };
|
|
var vm = new PrepPanelViewModel(worker);
|
|
|
|
await vm.PlanDayCommand.ExecuteAsync(null);
|
|
|
|
Assert.False(vm.PrepOperation.IsRunning);
|
|
Assert.True(vm.PlanDayCommand.CanExecute(null));
|
|
}
|
|
|
|
private sealed class TicketWorker : StubWorkerClient
|
|
{
|
|
public TicketSettingsDto? Settings { get; set; }
|
|
public override Task<TicketSettingsDto?> GetTicketSettingsAsync() => Task.FromResult(Settings);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("http://api", true, true)]
|
|
[InlineData("http://api", false, false)]
|
|
[InlineData(null, true, false)]
|
|
public async Task TicketsConfigured_needs_base_url_and_token(string? url, bool tokenSet, bool expected)
|
|
{
|
|
var worker = new TicketWorker { Settings = new TicketSettingsDto(url, tokenSet) };
|
|
var vm = new PrepPanelViewModel(worker);
|
|
|
|
await vm.RefreshTicketsConfiguredAsync();
|
|
|
|
Assert.Equal(expected, vm.TicketsConfigured);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ImportTicketsAndPlanDay_calls_the_worker_and_shares_the_plan_day_lock()
|
|
{
|
|
var worker = new Worker();
|
|
var vm = new PrepPanelViewModel(worker);
|
|
|
|
var plan = vm.PlanDayCommand.ExecuteAsync(null);
|
|
Assert.False(vm.ImportTicketsAndPlanDayCommand.CanExecute(null));
|
|
worker.Gate.SetResult(true);
|
|
await plan;
|
|
|
|
await vm.ImportTicketsAndPlanDayCommand.ExecuteAsync(null);
|
|
Assert.Equal(1, worker.RunTicketImportNowCalls);
|
|
}
|
|
}
|