Unterseiten: gemeinsamer Footer über ein Layout

/kontakt, /ueber-uns, /agb, /impressum, /wartungs-abo, /hosting-abo und
die 404-Seite bekommen den vorhandenen Footer (Impressum, Datenschutz,
Kündigen/Widerrufen) über ein gemeinsames Layout in src/routes.tsx. Die
Seiten selbst bleiben unverändert, damit die bestehenden Abo- und
AGB-Tests nicht auf doppelte Footer-Links stoßen. Die Startseite behält
ihren eigenen Footer, /datenschutz leitet weiter und bleibt ohne.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Sonnet 5.5 committed 2026-10-01 10:41:38 +00:00
1 parent c75befe8e5
commit 900d3a9ab5
2 files changed
+44 -9

No files matched your search

+21 -9
View File
@@ -1,4 +1,5 @@
import { Routes, Route } from "react-router-dom";
import { Routes, Route, Outlet } from "react-router-dom";
import Footer from "@/components/Footer";
import Index from "./pages/Index";
import ContactPage from "./pages/Contact";
import AGBPage from "./pages/AGB";
@@ -9,18 +10,29 @@ import HostingAboPage from "./pages/HostingAbo";
import DatenschutzPage from "./pages/Datenschutz";
import NotFound from "./pages/NotFound";
/** Gemeinsamer Rahmen aller Unterseiten: Seiteninhalt, darunter der Footer mit Impressum, Datenschutz und Kündigen. */
const SubpageLayout = () => (
<>
<Outlet />
<Footer />
</>
);
/** Alle Seiten der Website; App.tsx rendert sie im BrowserRouter, die Tests im MemoryRouter. */
export const AppRoutes = () => (
<Routes>
{/* Die Startseite bringt ihren Footer selbst mit; /datenschutz leitet nur weiter. */}
<Route path="/" element={<Index />} />
<Route path="/kontakt" element={<ContactPage />} />
<Route path="/agb" element={<AGBPage />} />
<Route path="/impressum" element={<ImpressumPage />} />
<Route path="/ueber-uns" element={<AboutPage />} />
<Route path="/wartungs-abo" element={<WartungsAboPage />} />
<Route path="/hosting-abo" element={<HostingAboPage />} />
<Route path="/datenschutz" element={<DatenschutzPage />} />
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
<Route path="*" element={<NotFound />} />
<Route element={<SubpageLayout />}>
<Route path="/kontakt" element={<ContactPage />} />
<Route path="/agb" element={<AGBPage />} />
<Route path="/impressum" element={<ImpressumPage />} />
<Route path="/ueber-uns" element={<AboutPage />} />
<Route path="/wartungs-abo" element={<WartungsAboPage />} />
<Route path="/hosting-abo" element={<HostingAboPage />} />
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
<Route path="*" element={<NotFound />} />
</Route>
</Routes>
);
+23
View File
@@ -259,3 +259,26 @@ describe("B5 Erfolgsversprechen entschärft", () => {
expect(screen.queryByText("Langfristige Partnerschaft")).toBeNull();
});
});
describe("C1 Footer auf allen Unterseiten", () => {
const unterseiten = ["/kontakt", "/ueber-uns", "/agb", "/impressum", "/wartungs-abo", "/hosting-abo", "/gibt-es-nicht"];
it.each(unterseiten)("%s zeigt genau einen Footer mit Impressum und Datenschutz", (pfad) => {
seite(pfad);
const footer = screen.getByRole("contentinfo");
expect(within(footer).getByRole("link", { name: "Impressum" })).toHaveAttribute("href", "/impressum");
expect(within(footer).getByRole("link", { name: "Datenschutz" })).toHaveAttribute("href", DATENSCHUTZ);
});
it("die Startseite hat weiterhin genau einen Footer", () => {
seite("/");
expect(screen.getAllByRole("contentinfo")).toHaveLength(1);
});
it("der Footer steht hinter dem Seiteninhalt", () => {
seite("/impressum");
const inhalt = screen.getByRole("main");
const footer = screen.getByRole("contentinfo");
expect(inhalt.compareDocumentPosition(footer) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
});
});