Hero: ehrliche Fakten statt Zahlenleiste
Die Leiste mit Projektzähler (/api/projects), "Am Markt"-Ticker, 99,9 % Systemverfügbarkeit und Flagge ist ersetzt durch drei belegbare Fakten ohne Count-up: Falkenstein (Server in Deutschland), Live-Vorschau (im Kundenportal) und ab 20 € (Hosting im Monat). Einspaltig auf dem Handy, ab md drei Spalten. Der zweite Button "Projekte ansehen" ist entfernt, ebenso Projekt-Query, FOUNDING_DATE und src/lib/projects.ts. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
79c3551934
commit
a27b1fe255
3 files changed
+133
-144
No files matched your search
@@ -0,0 +1,119 @@
|
||||
import { describe, it, expect, vi, afterEach } from "vitest";
|
||||
import { render, screen, within, fireEvent, act, cleanup } from "@testing-library/react";
|
||||
import { MemoryRouter } from "react-router-dom";
|
||||
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { AppRoutes } from "@/routes";
|
||||
import { usePageMeta } from "@/hooks/use-page-meta";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import Hero from "@/components/Hero";
|
||||
import ProblemSection from "@/components/ProblemSection";
|
||||
import SolutionSection from "@/components/SolutionSection";
|
||||
import Values from "@/components/Values";
|
||||
import Services from "@/components/Services";
|
||||
import Process from "@/components/Process";
|
||||
import KontaktAbschnitt from "@/components/Contact";
|
||||
import About from "@/pages/About";
|
||||
import { TextHoverEffect } from "@/components/ui/text-hover-effect";
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
|
||||
// WebGL, Canvas und Netzwerk laden wir in jsdom nicht: die Effekt-Komponenten und
|
||||
// das Kontaktformular-Backend werden durch Attrappen ersetzt.
|
||||
vi.mock("@/components/Silk", () => ({ default: () => null }));
|
||||
vi.mock("@/components/PixelBlast", () => ({ default: () => null }));
|
||||
vi.mock("@/components/LightRays", () => ({ default: () => null }));
|
||||
vi.mock("@/components/ui/flickering-grid", () => ({ FlickeringGrid: () => null }));
|
||||
vi.mock("@/lib/appwrite", () => ({ createContactDocument: vi.fn().mockResolvedValue(undefined) }));
|
||||
|
||||
// Dieselben Future-Flags wie der BrowserRouter in App.tsx, sonst warnt React Router in der Testausgabe.
|
||||
const routerFuture = { v7_startTransition: true, v7_relativeSplatPath: true };
|
||||
|
||||
const DATENSCHUTZ = "https://project.webklar.com/datenschutz.html";
|
||||
const TELEFON = "0176 23726355";
|
||||
const TELEFON_HREF = "tel:+4917623726355";
|
||||
|
||||
/** Rendert die komplette Routenliste (mit gemeinsamem Footer) an einem Pfad. */
|
||||
const seite = (pfad: string) =>
|
||||
render(
|
||||
<MemoryRouter initialEntries={[pfad]} future={routerFuture}>
|
||||
<AppRoutes />
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
/** Rendert eine einzelne Komponente im Router. */
|
||||
const zeige = (ui: React.ReactElement) =>
|
||||
render(
|
||||
<MemoryRouter future={routerFuture}>
|
||||
{ui}
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
// ── Quelltext-Scan ─────────────────────────────────────────────────────────────
|
||||
// vitest läuft im Projektverzeichnis
|
||||
const WURZEL = `${process.cwd()}/`;
|
||||
const dateien = (ordner: string): string[] =>
|
||||
readdirSync(ordner).flatMap((name) => {
|
||||
const pfad = join(ordner, name);
|
||||
return statSync(pfad).isDirectory() ? dateien(pfad) : [pfad];
|
||||
});
|
||||
const QUELLEN = [
|
||||
...dateien(join(WURZEL, "src")).filter((p) => /\.(tsx?|css)$/.test(p) && !p.includes("/src/test/")),
|
||||
join(WURZEL, "index.html"),
|
||||
].map((pfad) => ({ pfad: pfad.replace(WURZEL, ""), text: readFileSync(pfad, "utf8") }));
|
||||
|
||||
/** Pfade aller Quelldateien (ohne Tests), in denen das Muster vorkommt. */
|
||||
const vorkommen = (muster: RegExp) => QUELLEN.filter(({ text }) => muster.test(text)).map(({ pfad }) => pfad);
|
||||
const lies = (pfad: string) => readFileSync(join(WURZEL, pfad), "utf8");
|
||||
const gibtEs = (pfad: string) => existsSync(join(WURZEL, pfad));
|
||||
|
||||
const meta = (name: string) => document.querySelector(`meta[name="${name}"]`)?.getAttribute("content");
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
vi.restoreAllMocks();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
describe("B1 Hero: ehrliche Fakten statt Zahlenleiste", () => {
|
||||
const FAKTEN = [
|
||||
["Falkenstein", "Server in Deutschland"],
|
||||
["Live-Vorschau", "im Kundenportal"],
|
||||
["ab 20 €", "Hosting im Monat"],
|
||||
];
|
||||
|
||||
it("zeigt genau drei Fakten mit Wert und Beschriftung", () => {
|
||||
zeige(<Hero />);
|
||||
for (const [wert, beschriftung] of FAKTEN) {
|
||||
expect(screen.getByText(wert)).toBeInTheDocument();
|
||||
expect(screen.getByText(beschriftung)).toBeInTheDocument();
|
||||
}
|
||||
const raster = screen.getByText("Falkenstein").closest(".grid");
|
||||
expect(raster?.children).toHaveLength(3);
|
||||
expect(raster).toHaveClass("grid-cols-1", "md:grid-cols-3");
|
||||
});
|
||||
|
||||
it("die alte Zahlenleiste ist weg: kein Projektzähler, kein »Am Markt«, keine 99,9 %, keine Flagge", () => {
|
||||
const { container } = zeige(<Hero />);
|
||||
expect(screen.queryByText("Am Markt")).toBeNull();
|
||||
expect(screen.queryByText("Projekte")).toBeNull();
|
||||
expect(screen.queryByText("Systemverfügbarkeit")).toBeNull();
|
||||
expect(container).not.toHaveTextContent(/99[,.]9|🇩🇪|Serverstandort/);
|
||||
});
|
||||
|
||||
it("hat nur noch den Potenzialanalyse-Button, keinen »Projekte ansehen«", () => {
|
||||
zeige(<Hero />);
|
||||
expect(screen.getAllByRole("button").map((b) => b.getAttribute("aria-label"))).toEqual([
|
||||
"Kostenlose Potenzialanalyse sichern",
|
||||
]);
|
||||
});
|
||||
|
||||
it("lädt nichts vom Netz und braucht keinen QueryClient", () => {
|
||||
const abruf = vi.fn();
|
||||
vi.stubGlobal("fetch", abruf);
|
||||
zeige(<Hero />);
|
||||
expect(abruf).not.toHaveBeenCalled();
|
||||
expect(gibtEs("src/lib/projects.ts")).toBe(false);
|
||||
expect(vorkommen(/api\/projects|fetchProjects|FOUNDING_DATE/)).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user