import { fireEvent, render, screen } from "@testing-library/react";
import type { ReactNode } from "react";
import {
getFeaturedProjects,
type PortfolioProjectView,
} from "@/lib/portfolio-data";
import { isClientProject } from "@/lib/proof";
import Projects from "./Projects";
// o Link do Next, trocado por um que mostra o `prefetch` recebido: HoverPrefetchLink começa em false
jest.mock("next/link", () => ({
__esModule: true,
default: ({
children,
prefetch,
...props
}: { children?: React.ReactNode; prefetch?: boolean | null } & Record<
string,
unknown
>) => (
{children}
),
}));
jest.mock("./Section", () => ({
Section: ({ children, title }: { children: ReactNode; title: string }) => (
),
}));
const providerProjects = jest.fn();
jest.mock("./showcase/ShowcaseProvider", () => ({
ShowcaseProvider: ({
children,
projects,
}: {
children: ReactNode;
projects: PortfolioProjectView[];
}) => {
providerProjects(projects);
return
{children}
;
},
}));
jest.mock("./showcase/ProjectReel", () => ({
ProjectReel: () => ,
}));
// A página entrega só os projetos de cliente; aqui usamos os reais do portfólio, com uma demo indisponível de propósito
const clientProjects: PortfolioProjectView[] = getFeaturedProjects(null)
.filter(isClientProject)
.map((project, index) => ({
...project,
demoAvailability: index === 0 ? ("unavailable" as const) : "available",
}));
describe("Projects", () => {
beforeEach(() => providerProjects.mockClear());
it("presents the client projects once, through the reel only", () => {
const { container } = render();
expect(clientProjects.length).toBeGreaterThan(0);
expect(screen.getByTestId("project-reel")).toBeInTheDocument();
expect(providerProjects).toHaveBeenCalledWith(clientProjects);
// sem grade de cards: nem artigos, nem capas provisórias
expect(container.querySelector("article")).toBeNull();
expect(container.querySelector(".ds-cover, .ds-cover-fallback")).toBeNull();
expect(screen.queryByRole("heading", { level: 3 })).not.toBeInTheDocument();
});
it("drops the availability badge, the code link and every GitHub link", () => {
const { container } = render();
expect(
screen.queryByText(/Demo indisponível|indisponível na última/i),
).toBeNull();
expect(screen.queryByText(/Ver codigo|Ver código/i)).toBeNull();
expect(screen.queryByText(/Abrir projeto/i)).toBeNull();
for (const link of container.querySelectorAll("a")) {
expect(link.getAttribute("href") ?? "").not.toMatch(/github\.com/);
}
});
it("ends with a secondary link to all the cases", () => {
render();
const link = screen.getByRole("link", { name: "Ver os cases" });
expect(link).toHaveAttribute("href", "/cases");
// secundário: contorno, sem o fundo verde-limão do contato
expect(link.className).toContain("border");
expect(link.className).not.toContain("bg-[var(--slash)]");
expect(screen.getAllByRole("link")).toEqual([link]);
});
it("pre-fetches /cases only when the visitor reaches the link, not when it comes into view", () => {
render();
const link = screen.getByRole("link", { name: "Ver os cases" });
expect(link).toHaveAttribute("data-prefetch", "false");
fireEvent.mouseEnter(link);
expect(link).toHaveAttribute("data-prefetch", "null");
});
});