ScopeGlobs auf Tasks und SerializeOnFileOverlap auf der Listen-Config waren ungenutzt: der Scope wurde nie befuellt, also hat der Queue-Picker nie serialisiert. ScopeOverlap, das Picker-Gate, die DTO-Felder, die UI-Option und die Spalten fallen weg (Migration DropFileScopeSerialization).
69 lines
2.7 KiB
C#
69 lines
2.7 KiB
C#
using ClaudeDo.Data;
|
|
using ClaudeDo.Data.Models;
|
|
using ClaudeDo.Data.Repositories;
|
|
using ClaudeDo.Worker.Hub;
|
|
using ClaudeDo.Worker.Tests.Infrastructure;
|
|
using Xunit;
|
|
|
|
namespace ClaudeDo.Worker.Tests.Hub;
|
|
|
|
/// UpdateListConfig's "all fields blank -> delete the row" branch used to delete unconditionally,
|
|
/// silently dropping fields the caller doesn't own. It may only delete when nothing else is stored;
|
|
/// the preserve-the-stored-value side is covered by ListConfigTicketProjectTests.
|
|
public sealed class ListConfigHubTests : IDisposable
|
|
{
|
|
private readonly DbFixture _db = new();
|
|
|
|
public void Dispose() => _db.Dispose();
|
|
|
|
private WorkerHub CreateHub()
|
|
{
|
|
var factory = _db.CreateFactory();
|
|
var broadcaster = new HubBroadcaster(new CapturingHubContext());
|
|
var hub = new WorkerHub(
|
|
null!, null!, null!, null!, broadcaster, factory,
|
|
null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!,
|
|
null!, new ClaudeDo.Worker.Online.OnlineInboxConfig(), new ClaudeDo.Worker.OnlineRefreshTokenStore(new ClaudeDo.Worker.DpapiTokenStore("unused.token")),
|
|
new ClaudeDo.Worker.Runner.PendingQuestionRegistry(), null!);
|
|
hub.Clients = new FakeHubCallerClients(new RecordingClientProxy());
|
|
hub.Context = new FakeHubCallerContext();
|
|
return hub;
|
|
}
|
|
|
|
// Each helper opens (and disposes) its own short-lived context/repository -- ListRepository's
|
|
// GetConfigAsync doesn't AsNoTracking(), so reusing one long-lived instance across a hub call
|
|
// that writes via a *different* context would return a stale, identity-mapped entity.
|
|
|
|
private async Task<string> SeedListAsync()
|
|
{
|
|
var listId = Guid.NewGuid().ToString();
|
|
await using var ctx = _db.CreateContext();
|
|
await new ListRepository(ctx).AddAsync(new ListEntity { Id = listId, Name = "L", CreatedAt = DateTime.UtcNow });
|
|
return listId;
|
|
}
|
|
|
|
private async Task SeedConfigAsync(string listId, string? model = null)
|
|
{
|
|
await using var ctx = _db.CreateContext();
|
|
await new ListRepository(ctx).SetConfigAsync(new ListConfigEntity { ListId = listId, Model = model });
|
|
}
|
|
|
|
private async Task<ListConfigEntity?> GetConfigAsync(string listId)
|
|
{
|
|
await using var ctx = _db.CreateContext();
|
|
return await new ListRepository(ctx).GetConfigAsync(listId);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateListConfig_AllBlank_NoUnrelatedSettings_DeletesRow()
|
|
{
|
|
var hub = CreateHub();
|
|
var listId = await SeedListAsync();
|
|
await SeedConfigAsync(listId, model: "opus");
|
|
|
|
await hub.UpdateListConfig(new UpdateListConfigDto(listId, null, null, null));
|
|
|
|
Assert.Null(await GetConfigAsync(listId));
|
|
}
|
|
}
|