import { render, screen, waitFor } from "@testing-library/react"; import type { ReactNode } from "react"; import Hero from "./Hero"; jest.mock("next/dynamic", () => () => { const DynamicComponent = ({ variant }: { variant?: string }) => (
); DynamicComponent.displayName = "MockHeroScene"; return DynamicComponent; }); jest.mock("motion/react", () => { const React = require("react"); const motion = new Proxy( {}, { get: (_, tag: string) => { const Component = ({ children, initial, animate, whileHover: _whileHover, whileTap: _whileTap, variants: _variants, transition: _transition, ...props }: { children?: ReactNode; initial?: unknown; animate?: unknown; } & Record) => { const dataProps = { ...(initial !== undefined ? { "data-initial": JSON.stringify(initial) } : {}), ...(animate !== undefined ? { "data-animate": JSON.stringify(animate) } : {}), }; return React.createElement(tag, { ...props, ...dataProps }, children); }; Component.displayName = `motion.${tag}`; return Component; }, }, ); return { AnimatePresence: ({ children }: { children: React.ReactNode }) => children, motion, useInView: () => true, useReducedMotion: () => true, useMotionValue: (initial: number) => ({ get: () => initial, set: jest.fn(), }), useSpring: ( value: { get: () => number; set: (v: number) => void }, _config: unknown, ) => value, useTransform: ( value: { get: () => number; set: (v: number) => void }, _input: number[], _output: number[], ) => value, }; }); jest.mock("cobe", () => ({ __esModule: true, default: jest.fn(() => ({ destroy: jest.fn(), })), })); function mockMatchMedia(matches: boolean) { Object.defineProperty(window, "matchMedia", { writable: true, value: jest.fn().mockImplementation((query) => ({ matches, media: query, onchange: null, addListener: jest.fn(), removeListener: jest.fn(), addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), })), }); } describe("Hero reduced motion", () => { beforeEach(() => { mockMatchMedia(true); jest.spyOn(Math, "random").mockReturnValue(0); }); afterEach(() => { jest.restoreAllMocks(); }); it("keeps essential hero content visible with reduced motion enabled", async () => { render(); await waitFor(() => expect(screen.queryByTestId("hero-scene")).not.toBeInTheDocument(), ); expect( screen.getByText(/Disponível para novas oportunidades/i), ).toBeInTheDocument(); expect( screen.getByRole("heading", { level: 1, name: /engenharia de software para sistemas/i, }), ).toBeInTheDocument(); expect( screen.getByRole("button", { name: /conversar sobre uma oportunidade/i }), ).toBeInTheDocument(); }); it("keeps motion blocks declarative instead of requiring 3D", async () => { const { container } = render(); await waitFor(() => expect(screen.queryByTestId("hero-scene")).not.toBeInTheDocument(), ); const rootMotionBlock = container.querySelector( "div[data-initial][data-animate]", ); expect(rootMotionBlock).toBeInTheDocument(); expect(rootMotionBlock?.getAttribute("data-initial")).toContain("hidden"); expect(rootMotionBlock?.getAttribute("data-animate")).toContain("visible"); }); });