import { cleanup } from "@testing-library/react"; import { afterEach, vi } from "vitest"; import "@testing-library/jest-dom/vitest"; import React from "react"; afterEach(() => { cleanup(); }); // --------------------------------------------------------------------------- // Global mocks for heavy / browser-only libraries so components render in jsdom. // (vi.mock in a setup file applies to every test file in the component project.) // --------------------------------------------------------------------------- vi.mock("framer-motion", () => { const passthrough = (tag: string) => React.forwardRef(function MotionMock( { children, ...props }: Record & { children?: React.ReactNode }, ref: React.Ref, ) { const domProps: Record = {}; for (const [key, value] of Object.entries(props)) { // Drop motion-only props that would warn as unknown DOM attributes. if ( /^(initial|animate|exit|transition|variants|whileHover|whileTap|whileInView|whileFocus|whileDrag|drag|layout|layoutId|viewport|custom|onAnimationComplete|style)$/.test( key, ) ) { if (key === "style") domProps.style = value; continue; } domProps[key] = value; } return React.createElement(tag, { ...domProps, ref }, children as React.ReactNode); }); const motion = new Proxy( {}, { get: (_target, tag: string) => passthrough(tag), }, ); return { motion, AnimatePresence: ({ children }: { children?: React.ReactNode }) => React.createElement(React.Fragment, null, children), useReducedMotion: () => true, useInView: () => true, useScroll: () => ({ scrollYProgress: { on: () => () => {}, get: () => 0 } }), useTransform: () => 0, useMotionValue: (value: unknown) => ({ get: () => value, set: () => {}, on: () => () => {} }), useAnimate: () => [React.useRef(null), () => Promise.resolve()], }; }); vi.mock("gsap", () => { const tween = { kill: () => {}, play: () => {}, pause: () => {}, progress: () => {} }; const gsap = { to: () => tween, from: () => tween, fromTo: () => tween, set: () => tween, timeline: () => ({ to: () => ({}), from: () => ({}), fromTo: () => ({}), add: () => ({}), kill: () => {}, }), registerPlugin: () => {}, context: (fn: () => void) => { if (typeof fn === "function") fn(); return { revert: () => {}, kill: () => {} }; }, matchMedia: () => ({ add: () => {}, revert: () => {} }), utils: { toArray: (v: unknown) => (Array.isArray(v) ? v : [v]) }, }; return { gsap, default: gsap }; }); vi.mock("@gsap/react", () => ({ useGSAP: () => ({ context: {}, contextSafe: (fn: unknown) => fn }), })); vi.mock("next/link", () => ({ default: React.forwardRef(function LinkMock( { href, children, ...props }: Record & { href?: unknown; children?: React.ReactNode }, ref: React.Ref, ) { return React.createElement("a", { href: String(href ?? ""), ref, ...props }, children as React.ReactNode); }), })); vi.mock("next/image", () => ({ default: ({ src, alt, ...props }: Record & { src?: unknown; alt?: string }) => React.createElement("img", { src: String(src ?? ""), alt: alt ?? "", ...props }), })); vi.mock("next/navigation", () => ({ usePathname: () => "/", useRouter: () => ({ push: vi.fn(), replace: vi.fn(), refresh: vi.fn(), back: vi.fn(), forward: vi.fn(), prefetch: vi.fn(), }), useSearchParams: () => new URLSearchParams(), useParams: () => ({}), redirect: vi.fn(), notFound: vi.fn(), })); vi.mock("next-intl", () => ({ useTranslations: () => { const t = (key: string) => key; t.rich = (key: string) => key; t.markup = (key: string) => key; t.raw = (key: string) => key; return t; }, useLocale: () => "de", useFormatter: () => ({ dateTime: (v: Date) => v.toISOString(), number: (v: number) => String(v), relativeTime: (v: unknown) => String(v), }), useMessages: () => ({}), NextIntlClientProvider: ({ children }: { children?: React.ReactNode }) => React.createElement(React.Fragment, null, children), }));