From fa83d7f4414884ff7e35131ccd99556158d4197f Mon Sep 17 00:00:00 2001 From: mika kuns Date: Thu, 4 Jun 2026 08:05:33 +0200 Subject: [PATCH] feat(daily-prep): add ClearMyDay hub method --- src/ClaudeDo.Worker/Hub/WorkerHub.cs | 15 +++ .../Hub/ClearMyDayHubTests.cs | 105 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 tests/ClaudeDo.Worker.Tests/Hub/ClearMyDayHubTests.cs diff --git a/src/ClaudeDo.Worker/Hub/WorkerHub.cs b/src/ClaudeDo.Worker/Hub/WorkerHub.cs index b19ab98..415ef19 100644 --- a/src/ClaudeDo.Worker/Hub/WorkerHub.cs +++ b/src/ClaudeDo.Worker/Hub/WorkerHub.cs @@ -581,4 +581,19 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub using var ctx = _dbFactory.CreateDbContext(); await new DailyNoteRepository(ctx).DeleteAsync(id); } + + public async Task ClearMyDay() + { + await using var ctx = await _dbFactory.CreateDbContextAsync(); + var ids = await ctx.Tasks.Where(t => t.IsMyDay).Select(t => t.Id).ToListAsync(); + if (ids.Count == 0) return 0; + + await ctx.Tasks.Where(t => t.IsMyDay) + .ExecuteUpdateAsync(s => s.SetProperty(t => t.IsMyDay, false)); + + foreach (var id in ids) + await _broadcaster.TaskUpdated(id); + + return ids.Count; + } } diff --git a/tests/ClaudeDo.Worker.Tests/Hub/ClearMyDayHubTests.cs b/tests/ClaudeDo.Worker.Tests/Hub/ClearMyDayHubTests.cs new file mode 100644 index 0000000..402cce2 --- /dev/null +++ b/tests/ClaudeDo.Worker.Tests/Hub/ClearMyDayHubTests.cs @@ -0,0 +1,105 @@ +using ClaudeDo.Data.Models; +using ClaudeDo.Data.Repositories; +using ClaudeDo.Worker.Hub; +using ClaudeDo.Worker.Tests.Infrastructure; +using Microsoft.EntityFrameworkCore; +using Xunit; +using TaskStatus = ClaudeDo.Data.Models.TaskStatus; + +namespace ClaudeDo.Worker.Tests.Hub; + +public sealed class ClearMyDayHubTests : IDisposable +{ + private readonly DbFixture _db = new(); + + public void Dispose() => _db.Dispose(); + + private WorkerHub CreateHub() + { + var broadcaster = new HubBroadcaster(new CapturingHubContext()); + var hub = new WorkerHub( + null!, null!, null!, null!, broadcaster, _db.CreateFactory(), + null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!); + hub.Clients = new FakeHubCallerClients(new RecordingClientProxy()); + hub.Context = new FakeHubCallerContext(); + return hub; + } + + private async Task<(string listId, string idleMyDay, string doneMyDay, string notMyDay)> SeedAsync() + { + using var ctx = _db.CreateContext(); + var listId = Guid.NewGuid().ToString(); + await new ListRepository(ctx).AddAsync(new ListEntity + { + Id = listId, Name = "L", CreatedAt = DateTime.UtcNow, + }); + + var repo = new TaskRepository(ctx); + + var idleMyDay = Guid.NewGuid().ToString(); + await repo.AddAsync(new TaskEntity + { + Id = idleMyDay, ListId = listId, Title = "Idle MyDay", + Status = TaskStatus.Idle, IsMyDay = true, + CreatedAt = DateTime.UtcNow, CommitType = "feat", + }); + + var doneMyDay = Guid.NewGuid().ToString(); + await repo.AddAsync(new TaskEntity + { + Id = doneMyDay, ListId = listId, Title = "Done MyDay", + Status = TaskStatus.Done, IsMyDay = true, + CreatedAt = DateTime.UtcNow, CommitType = "feat", + }); + + var notMyDay = Guid.NewGuid().ToString(); + await repo.AddAsync(new TaskEntity + { + Id = notMyDay, ListId = listId, Title = "Not MyDay", + Status = TaskStatus.Idle, IsMyDay = false, + CreatedAt = DateTime.UtcNow, CommitType = "feat", + }); + + return (listId, idleMyDay, doneMyDay, notMyDay); + } + + [Fact] + public async Task ClearMyDay_clears_all_isMyDay_tasks() + { + var (_, _, _, notMyDay) = await SeedAsync(); + var hub = CreateHub(); + + var cleared = await hub.ClearMyDay(); + + Assert.Equal(2, cleared); + + await using var ctx = _db.CreateContext(); + Assert.False(await ctx.Tasks.AnyAsync(t => t.IsMyDay)); + + var notMyDayTask = await ctx.Tasks.FindAsync(notMyDay); + Assert.NotNull(notMyDayTask); + Assert.False(notMyDayTask!.IsMyDay); + } + + [Fact] + public async Task ClearMyDay_returns_zero_when_no_myDay_tasks() + { + using var ctx = _db.CreateContext(); + var listId = Guid.NewGuid().ToString(); + await new ListRepository(ctx).AddAsync(new ListEntity + { + Id = listId, Name = "L2", CreatedAt = DateTime.UtcNow, + }); + await new TaskRepository(ctx).AddAsync(new TaskEntity + { + Id = Guid.NewGuid().ToString(), ListId = listId, Title = "No MyDay", + Status = TaskStatus.Idle, IsMyDay = false, + CreatedAt = DateTime.UtcNow, CommitType = "feat", + }); + + var hub = CreateHub(); + var cleared = await hub.ClearMyDay(); + + Assert.Equal(0, cleared); + } +}