From 2df18425c45e02d26989001c0fba1b0753980737 Mon Sep 17 00:00:00 2001 From: gamer147 Date: Sun, 31 May 2026 10:37:42 -0400 Subject: [PATCH] feat(repo): IArenaTwoPickRunRepository + tests Co-Authored-By: Claude Sonnet 4.6 --- .../Viewer/ArenaTwoPickRunRepository.cs | 36 ++++++++++ .../Viewer/IArenaTwoPickRunRepository.cs | 10 +++ SVSim.EmulatedEntrypoint/Program.cs | 1 + .../ArenaTwoPickRunRepositoryTests.cs | 72 +++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 SVSim.Database/Repositories/Viewer/ArenaTwoPickRunRepository.cs create mode 100644 SVSim.Database/Repositories/Viewer/IArenaTwoPickRunRepository.cs create mode 100644 SVSim.UnitTests/Repositories/ArenaTwoPickRunRepositoryTests.cs diff --git a/SVSim.Database/Repositories/Viewer/ArenaTwoPickRunRepository.cs b/SVSim.Database/Repositories/Viewer/ArenaTwoPickRunRepository.cs new file mode 100644 index 0000000..bf1f2ca --- /dev/null +++ b/SVSim.Database/Repositories/Viewer/ArenaTwoPickRunRepository.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore; +using SVSim.Database.Models; + +namespace SVSim.Database.Repositories.Viewer; + +public class ArenaTwoPickRunRepository : IArenaTwoPickRunRepository +{ + private readonly SVSimDbContext _db; + public ArenaTwoPickRunRepository(SVSimDbContext db) => _db = db; + + public Task GetByViewerIdAsync(long viewerId) => + _db.ViewerArenaTwoPickRuns.FirstOrDefaultAsync(r => r.ViewerId == viewerId); + + public async Task UpsertAsync(ViewerArenaTwoPickRun run) + { + run.UpdatedAt = DateTime.UtcNow; + if (run.Id == 0) + { + run.CreatedAt = DateTime.UtcNow; + _db.ViewerArenaTwoPickRuns.Add(run); + } + else + { + _db.ViewerArenaTwoPickRuns.Update(run); + } + await _db.SaveChangesAsync(); + } + + public async Task DeleteAsync(long viewerId) + { + var row = await _db.ViewerArenaTwoPickRuns.FirstOrDefaultAsync(r => r.ViewerId == viewerId); + if (row is null) return; + _db.ViewerArenaTwoPickRuns.Remove(row); + await _db.SaveChangesAsync(); + } +} diff --git a/SVSim.Database/Repositories/Viewer/IArenaTwoPickRunRepository.cs b/SVSim.Database/Repositories/Viewer/IArenaTwoPickRunRepository.cs new file mode 100644 index 0000000..0252c9c --- /dev/null +++ b/SVSim.Database/Repositories/Viewer/IArenaTwoPickRunRepository.cs @@ -0,0 +1,10 @@ +using SVSim.Database.Models; + +namespace SVSim.Database.Repositories.Viewer; + +public interface IArenaTwoPickRunRepository +{ + Task GetByViewerIdAsync(long viewerId); + Task UpsertAsync(ViewerArenaTwoPickRun run); + Task DeleteAsync(long viewerId); +} diff --git a/SVSim.EmulatedEntrypoint/Program.cs b/SVSim.EmulatedEntrypoint/Program.cs index e1ecbd6..8019e38 100644 --- a/SVSim.EmulatedEntrypoint/Program.cs +++ b/SVSim.EmulatedEntrypoint/Program.cs @@ -103,6 +103,7 @@ public class Program builder.Services.AddSingleton(TimeProvider.System); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddSingleton(); diff --git a/SVSim.UnitTests/Repositories/ArenaTwoPickRunRepositoryTests.cs b/SVSim.UnitTests/Repositories/ArenaTwoPickRunRepositoryTests.cs new file mode 100644 index 0000000..853b4ce --- /dev/null +++ b/SVSim.UnitTests/Repositories/ArenaTwoPickRunRepositoryTests.cs @@ -0,0 +1,72 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using SVSim.Database; +using SVSim.Database.Models; +using SVSim.Database.Repositories.Viewer; +using SVSim.UnitTests.Infrastructure; + +namespace SVSim.UnitTests.Repositories; + +public class ArenaTwoPickRunRepositoryTests +{ + private static async Task<(SVSimDbContext, ArenaTwoPickRunRepository)> SetupAsync() + { + var factory = new SVSimTestFactory(); + var scope = factory.Services.CreateScope(); + var db = scope.ServiceProvider.GetRequiredService(); + await db.Database.EnsureCreatedAsync(); + return (db, new ArenaTwoPickRunRepository(db)); + } + + [Test] + public async Task GetByViewerId_returns_null_when_no_run() + { + var (db, repo) = await SetupAsync(); + await using var _ = db; + var run = await repo.GetByViewerIdAsync(viewerId: 42); + Assert.That(run, Is.Null); + } + + [Test] + public async Task Insert_then_fetch_round_trips_jsonb_columns() + { + var (db, repo) = await SetupAsync(); + await using var _ = db; + + var run = new ViewerArenaTwoPickRun + { + ViewerId = 42, + EntryId = 0, + RewardScheduleId = 1, + ChallengeId = 1, + MaxBattleCount = 7, + CandidateClassIdsJson = "[1,7,8]", + SelectedCardIdsJson = "[]", + PendingPickSetsJson = "[]", + ResultListJson = "[]", + CreatedAt = DateTime.UtcNow, + UpdatedAt = DateTime.UtcNow, + }; + await repo.UpsertAsync(run); + + var fetched = await repo.GetByViewerIdAsync(42); + Assert.That(fetched, Is.Not.Null); + Assert.That(fetched!.CandidateClassIdsJson, Is.EqualTo("[1,7,8]")); + Assert.That(fetched.MaxBattleCount, Is.EqualTo(7)); + } + + [Test] + public async Task Delete_removes_the_row() + { + var (db, repo) = await SetupAsync(); + await using var _ = db; + await repo.UpsertAsync(new ViewerArenaTwoPickRun + { + ViewerId = 42, EntryId = 0, MaxBattleCount = 7, + CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow, + }); + await repo.DeleteAsync(42); + var fetched = await repo.GetByViewerIdAsync(42); + Assert.That(fetched, Is.Null); + } +}