From 992fbf0763c6ae11337d849769d20a22fcef6705 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Wed, 3 Jun 2026 09:34:03 +0200 Subject: [PATCH] feat(data): add WeekReportRepository with tests --- .../Repositories/WeekReportRepository.cs | 38 ++++++++++++++++ .../Repositories/WeekReportRepositoryTests.cs | 43 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/ClaudeDo.Data/Repositories/WeekReportRepository.cs create mode 100644 tests/ClaudeDo.Worker.Tests/Repositories/WeekReportRepositoryTests.cs diff --git a/src/ClaudeDo.Data/Repositories/WeekReportRepository.cs b/src/ClaudeDo.Data/Repositories/WeekReportRepository.cs new file mode 100644 index 0000000..996b58f --- /dev/null +++ b/src/ClaudeDo.Data/Repositories/WeekReportRepository.cs @@ -0,0 +1,38 @@ +using ClaudeDo.Data.Models; +using Microsoft.EntityFrameworkCore; + +namespace ClaudeDo.Data.Repositories; + +public sealed class WeekReportRepository +{ + private readonly ClaudeDoDbContext _context; + + public WeekReportRepository(ClaudeDoDbContext context) => _context = context; + + public async Task GetByRangeAsync( + DateOnly start, DateOnly end, CancellationToken ct = default) => + await _context.WeekReports.AsNoTracking() + .FirstOrDefaultAsync(r => r.StartDate == start && r.EndDate == end, ct); + + public async Task UpsertAsync(DateOnly start, DateOnly end, string markdown, CancellationToken ct = default) + { + var row = await _context.WeekReports + .FirstOrDefaultAsync(r => r.StartDate == start && r.EndDate == end, ct); + if (row is null) + { + _context.WeekReports.Add(new WeekReportEntity + { + StartDate = start, + EndDate = end, + Markdown = markdown, + GeneratedAt = DateTime.UtcNow, + }); + } + else + { + row.Markdown = markdown; + row.GeneratedAt = DateTime.UtcNow; + } + await _context.SaveChangesAsync(ct); + } +} diff --git a/tests/ClaudeDo.Worker.Tests/Repositories/WeekReportRepositoryTests.cs b/tests/ClaudeDo.Worker.Tests/Repositories/WeekReportRepositoryTests.cs new file mode 100644 index 0000000..96fa967 --- /dev/null +++ b/tests/ClaudeDo.Worker.Tests/Repositories/WeekReportRepositoryTests.cs @@ -0,0 +1,43 @@ +using ClaudeDo.Data.Repositories; +using ClaudeDo.Worker.Tests.Infrastructure; + +namespace ClaudeDo.Worker.Tests.Repositories; + +public class WeekReportRepositoryTests : IDisposable +{ + private readonly DbFixture _db = new(); + public void Dispose() => _db.Dispose(); + + private static readonly DateOnly Start = new(2026, 5, 28); + private static readonly DateOnly End = new(2026, 6, 3); + + [Fact] + public async Task Upsert_Insert_Then_GetByRange_RoundTrips() + { + using (var ctx = _db.CreateContext()) + await new WeekReportRepository(ctx).UpsertAsync(Start, End, "# Report"); + using var read = _db.CreateContext(); + var row = await new WeekReportRepository(read).GetByRangeAsync(Start, End); + Assert.NotNull(row); + Assert.Equal("# Report", row!.Markdown); + } + + [Fact] + public async Task Upsert_Existing_Overwrites_Markdown() + { + using (var ctx = _db.CreateContext()) + await new WeekReportRepository(ctx).UpsertAsync(Start, End, "old"); + using (var ctx = _db.CreateContext()) + await new WeekReportRepository(ctx).UpsertAsync(Start, End, "new"); + using var read = _db.CreateContext(); + var row = await new WeekReportRepository(read).GetByRangeAsync(Start, End); + Assert.Equal("new", row!.Markdown); + } + + [Fact] + public async Task GetByRange_MissingRange_ReturnsNull() + { + using var read = _db.CreateContext(); + Assert.Null(await new WeekReportRepository(read).GetByRangeAsync(Start, End)); + } +}