From 3fd40687627e538a219ee5e0ef1edfa0dbdb2cf0 Mon Sep 17 00:00:00 2001 From: tleininger Date: Wed, 23 Sep 2026 22:32:01 +0200 Subject: [PATCH] Serve the home nav link from PocketBase, not a hard-coded copy --- Elternbeirat.Web.Tests/NavBuilderTests.cs | 10 ---------- .../PocketBaseClientTests.cs | 6 +++--- Elternbeirat.Web.Tests/PocketBaseFixture.cs | 19 +++++++++++-------- .../Components/Layout/MainLayout.razor | 8 ++++---- .../Components/Layout/MainLayout.razor.css | 13 +++---------- .../Features/Layout/NavBuilder.cs | 6 +++--- pb/pb_migrations/1727200000_dev_seed.js | 2 +- pb/pb_migrations/collections_schema.json | 2 +- 8 files changed, 26 insertions(+), 40 deletions(-) diff --git a/Elternbeirat.Web.Tests/NavBuilderTests.cs b/Elternbeirat.Web.Tests/NavBuilderTests.cs index dcaf642..c8cdedc 100644 --- a/Elternbeirat.Web.Tests/NavBuilderTests.cs +++ b/Elternbeirat.Web.Tests/NavBuilderTests.cs @@ -19,7 +19,6 @@ public class NavBuilderTests Page("board", "header", 2, "Vorstandsteam"), Page("home", "header", 1, "Start"), Page("imprint", "footer", 1, "Impressum"), - Page("hidden", "", 1, "Unterseite"), }; var header = NavBuilder.Header(pages); @@ -56,13 +55,4 @@ public class NavBuilderTests header[0].Href.ShouldBe("/"); header[1].Href.ShouldBe("/board"); } - - [Fact] - public void Pages_without_a_location_never_appear_in_a_menu() - { - var pages = new[] { Page("hidden", "", 1, "Unterseite") }; - - NavBuilder.Header(pages).ShouldBeEmpty(); - NavBuilder.Footer(pages).ShouldBeEmpty(); - } } diff --git a/Elternbeirat.Web.Tests/PocketBaseClientTests.cs b/Elternbeirat.Web.Tests/PocketBaseClientTests.cs index a7b999b..bdd1828 100644 --- a/Elternbeirat.Web.Tests/PocketBaseClientTests.cs +++ b/Elternbeirat.Web.Tests/PocketBaseClientTests.cs @@ -85,9 +85,9 @@ public sealed class PocketBaseClientTests(PocketBaseFixture pocketBase) var home = pages.Single(p => p.Slug == "home"); home.Embed.ShouldBe(["posts", "events"], ignoreOrder: true); - // Home has no menu slot: the brand is the home link, so a "Start" nav - // entry would be redundant. NavBuilder filters it out via this empty value. - home.Location.ShouldBe(""); + // Home sits in the header like every other page (location is required); it + // is the single source of the home nav link. + home.Location.ShouldBe("header"); } [Fact] diff --git a/Elternbeirat.Web.Tests/PocketBaseFixture.cs b/Elternbeirat.Web.Tests/PocketBaseFixture.cs index 2972f4a..c8a75ee 100644 --- a/Elternbeirat.Web.Tests/PocketBaseFixture.cs +++ b/Elternbeirat.Web.Tests/PocketBaseFixture.cs @@ -220,14 +220,14 @@ public sealed class PocketBaseFixture : IAsyncLifetime private static async Task SeedRecordsAsync(HttpClient http) { // Pages that the route smoke tests reach through the navigation, the - // footer or the FAQ hub. Header pages carry a location+order; the FAQ - // sub-pages are plain content pages without a menu slot. All public. - // The home page has no menu slot (location ""): the site brand is the home - // link, so a separate "Start" nav entry would be redundant. + // footer or the FAQ hub. Every page carries a location ("header" or + // "footer") -- the field is required, matching production. All public. + // The home page sits in the header at order 1, like production; the brand + // links home too, but the nav entry is the single source of the home link. await CreateRecordAsync(http, "pages", new { - title = "Startseite", body = "# Willkommen", location = "", - order = 0, slug = "home", embed = new[] { "posts", "events" }, @public = true, + title = "Start", body = "# Willkommen", location = "header", + order = 1, slug = "home", embed = new[] { "posts", "events" }, @public = true, }); await CreateRecordAsync(http, "pages", new { @@ -253,10 +253,13 @@ public sealed class PocketBaseFixture : IAsyncLifetime title = "Downloads", body = "# Downloads", location = "header", order = 5, slug = "downloads", embed = Array.Empty(), @public = true, }); + // A plain content page reached only by its slug (not shown in the header), + // so the catch-all "/{slug}" ContentPage route stays covered. It carries a + // valid location because the field is required; footer keeps it low-key. await CreateRecordAsync(http, "pages", new { - title = "FAQ Mensa", body = "# Mensa", location = "", - order = 0, slug = "faq-lunch", embed = Array.Empty(), @public = true, + title = "FAQ Mensa", body = "# Mensa", location = "footer", + order = 9, slug = "faq-lunch", embed = Array.Empty(), @public = true, }); await CreateRecordAsync(http, "pages", new { diff --git a/Elternbeirat.Web/Components/Layout/MainLayout.razor b/Elternbeirat.Web/Components/Layout/MainLayout.razor index 64c52f3..d12db70 100644 --- a/Elternbeirat.Web/Components/Layout/MainLayout.razor +++ b/Elternbeirat.Web/Components/Layout/MainLayout.razor @@ -20,10 +20,10 @@