using JobTrackerApi.Data; using JobTrackerApi.Models; using JobTrackerApi.Services; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Moq; using Xunit; namespace JobTrackerApi.Tests; public sealed class EmailDraftPersistenceTests { [Fact] public async Task Drafts_are_owner_filtered_and_follow_the_owned_job_lifecycle() { await using var connection = new SqliteConnection("Data Source=:memory:"); await connection.OpenAsync(); var options = new DbContextOptionsBuilder().UseSqlite(connection).Options; int userOneJobId; int userTwoJobId; await using (var seed = Context(options, null)) { await seed.Database.EnsureCreatedAsync(); var companyOne = new Company { Name = "One", OwnerUserId = "user-1" }; var companyTwo = new Company { Name = "Two", OwnerUserId = "user-2" }; seed.Companies.AddRange(companyOne, companyTwo); await seed.SaveChangesAsync(); var jobOne = new JobApplication { JobTitle = "Role one", CompanyId = companyOne.Id, OwnerUserId = "user-1" }; var jobTwo = new JobApplication { JobTitle = "Role two", CompanyId = companyTwo.Id, OwnerUserId = "user-2" }; seed.JobApplications.AddRange(jobOne, jobTwo); await seed.SaveChangesAsync(); userOneJobId = jobOne.Id; userTwoJobId = jobTwo.Id; seed.EmailDrafts.AddRange( Draft("user-1", jobOne.Id, "one@example.test"), Draft("user-2", jobTwo.Id, "two@example.test")); await seed.SaveChangesAsync(); } await using (var userOne = Context(options, "user-1")) { var visible = Assert.Single(await userOne.EmailDrafts.AsNoTracking().ToListAsync()); Assert.Equal(userOneJobId, visible.JobApplicationId); Assert.Equal("one@example.test", visible.To); var job = await userOne.JobApplications.SingleAsync(item => item.Id == userOneJobId); userOne.JobApplications.Remove(job); await userOne.SaveChangesAsync(); } await using var verify = Context(options, null); var remaining = Assert.Single(await verify.EmailDrafts.IgnoreQueryFilters().AsNoTracking().ToListAsync()); Assert.Equal("user-2", remaining.OwnerUserId); Assert.Equal(userTwoJobId, remaining.JobApplicationId); } private static EmailDraft Draft(string ownerUserId, int jobApplicationId, string recipient) => new() { Id = Guid.NewGuid(), OwnerUserId = ownerUserId, JobApplicationId = jobApplicationId, Provider = "gmail", To = recipient, Subject = "Synthetic draft", BodyText = "Synthetic private draft body.", ThreadId = "thread-1", ClientRequestId = Guid.NewGuid().ToString("D"), CreatedAtUtc = DateTime.UtcNow, UpdatedAtUtc = DateTime.UtcNow, }; private static JobTrackerContext Context(DbContextOptions options, string? userId) { var currentUser = new Mock(); currentUser.SetupGet(service => service.UserId).Returns(userId); return new JobTrackerContext(options, currentUser.Object); } }