| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- /* @vitest-environment node */
- import { describe, it, expect, vi } from "vitest";
- import React from "react";
- import { renderToString } from "react-dom/server";
- /**
- * Mock `next/link` so this unit test does not depend on the Next.js runtime.
- * For a server-render smoke test, a minimal <a href="..."> replacement is enough.
- */
- vi.mock("next/link", async () => {
- const ReactNs = await import("react");
- const React = ReactNs.default ?? ReactNs;
- function LinkMock({ href, children, ...props }) {
- const resolvedHref =
- typeof href === "string"
- ? href
- : href?.pathname
- ? String(href.pathname)
- : "";
- return React.createElement("a", { href: resolvedHref, ...props }, children);
- }
- return { default: LinkMock };
- });
- /**
- * Mock `next/image` to avoid Next.js runtime constraints in SSR unit tests
- * (e.g. width/height enforcement, internal config dependencies).
- */
- vi.mock("next/image", async () => {
- const ReactNs = await import("react");
- const React = ReactNs.default ?? ReactNs;
- function ImageMock(props) {
- const {
- src,
- alt,
- width,
- height,
- fill,
- priority,
- quality,
- loader,
- blurDataURL,
- placeholder,
- sizes,
- ...rest
- } = props || {};
- const resolvedSrc =
- typeof src === "string" ? src : src?.src ? String(src.src) : "";
- const imgProps = {
- src: resolvedSrc,
- alt: alt || "",
- ...rest,
- };
- // Only attach width/height if present (fill-mode images won't have them).
- if (width !== undefined) imgProps.width = width;
- if (height !== undefined) imgProps.height = height;
- return React.createElement("img", imgProps);
- }
- return { default: ImageMock };
- });
- /**
- * AppShell renders TopNav which includes QuickNav (client component).
- * QuickNav uses next/navigation hooks (useRouter/usePathname).
- *
- * In a pure react-dom/server smoke test, we must mock these hooks to avoid
- * runtime errors and keep this test deterministic.
- */
- vi.mock("next/navigation", () => {
- return {
- usePathname: () => "/",
- useRouter: () => ({
- push: () => {},
- replace: () => {},
- refresh: () => {},
- prefetch: () => {},
- }),
- };
- });
- // Import AFTER the mocks so the module under test uses the mocked Next modules.
- import AppShell from "./AppShell";
- describe("components/app-shell/AppShell", () => {
- it("renders the shell without crashing and includes key areas", () => {
- const element = React.createElement(
- AppShell,
- null,
- React.createElement("div", null, "Child content"),
- );
- const html = renderToString(element);
- // Sidebar placeholder heading (German)
- expect(html).toContain("Seitenleiste");
- // Rendered children
- expect(html).toContain("Child content");
- });
- });
|