using System.Net; using FluentAssertions; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Xunit; namespace InboxIntel.IntegrationTests; /// /// Test host that disables startup auto-migration so the factory boots without /// a live PostgreSQL instance. The auth tests below never touch the database /// (the challenge happens in middleware before any controller runs). /// public class TestAppFactory : WebApplicationFactory { protected override IHost CreateHost(IHostBuilder builder) { builder.ConfigureHostConfiguration(cfg => cfg.AddInMemoryCollection(new Dictionary { ["Database:AutoMigrate"] = "false", // Npgsql 10 eagerly validates the connection string when the DbContext is // resolved (8.x was lazy); these tests never connect, but the string must parse. ["ConnectionStrings:Postgres"] = "Host=localhost;Database=test;Username=test;Password=test", // Dummy OAuth creds so the Google challenge produces a real 302 redirect // (an empty ClientId can make the handler throw instead of redirecting). ["GoogleOAuth:ClientId"] = "test-client-id", ["GoogleOAuth:ClientSecret"] = "test-client-secret" })); return base.CreateHost(builder); } } /// /// Smoke tests proving the host boots and authorization is enforced. A fuller /// suite would swap PostgreSQL for a Testcontainers instance and the Gmail /// client for a fake, then exercise sync -> analytics end to end. /// public class AuthEndpointsTests : IClassFixture { private readonly TestAppFactory _factory; public AuthEndpointsTests(TestAppFactory factory) => _factory = factory; [Fact] public async Task Protected_endpoint_challenges_when_anonymous() { var client = _factory.CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); var resp = await client.GetAsync("/api/v1/analytics/dashboard"); // Unauthenticated -> redirect to Google challenge (302) or 401. resp.StatusCode.Should().BeOneOf(HttpStatusCode.Found, HttpStatusCode.Unauthorized); } [Fact] public async Task Login_endpoint_is_anonymous() { var client = _factory.CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); var resp = await client.GetAsync("/api/v1/auth/login"); resp.StatusCode.Should().Be(HttpStatusCode.Redirect); // 302 to Google } }