fix(ui): report and gate ListSettingsModal load failures instead of swallowing them

BeginLoad's fire-and-forget LoadAsync now catches instead of leaving an
unobserved task exception, reports it via the new ErrorReported event
(wired into FlashFooterError like the other modal VMs), and keeps Save
locked so the failure can't clobber list_config with blank fields.
LoadTicketProjectsAsync's empty catch now reports too; behavior for the
dropdown itself is unchanged.
This commit is contained in:
mika kuns
2026-09-02 22:33:48 +02:00
parent 77c70d74cb
commit a1b20d9f27
5 changed files with 71 additions and 5 deletions
@@ -38,9 +38,12 @@ public class ListSettingsModalViewModelTests
public Func<Task<List<TicketProjectDto>>>? TicketProjectsFactory;
public UpdateListConfigDto? SavedListConfig;
public Exception? GetListConfigThrows;
public override Task<ListConfigDto?> GetListConfigAsync(string listId)
{
GetListConfigCalls++;
if (GetListConfigThrows is not null) throw GetListConfigThrows;
return Task.FromResult(Cfg);
}
@@ -125,4 +128,45 @@ public class ListSettingsModalViewModelTests
Assert.Equal(7, worker.SavedListConfig!.TicketProjectId);
}
[Fact]
public async Task LoadAsync_CoreLoadThrows_BlocksSaveAndDoesNotOverwriteConfig()
{
var worker = new CountingWorker
{
Cfg = new ListConfigDto("opus", null, null),
GetListConfigThrows = new InvalidOperationException("worker offline"),
};
var vm = new ListSettingsModalViewModel(worker, NewFactory());
string? reported = null;
vm.ErrorReported += m => reported = m;
await vm.LoadAsync("l1", "List One", "/repo", "feat");
Assert.False(vm.SaveCommand.CanExecute(null));
Assert.NotNull(reported);
Assert.Contains("worker offline", reported);
Assert.Null(worker.SavedListConfig);
}
[Fact]
public async Task LoadAsync_TicketProjectsThrow_ReportsErrorButRestOfLoadStillWorks()
{
var worker = new CountingWorker
{
Cfg = new ListConfigDto("opus", null, null, null, null, "make test", null, 7, true),
TicketProjectsFactory = () => throw new InvalidOperationException("ticket system down"),
};
var vm = new ListSettingsModalViewModel(worker, NewFactory());
string? reported = null;
vm.ErrorReported += m => reported = m;
await vm.LoadAsync("l1", "List One", "/repo", "feat");
Assert.Equal("make test", vm.VerifyCommand);
Assert.True(vm.PowerUseAllowed);
Assert.True(vm.SaveCommand.CanExecute(null));
Assert.NotNull(reported);
Assert.Contains("ticket system down", reported);
}
}