From 60ccfa8122a5388a7edde7515e3c23b47707f435 Mon Sep 17 00:00:00 2001 From: Dave Date: Wed, 14 Oct 2026 11:03:04 +0200 Subject: [PATCH] fix(sidebar): top-level nav rendered only dashboardItems[0] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Search entry added in 1ee3555 was in the array, in the build, and typed correctly — and never appeared. The top-level nav block rendered `dashboardItems[0]` with a hardcoded index, so every entry after the first was silently dropped. Caught when the operator asked where the link was. Rendered as a map so appending an entry just works. Regression test asserts the whole top-level set (Dashboard + Search) rather than "Search exists", so the next person to append an entry gets a passing test instead of an invisible link. Verified it fails when the map is limited back to a single entry while the three pre-existing sidebar tests keep passing. --- src/components/sidebar.test.tsx | 27 +++++++++++++++++++++++++++ src/components/sidebar.tsx | 20 ++++++++++++++------ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/components/sidebar.test.tsx b/src/components/sidebar.test.tsx index 1e0cc0c..686ee75 100644 --- a/src/components/sidebar.test.tsx +++ b/src/components/sidebar.test.tsx @@ -95,4 +95,31 @@ describe("Sidebar", () => { expect(ops.queryByText("Stock Orders")).not.toBeInTheDocument(); expect(ops.queryByText("Pricelist")).not.toBeInTheDocument(); }); + + it("renders every top-level nav entry, not just the first", () => { + // Regression guard. The top-level nav rendered `dashboardItems[0]` + // — a hardcoded index — so any entry added after Dashboard existed + // in the array and in the build but never appeared in the sidebar. + // That's how the universal Search link shipped invisible: the + // operator asked for it, the code was correct, the entry was simply + // never rendered. + // + // Asserts the full top-level set rather than "Search exists" so the + // next person to append an entry gets a passing test instead of a + // silently invisible link. + render(); + const desktop = screen.getAllByRole("complementary")[0]; + + for (const label of ["Dashboard", "Search"]) { + expect( + within(desktop).queryByText(label, { exact: true }), + `top-level nav should render "${label}"`, + ).toBeInTheDocument(); + } + + // And the Search entry must actually point at the route. + const link = within(desktop).getByText("Search", { exact: true }).closest("a"); + expect(link).not.toBeNull(); + expect(link).toHaveAttribute("href", "/search"); + }); }); diff --git a/src/components/sidebar.tsx b/src/components/sidebar.tsx index b664326..6f4d6f9 100644 --- a/src/components/sidebar.tsx +++ b/src/components/sidebar.tsx @@ -330,12 +330,20 @@ function NavContent({ onLinkClick }: { onLinkClick?: () => void }) { {/* Nav */}