using ClaudeDo.Data; using ClaudeDo.Ui.Services; using ClaudeDo.Ui.Services.Interfaces; using ClaudeDo.Ui.ViewModels; using ClaudeDo.Ui.ViewModels.Conflicts; using ClaudeDo.Ui.ViewModels.Modals; using Microsoft.EntityFrameworkCore; namespace ClaudeDo.Ui.Tests; /// /// The test doubles every ViewModel test needs. They used to be redeclared as a private nested /// class in each test file (TestDbFactory alone in 40 of them) — put new shared no-op doubles here /// rather than copying one again. Test-specific behaviour still belongs in the test file. /// public sealed class TestDbFactory(Func create) : IDbContextFactory { public ClaudeDoDbContext CreateDbContext() => create(); } public sealed class NullServiceProvider : IServiceProvider { public object? GetService(Type serviceType) => null; } public sealed class StubNotesApi : INotesApi { public Task> ListAsync(DateOnly day) => Task.FromResult(new List()); public Task> ListBetweenAsync(DateOnly start, DateOnly end) => Task.FromResult(new List()); public Task AddAsync(DateOnly day, string text) => Task.FromResult(null); public Task UpdateAsync(string id, string text) => Task.CompletedTask; public Task DeleteAsync(string id) => Task.CompletedTask; } /// is abstract — this is the concrete no-op subclass. public sealed class DefaultStub : StubWorkerClient { } /// /// Records the message/label of the last Confirm/Error call and returns a configurable /// Confirm result. Covers the ViewModels (DetailsIsland, TasksIsland, ...) that take their /// dialog seam via a settable Dialogs property instead of a per-call constructor arg. /// public sealed class RecordingDialogService : IDialogService { public bool ConfirmResult { get; set; } = true; public string? LastConfirmMessage { get; private set; } public string? LastConfirmLabel { get; private set; } public string? LastErrorMessage { get; private set; } public Task ConfirmAsync(string message, string? confirmLabel = null) { LastConfirmMessage = message; LastConfirmLabel = confirmLabel; return Task.FromResult(ConfirmResult); } public Task ShowErrorAsync(string message) { LastErrorMessage = message; return Task.CompletedTask; } public Task ShowAboutAsync(AboutModalViewModel vm) => throw new NotImplementedException(); public Task ShowWeeklyReportAsync(WeeklyReportModalViewModel vm) => throw new NotImplementedException(); public Task ShowUsageMonitorAsync(UsageMonitorModalViewModel vm) => throw new NotImplementedException(); public Task ShowSettingsAsync(SettingsModalViewModel vm) => throw new NotImplementedException(); public Task ShowListSettingsAsync(ListSettingsModalViewModel vm) => throw new NotImplementedException(); public Task ShowRepoImportAsync(RepoImportModalViewModel vm) => throw new NotImplementedException(); public Task ShowWorktreesOverviewAsync(WorktreesOverviewModalViewModel vm) => throw new NotImplementedException(); public Task?> ShowMergeHelperSelectionAsync(MergeHelperSelectionModalViewModel vm) => throw new NotImplementedException(); public Task ShowWorkerConnectionAsync(WorkerConnectionModalViewModel vm) => throw new NotImplementedException(); public Task ShowConflictResolverAsync(ConflictResolverViewModel vm) => throw new NotImplementedException(); public Task ShowLogVisualizerAsync(LogVisualizerViewModel vm) => throw new NotImplementedException(); public void ShowMissionControl(MissionControlViewModel vm) => throw new NotImplementedException(); public void ShowCheatSheets(CheatSheetsViewModel vm) => throw new NotImplementedException(); }