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);
}