using System.Net; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; namespace Elternbeirat.Web.Tests; /// /// Smoke tests: every known route must return 200, unknown routes must return /// 404. This catches broken content files, renamed slugs or routing regressions /// before a deploy. /// /// The post routes now read from PocketBase, so the tests point the web app at the /// seeded container from (shared via the /// collection) and assert against its known slugs. Requires Docker, like the /// client tests. /// /// [Collection(PocketBaseTestGroup.Name)] public sealed class RouteSmokeTests : IDisposable { // WithWebHostBuilder returns a new factory that wraps the base one; both are // disposable, so both are held and disposed to avoid leaking either. private readonly WebApplicationFactory _baseFactory = new(); private readonly WebApplicationFactory _factory; public RouteSmokeTests(PocketBaseFixture pocketBase) { // Point the app's PocketBaseClient at the seeded test container instead of // the value from appsettings. UseSetting (not ConfigureAppConfiguration) // because it wins over appsettings.Development.json, which otherwise pins the // client to localhost:8090 while the test container uses a random port. _factory = _baseFactory.WithWebHostBuilder(builder => builder.UseSetting("PocketBase:BaseUrl", pocketBase.BaseUrl.ToString())); } public void Dispose() { _factory.Dispose(); _baseFactory.Dispose(); } /// /// Every route that a visitor can reach through the navigation, the FAQ hub /// or the news section. The post slugs match the fixture's seed. /// public static TheoryData KnownRoutes => [ "/", "/vorstandsteam", "/foerderverein", "/faq", "/faq-mensa", "/faq-schliessfach", "/faq-elterneuro", "/faq-elternarbeit", "/downloads", "/kontakt", "/impressum", "/datenschutz", "/posts", "/posts/new-board", "/posts/new-hall", "/events", "/events.ics", ]; [Theory] [MemberData(nameof(KnownRoutes))] public async Task Known_route_returns_200(string route) { var client = _factory.CreateClient(); var response = await client.GetAsync(new Uri(route, UriKind.Relative)); response.StatusCode.ShouldBe(HttpStatusCode.OK); } [Theory] [InlineData("/gibt-es-nicht")] [InlineData("/posts/gibt-es-nicht")] public async Task Unknown_route_returns_404(string route) { var client = _factory.CreateClient(); var response = await client.GetAsync(new Uri(route, UriKind.Relative)); response.StatusCode.ShouldBe(HttpStatusCode.NotFound); } }