using System.Net.Http.Json; using System.Text.Json; using System.Text.Json.Serialization; using FamilyNido.Persistence; using Microsoft.Extensions.DependencyInjection; namespace FamilyNido.Tests.Integration; /// /// Common base for integration tests. Resets the DB before each test, exposes /// helpers for getting an and an HTTP client, /// and is opted into automatically so /// concrete tests only need to inherit. /// [Collection(IntegrationCollection.Name)] public abstract class IntegrationTestBase : IAsyncLifetime { /// Shared fixture — Postgres + WebApplicationFactory. protected IntegrationFixture Fixture { get; } /// Test-scoped HTTP client. Cookies persist within the same test. protected HttpClient Client { get; private set; } = null!; /// Constructor — xUnit injects the fixture via the collection. protected IntegrationTestBase(IntegrationFixture fixture) { Fixture = fixture; } /// public async Task InitializeAsync() { await Fixture.ResetAsync(); Client = Fixture.Factory.CreateClient(new Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactoryClientOptions { // Cookies are essential — local-login signs the session into one. HandleCookies = true, AllowAutoRedirect = false, }); } /// public Task DisposeAsync() { Client?.Dispose(); return Task.CompletedTask; } /// /// Run the supplied delegate inside a fresh DI scope with an /// available — used by tests to seed /// data or assert persisted state. /// protected async Task WithDbAsync(Func> action) { await using var scope = Fixture.Factory.Services.CreateAsyncScope(); var db = scope.ServiceProvider.GetRequiredService(); return await action(db); } /// Void overload of for seeding helpers. protected async Task WithDbAsync(Func action) { await using var scope = Fixture.Factory.Services.CreateAsyncScope(); var db = scope.ServiceProvider.GetRequiredService(); await action(db); } /// /// JSON options that mirror the API: enums serialised as strings (the /// API registers globally on /// HttpJsonOptions). Tests use this when reading bodies. /// protected static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web) { Converters = { new JsonStringEnumConverter() }, }; /// Read the response as using the API's JSON conventions. protected static Task ReadAsync(HttpResponseMessage response) => response.Content.ReadFromJsonAsync(JsonOptions); }