test: dedupe the nested test doubles into one shared file

TestDbFactory was redeclared as a private nested class in 40 test files,
NullServiceProvider and StubNotesApi in 14 each, DefaultStub in 5 — 73
declarations, all semantically identical (StubNotesApi differed only in
formatting and type qualification). They now live in TestDoubles.cs next to the
existing StubWorkerClient, which was already the shared-double pattern in this
project.
This commit is contained in:
mika kuns
2026-08-26 10:11:58 +02:00
parent 81994aadca
commit 76d836a278
43 changed files with 36 additions and 428 deletions
@@ -149,10 +149,4 @@ public class ShellOpenTests
Assert.Null(reportedError); Assert.Null(reportedError);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
} }
+32
View File
@@ -0,0 +1,32 @@
using ClaudeDo.Data;
using ClaudeDo.Ui.Services;
using ClaudeDo.Ui.Services.Interfaces;
using Microsoft.EntityFrameworkCore;
namespace ClaudeDo.Ui.Tests;
/// <summary>
/// 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.
/// </summary>
public sealed class TestDbFactory(Func<ClaudeDoDbContext> create) : IDbContextFactory<ClaudeDoDbContext>
{
public ClaudeDoDbContext CreateDbContext() => create();
}
public sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
public sealed class StubNotesApi : INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) => Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) => Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
/// <summary><see cref="StubWorkerClient"/> is abstract — this is the concrete no-op subclass.</summary>
public sealed class DefaultStub : StubWorkerClient { }
@@ -35,27 +35,8 @@ public class DetailsIslandConflictSeamTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<ClaudeDo.Ui.Services.DailyNoteDto>> ListAsync(DateOnly day) =>
Task.FromResult(new List<ClaudeDo.Ui.Services.DailyNoteDto>());
public Task<ClaudeDo.Ui.Services.DailyNoteDto?> AddAsync(DateOnly day, string text) =>
Task.FromResult<ClaudeDo.Ui.Services.DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class ConflictApproveWorkerClient : StubWorkerClient private sealed class ConflictApproveWorkerClient : StubWorkerClient
{ {
@@ -64,7 +45,7 @@ public class DetailsIslandConflictSeamTests : IDisposable
Task.FromResult<MergeResultDto?>(new MergeResultDto("conflict", new[] { "a.cs" }, null)); Task.FromResult<MergeResultDto?>(new MergeResultDto("conflict", new[] { "a.cs" }, null));
} }
private DetailsIslandViewModel BuildVm(StubWorkerClient worker, IMergeCoordinator merge) private DetailsIslandViewModel BuildVm(StubWorkerClient worker, MergeCoordinator merge)
{ {
var factory = new TestDbFactory(NewContext); var factory = new TestDbFactory(NewContext);
return new DetailsIslandViewModel(factory, worker, new NullServiceProvider(), new StubNotesApi(), merge); return new DetailsIslandViewModel(factory, worker, new NullServiceProvider(), new StubNotesApi(), merge);
@@ -33,27 +33,8 @@ public class DetailsIslandDeleteTaskTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) =>
Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) =>
Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class RecordingWorkerClient : StubWorkerClient private sealed class RecordingWorkerClient : StubWorkerClient
{ {
@@ -36,27 +36,8 @@ public class DetailsIslandDescriptionSaveRaceTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) =>
Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) =>
Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class FakeWorker : StubWorkerClient private sealed class FakeWorker : StubWorkerClient
{ {
@@ -31,27 +31,9 @@ public class DetailsIslandEmptyStateTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class DefaultStub : StubWorkerClient { }
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) => Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) => Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private DetailsIslandViewModel NewDetailsVm(StubWorkerClient stub) private DetailsIslandViewModel NewDetailsVm(StubWorkerClient stub)
{ {
@@ -45,27 +45,8 @@ public class DetailsIslandErrorFeedbackTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) =>
Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) =>
Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class ThrowingWorkerClient : StubWorkerClient private sealed class ThrowingWorkerClient : StubWorkerClient
{ {
@@ -36,27 +36,8 @@ public class DetailsIslandHandlerRangeTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) =>
Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) =>
Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class FakeWorkerClient : StubWorkerClient private sealed class FakeWorkerClient : StubWorkerClient
{ {
@@ -34,12 +34,6 @@ public class DetailsIslandPlanningTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class FakeWorkerClient : StubWorkerClient private sealed class FakeWorkerClient : StubWorkerClient
{ {
@@ -48,20 +42,7 @@ public class DetailsIslandPlanningTests : IDisposable
public override Task<MergeTargetsDto?> GetMergeTargetsAsync(string taskId) => Task.FromResult(MergeTargetsResult); public override Task<MergeTargetsDto?> GetMergeTargetsAsync(string taskId) => Task.FromResult(MergeTargetsResult);
} }
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<ClaudeDo.Ui.Services.DailyNoteDto>> ListAsync(DateOnly day) =>
Task.FromResult(new List<ClaudeDo.Ui.Services.DailyNoteDto>());
public Task<ClaudeDo.Ui.Services.DailyNoteDto?> AddAsync(DateOnly day, string text) =>
Task.FromResult<ClaudeDo.Ui.Services.DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private DetailsIslandViewModel BuildVm(StubWorkerClient worker) private DetailsIslandViewModel BuildVm(StubWorkerClient worker)
{ {
@@ -31,22 +31,8 @@ public class DetailsIslandPrepModeTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class DefaultStub : StubWorkerClient { }
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) => Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) => Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private DetailsIslandViewModel NewDetailsVm(StubWorkerClient stub) private DetailsIslandViewModel NewDetailsVm(StubWorkerClient stub)
{ {
@@ -54,10 +40,6 @@ public class DetailsIslandPrepModeTests : IDisposable
return new DetailsIslandViewModel(factory, stub, new NullServiceProvider(), new StubNotesApi(), new ClaudeDo.Ui.Services.MergeCoordinator()); return new DetailsIslandViewModel(factory, stub, new NullServiceProvider(), new StubNotesApi(), new ClaudeDo.Ui.Services.MergeCoordinator());
} }
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
[Fact] [Fact]
public void PrepLine_event_appends_to_PrepLog() public void PrepLine_event_appends_to_PrepLog()
@@ -36,27 +36,8 @@ public class DetailsIslandResetAndRetryTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) =>
Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) =>
Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class RecordingWorkerClient : StubWorkerClient private sealed class RecordingWorkerClient : StubWorkerClient
{ {
@@ -33,27 +33,8 @@ public class DetailsIslandReviewActionsTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) =>
Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) =>
Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class RecordingWorkerClient : StubWorkerClient private sealed class RecordingWorkerClient : StubWorkerClient
{ {
@@ -43,27 +43,8 @@ public class DetailsIslandRoadblockReplyTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) =>
Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) =>
Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class RecordingWorkerClient : StubWorkerClient private sealed class RecordingWorkerClient : StubWorkerClient
{ {
@@ -31,28 +31,9 @@ public class DetailsIslandTabsTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) => Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) => Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
// StubWorkerClient is abstract — use a concrete no-op subclass (same pattern as DetailsIslandPrepModeTests).
private sealed class DefaultStub : StubWorkerClient { }
private DetailsIslandViewModel NewVm() private DetailsIslandViewModel NewVm()
{ {
@@ -33,27 +33,9 @@ public class DetailsIslandTaskIdBadgeTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) => Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) => Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class DefaultStub : StubWorkerClient { }
private DetailsIslandViewModel NewVm() private DetailsIslandViewModel NewVm()
{ {
@@ -35,27 +35,8 @@ public class DetailsIslandTaskUpdatedTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class NullServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType) => null;
}
private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi
{
public Task<List<DailyNoteDto>> ListAsync(DateOnly day) =>
Task.FromResult(new List<DailyNoteDto>());
public Task<DailyNoteDto?> AddAsync(DateOnly day, string text) =>
Task.FromResult<DailyNoteDto?>(null);
public Task UpdateAsync(string id, string text) => Task.CompletedTask;
public Task DeleteAsync(string id) => Task.CompletedTask;
}
private sealed class FakeWorker : StubWorkerClient private sealed class FakeWorker : StubWorkerClient
{ {
@@ -40,12 +40,6 @@ public class ListsIslandErrorFeedbackTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
[Fact] [Fact]
public void OpenFindings_WhenClaudedoFolderMissing_RaisesErrorReported() public void OpenFindings_WhenClaudedoFolderMissing_RaisesErrorReported()
@@ -43,12 +43,6 @@ public class ListsIslandHasNoLinkedRepoTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class FakeWorker : StubWorkerClient private sealed class FakeWorker : StubWorkerClient
{ {
@@ -43,12 +43,6 @@ public class ListsIslandListUpdatedTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class FakeWorker : StubWorkerClient private sealed class FakeWorker : StubWorkerClient
{ {
@@ -34,12 +34,6 @@ public class MergeHelperSelectionModalViewModelTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private MergeHelperSelectionModalViewModel BuildVm() private MergeHelperSelectionModalViewModel BuildVm()
=> new(new TestDbFactory(NewContext)); => new(new TestDbFactory(NewContext));
@@ -36,12 +36,6 @@ public class MissionControlViewModelTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class FakeWorker : StubWorkerClient { } private sealed class FakeWorker : StubWorkerClient { }
@@ -30,12 +30,6 @@ public sealed class RepoImportModalViewModelTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class FakeWorkerClient : StubWorkerClient private sealed class FakeWorkerClient : StubWorkerClient
{ {
@@ -36,12 +36,6 @@ public class SettingsModalViewModelTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class FakeWorker : StubWorkerClient private sealed class FakeWorker : StubWorkerClient
{ {
@@ -31,12 +31,6 @@ public class TaskMonitorViewModelTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class FakeWorker : StubWorkerClient { } private sealed class FakeWorker : StubWorkerClient { }
@@ -31,12 +31,6 @@ public class TasksIslandAddAndSelectTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private async Task SeedListAsync() private async Task SeedListAsync()
{ {
@@ -33,12 +33,6 @@ public class TasksIslandApproveReviewTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class ThrowingWorkerClient : StubWorkerClient private sealed class ThrowingWorkerClient : StubWorkerClient
{ {
@@ -34,12 +34,6 @@ public class TasksIslandChainTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private TasksIslandViewModel BuildViewModel() private TasksIslandViewModel BuildViewModel()
{ {
@@ -36,12 +36,6 @@ public class TasksIslandClassifyItemsTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private TasksIslandViewModel BuildViewModel() private TasksIslandViewModel BuildViewModel()
{ {
@@ -30,14 +30,7 @@ public class TasksIslandDailyPrepTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class DefaultStub : StubWorkerClient { }
private TasksIslandViewModel NewTasksVm(StubWorkerClient stub) => private TasksIslandViewModel NewTasksVm(StubWorkerClient stub) =>
new(new TestDbFactory(NewContext), worker: stub); new(new TestDbFactory(NewContext), worker: stub);
@@ -32,12 +32,6 @@ public class TasksIslandEmptyStateTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private async Task SeedListAsync(string listId, string title = "seed task") private async Task SeedListAsync(string listId, string title = "seed task")
{ {
@@ -44,12 +44,6 @@ public class TasksIslandErrorFeedbackTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class ThrowingWorkerClient : StubWorkerClient private sealed class ThrowingWorkerClient : StubWorkerClient
{ {
@@ -36,12 +36,6 @@ public class TasksIslandFullReloadSelectionTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class FakeWorker : StubWorkerClient private sealed class FakeWorker : StubWorkerClient
{ {
@@ -34,12 +34,6 @@ public class TasksIslandListSwitchSelectionTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private async Task SeedTwoListsAsync() private async Task SeedTwoListsAsync()
{ {
@@ -36,12 +36,6 @@ public class TasksIslandMoveToListTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class FakeDialogService : IDialogService private sealed class FakeDialogService : IDialogService
{ {
@@ -30,12 +30,6 @@ public class TasksIslandOpenConPtySessionTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
[Fact] [Fact]
public void OpenConPtySessionCommand_RaisesOpenConPtySessionRequested_WithTaskId() public void OpenConPtySessionCommand_RaisesOpenConPtySessionRequested_WithTaskId()
@@ -30,12 +30,6 @@ public class TasksIslandOpenQuickClaudeSessionTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private TasksIslandViewModel BuildViewModel() => new(new TestDbFactory(NewContext), worker: null); private TasksIslandViewModel BuildViewModel() => new(new TestDbFactory(NewContext), worker: null);
@@ -35,12 +35,6 @@ public class TasksIslandPlanningOperationTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class GatedWorkerClient : StubWorkerClient private sealed class GatedWorkerClient : StubWorkerClient
{ {
@@ -36,12 +36,6 @@ public class TasksIslandQueuePlanInteractiveGateTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private sealed class RecordingWorkerClient : StubWorkerClient private sealed class RecordingWorkerClient : StubWorkerClient
{ {
@@ -33,12 +33,6 @@ public class TasksIslandRegroupTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private TasksIslandViewModel BuildViewModel() private TasksIslandViewModel BuildViewModel()
{ {
@@ -33,12 +33,6 @@ public class TasksIslandRemoveFromQueueTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
// RemoveFromQueueAsync now routes the dequeue through IWorkerClient.DequeueTaskAsync (the // RemoveFromQueueAsync now routes the dequeue through IWorkerClient.DequeueTaskAsync (the
// guarded TaskStateService transition) instead of writing the DB directly. This fake performs // guarded TaskStateService transition) instead of writing the DB directly. This fake performs
@@ -32,12 +32,6 @@ public class TasksIslandSelectByIdTests : IDisposable
return new ClaudeDoDbContext(opts); return new ClaudeDoDbContext(opts);
} }
private sealed class TestDbFactory : IDbContextFactory<ClaudeDoDbContext>
{
private readonly Func<ClaudeDoDbContext> _create;
public TestDbFactory(Func<ClaudeDoDbContext> create) => _create = create;
public ClaudeDoDbContext CreateDbContext() => _create();
}
private async Task SeedAsync() private async Task SeedAsync()
{ {
@@ -30,7 +30,7 @@ public class WorktreesOverviewBatchMergeTests
Assert.False(row.IsConflict); Assert.False(row.IsConflict);
} }
private static WorktreesOverviewModalViewModel NewVm(IMergeCoordinator? merge = null) => private static WorktreesOverviewModalViewModel NewVm(MergeCoordinator? merge = null) =>
new(new ClaudeDo.Ui.Services.WorkerClient("http://127.0.0.1:1/hub"), () => null!, new(new ClaudeDo.Ui.Services.WorkerClient("http://127.0.0.1:1/hub"), () => null!,
merge ?? new ClaudeDo.Ui.Services.MergeCoordinator()); merge ?? new ClaudeDo.Ui.Services.MergeCoordinator());
@@ -21,11 +21,6 @@ public class WorktreesOverviewReconcileTickTests
=> Task.FromResult<MergeTargetsDto?>(new MergeTargetsDto("main", new[] { "main" }, "chore(list): merge t")); => Task.FromResult<MergeTargetsDto?>(new MergeTargetsDto("main", new[] { "main" }, "chore(list): merge t"));
} }
private sealed class NoopMergeCoordinator : IMergeCoordinator
{
public Task ResolveConflictAsync(string taskId, string targetBranch) => Task.CompletedTask;
}
private static WorktreeOverviewDto Wt(string taskId, WorktreeState state = WorktreeState.Active) => private static WorktreeOverviewDto Wt(string taskId, WorktreeState state = WorktreeState.Active) =>
new(taskId, $"Task {taskId}", TaskStatus.WaitingForReview, "L1", "Work", new(taskId, $"Task {taskId}", TaskStatus.WaitingForReview, "L1", "Work",
$@"C:\wt\{taskId}", $"claudedo/{taskId}", "base0", state, "+1 -0", $@"C:\wt\{taskId}", $"claudedo/{taskId}", "base0", state, "+1 -0",
@@ -35,7 +30,8 @@ public class WorktreesOverviewReconcileTickTests
{ {
var worker = new FakeWorker { Worktrees = { Wt("a"), Wt("b"), Wt("c") } }; var worker = new FakeWorker { Worktrees = { Wt("a"), Wt("b"), Wt("c") } };
var vm = new WorktreesOverviewModalViewModel( var vm = new WorktreesOverviewModalViewModel(
worker, () => throw new InvalidOperationException("no diff vm in this test"), new NoopMergeCoordinator()); worker, () => throw new InvalidOperationException("no diff vm in this test"),
new ClaudeDo.Ui.Services.MergeCoordinator());
vm.Configure("L1", "Work"); vm.Configure("L1", "Work");
await vm.LoadAsync(); await vm.LoadAsync();
return (vm, worker); return (vm, worker);