Consume PocketBase for posts and events, with English routes
This commit is contained in:
1 parent
c59e7a4f83
commit
da87716d97
22 files changed
+278
-225
No files matched your search
@@ -7,7 +7,8 @@ namespace Elternbeirat.Web.Tests;
|
||||
/// with a known seed (see <see cref="PocketBaseFixture"/>). Because the data is fixed,
|
||||
/// the tests assert on exact values, and they need no network to the live instance.
|
||||
/// </summary>
|
||||
public sealed class PocketBaseClientTests(PocketBaseFixture pocketBase) : IClassFixture<PocketBaseFixture>
|
||||
[Collection(PocketBaseTestGroup.Name)]
|
||||
public sealed class PocketBaseClientTests(PocketBaseFixture pocketBase)
|
||||
{
|
||||
[Fact]
|
||||
public async Task Events_load_sorted_by_start()
|
||||
|
||||
@@ -49,6 +49,14 @@ public sealed class PocketBaseFixture : IAsyncLifetime
|
||||
/// <summary>Creates a <see cref="PocketBaseClient"/> pointed at this container.</summary>
|
||||
public PocketBaseClient CreateClient() => new(_http);
|
||||
|
||||
/// <summary>
|
||||
/// The base URL the container's PocketBase is reachable at. Set once the
|
||||
/// container is up; used to point the web app's client at this instance in the
|
||||
/// route smoke tests.
|
||||
/// </summary>
|
||||
public Uri BaseUrl => _http.BaseAddress
|
||||
?? throw new InvalidOperationException("PocketBase is not started yet.");
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
// Clear any leftover from an earlier run that was aborted before DisposeAsync
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Elternbeirat.Web.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Groups every test that needs the seeded PocketBase container into one xUnit
|
||||
/// collection, so the single <see cref="PocketBaseFixture"/> (one container, one
|
||||
/// seed) is shared across those classes instead of started once per class. The
|
||||
/// test project runs one PocketBase for the whole run under the fixed project
|
||||
/// name <c>eb-test-stack</c>; sharing avoids two classes fighting over it.
|
||||
/// </summary>
|
||||
[CollectionDefinition(Name)]
|
||||
public sealed class PocketBaseTestGroup : ICollectionFixture<PocketBaseFixture>
|
||||
{
|
||||
public const string Name = "PocketBase";
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
|
||||
namespace Elternbeirat.Web.Tests;
|
||||
@@ -7,19 +8,40 @@ 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.
|
||||
/// <para>
|
||||
/// The post routes now read from PocketBase, so the tests point the web app at the
|
||||
/// seeded container from <see cref="PocketBaseFixture"/> (shared via the
|
||||
/// collection) and assert against its known slugs. Requires Docker, like the
|
||||
/// client tests.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public sealed class RouteSmokeTests : IClassFixture<WebApplicationFactory<Program>>
|
||||
[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<Program> _baseFactory = new();
|
||||
private readonly WebApplicationFactory<Program> _factory;
|
||||
|
||||
public RouteSmokeTests(WebApplicationFactory<Program> factory)
|
||||
public RouteSmokeTests(PocketBaseFixture pocketBase)
|
||||
{
|
||||
_factory = factory;
|
||||
// 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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Every route that a visitor can reach through the navigation, the FAQ hub
|
||||
/// or the news section.
|
||||
/// or the news section. The post slugs match the fixture's seed.
|
||||
/// </summary>
|
||||
public static TheoryData<string> KnownRoutes =>
|
||||
[
|
||||
@@ -35,11 +57,11 @@ public sealed class RouteSmokeTests : IClassFixture<WebApplicationFactory<Progra
|
||||
"/kontakt",
|
||||
"/impressum",
|
||||
"/datenschutz",
|
||||
"/beitraege",
|
||||
"/beitraege/neuer-vorstand-gewaehlt",
|
||||
"/beitraege/neue-sporthalle-eroeffnet",
|
||||
"/termine",
|
||||
"/termine.ics",
|
||||
"/posts",
|
||||
"/posts/new-board",
|
||||
"/posts/new-hall",
|
||||
"/events",
|
||||
"/events.ics",
|
||||
];
|
||||
|
||||
[Theory]
|
||||
@@ -55,7 +77,7 @@ public sealed class RouteSmokeTests : IClassFixture<WebApplicationFactory<Progra
|
||||
|
||||
[Theory]
|
||||
[InlineData("/gibt-es-nicht")]
|
||||
[InlineData("/beitraege/gibt-es-nicht")]
|
||||
[InlineData("/posts/gibt-es-nicht")]
|
||||
public async Task Unknown_route_returns_404(string route)
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
Reference in new issue
Block a user