Adds dynamic case study and curriculo routes, project health monitoring for live demo status, and strengthens local SEO (structured data, service-area targeting for Garuva/Joinville/Curitiba, a dedicated "criação de sites" service page) so search results better match the professional title (Engenheiro da Computação) and experience (5 anos). Co-Authored-By: Claude Sonnet 5 <[email protected]>
126 lines
3.6 KiB
TypeScript
126 lines
3.6 KiB
TypeScript
import { fireEvent, 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 }) => (
|
|
<div data-testid="hero-scene" data-variant={variant} />
|
|
);
|
|
DynamicComponent.displayName = "MockHeroScene";
|
|
return DynamicComponent;
|
|
});
|
|
|
|
jest.mock("framer-motion", () => {
|
|
const React = require("react");
|
|
|
|
const motion = new Proxy(
|
|
{},
|
|
{
|
|
get: (_, tag: string) => {
|
|
const Component = ({
|
|
children,
|
|
initial: _initial,
|
|
animate: _animate,
|
|
whileHover: _whileHover,
|
|
whileTap: _whileTap,
|
|
variants: _variants,
|
|
transition: _transition,
|
|
...props
|
|
}: { children?: ReactNode } & Record<string, unknown>) =>
|
|
React.createElement(tag, props, children);
|
|
Component.displayName = `motion.${tag}`;
|
|
return Component;
|
|
},
|
|
},
|
|
);
|
|
|
|
return {
|
|
AnimatePresence: ({ children }: { children: React.ReactNode }) => children,
|
|
motion,
|
|
useInView: () => true,
|
|
useReducedMotion: () => false,
|
|
};
|
|
});
|
|
|
|
function mockMatchMedia(matches = false) {
|
|
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", () => {
|
|
beforeEach(() => {
|
|
mockMatchMedia(false);
|
|
jest.spyOn(Math, "random").mockReturnValue(0);
|
|
jest.spyOn(window, "open").mockImplementation(() => null);
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.restoreAllMocks();
|
|
});
|
|
|
|
it("renders the command center hero and primary actions", async () => {
|
|
const { container } = render(<Hero />);
|
|
|
|
await waitFor(() =>
|
|
expect(container.querySelector("[data-hero-variant]")).toHaveAttribute(
|
|
"data-hero-variant",
|
|
"command-center",
|
|
),
|
|
);
|
|
|
|
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();
|
|
expect(
|
|
screen.getByRole("link", { name: /ver casos selecionados/i }),
|
|
).toHaveAttribute("href", "/cases");
|
|
expect(screen.getByText(/Download CV/i)).toBeInTheDocument();
|
|
expect(screen.queryByTestId("hero-scene")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("keeps social links, proof content and WhatsApp CTA", async () => {
|
|
render(<Hero />);
|
|
|
|
await waitFor(() =>
|
|
expect(
|
|
screen.getByText(/Disponível para novas oportunidades/i),
|
|
).toBeInTheDocument(),
|
|
);
|
|
|
|
expect(screen.getByLabelText("GitHub")).toBeInTheDocument();
|
|
expect(screen.getByLabelText("LinkedIn")).toBeInTheDocument();
|
|
expect(screen.getByLabelText("Email")).toBeInTheDocument();
|
|
expect(screen.getByText(/Garuva, SC \/ Brasil/i)).toBeInTheDocument();
|
|
expect(screen.getByText(/Operacao/i)).toBeInTheDocument();
|
|
expect(screen.getByText(/Clareza/i)).toBeInTheDocument();
|
|
expect(screen.getAllByText(/Resultado/i).length).toBeGreaterThan(0);
|
|
|
|
fireEvent.click(
|
|
screen.getByRole("button", { name: /conversar sobre uma oportunidade/i }),
|
|
);
|
|
expect(window.open).toHaveBeenCalledWith(
|
|
expect.stringContaining("https://wa.me/"),
|
|
"_blank",
|
|
"noopener,noreferrer",
|
|
);
|
|
});
|
|
});
|