import { fireEvent, render, screen } from "@testing-library/react";
import { getFeaturedProjects } from "@/lib/portfolio-data";
import {
type ShowcaseItem,
ShowcaseProvider,
useShowcaseItems,
useShowcaseOpen,
} from "./ShowcaseProvider";
// a janela ampliada chega sob demanda (React.lazy): aqui entra já (o dublê logo abaixo), para o teste não esperar
jest.mock("./ProjectLightboxLazy", () => ({
ProjectLightboxLazy: jest.requireMock("./ProjectLightbox").ProjectLightbox,
}));
/**
* Testes de caminhos-base de ShowcaseProvider (complemento de ShowcaseProvider.test.tsx). O provedor só guarda a
* lista da vitrine e qual projeto está ampliado: aqui, a janela aberta quando a lista muda, a troca de projeto
* com a janela já aberta e a estabilidade do que ele entrega (lista e função de abrir) entre renderizações.
* A janela ampliada é um dublê que só mostra o índice.
*/
jest.mock("./ProjectLightbox", () => ({
ProjectLightbox: ({
index,
items,
onClose,
}: {
index: number;
items: unknown[];
onClose: () => void;
}) => (
aberto:{index} de {items.length}
),
}));
const projects = getFeaturedProjects(null);
const clientIds = ["sev-modaintima", "lavacao-047", "sc-plus", "as-servicos"];
const clients = projects.filter((project) => clientIds.includes(project.id));
function Opener({ id }: { id: string }) {
const open = useShowcaseOpen();
return (
);
}
describe("ShowcaseProvider: janela ampliada e mudança da lista", () => {
it("path: window open and its project leaves the list -> the window goes away", () => {
const { rerender } = render(
,
);
fireEvent.click(screen.getByRole("button", { name: "abrir sc-plus" }));
expect(screen.getByRole("dialog")).toHaveTextContent("aberto:2 de 4");
rerender(
project.id !== "sc-plus")}
>
,
);
expect(screen.queryByRole("dialog")).toBeNull();
});
it("path: window open and another project is opened -> it moves to the new project, one window only", () => {
render(
,
);
fireEvent.click(
screen.getByRole("button", { name: "abrir sev-modaintima" }),
);
expect(screen.getByRole("dialog")).toHaveTextContent("aberto:0 de 4");
fireEvent.click(screen.getByRole("button", { name: "abrir as-servicos" }));
expect(screen.getAllByRole("dialog")).toHaveLength(1);
expect(screen.getByRole("dialog")).toHaveTextContent("aberto:3 de 4");
});
it("path: a project outside the showcase is asked while another window is open -> no window is left", () => {
render(
,
);
fireEvent.click(
screen.getByRole("button", { name: "abrir sev-modaintima" }),
);
fireEvent.click(
screen.getByRole("button", { name: "abrir reddit-explorer" }),
);
// o id desconhecido não acha posição na lista: a janela não mostra projeto nenhum
expect(screen.queryByRole("dialog")).toBeNull();
});
it("path: closed window -> reopening the same project works again", () => {
render(
,
);
fireEvent.click(screen.getByRole("button", { name: "abrir lavacao-047" }));
fireEvent.click(screen.getByRole("button", { name: "fechar" }));
expect(screen.queryByRole("dialog")).toBeNull();
fireEvent.click(screen.getByRole("button", { name: "abrir lavacao-047" }));
expect(screen.getByRole("dialog")).toHaveTextContent("aberto:1 de 4");
});
});
type Captured = {
items: ShowcaseItem[];
open: (id: string) => void;
};
function Probe({ onRender }: { onRender: (captured: Captured) => void }) {
onRender({ items: useShowcaseItems(), open: useShowcaseOpen() });
return null;
}
describe("ShowcaseProvider: o que entrega a quem está dentro", () => {
it("path: re-render with the same projects -> the same list and the same open function", () => {
const seen: Captured[] = [];
const tree = () => (
seen.push(captured)} />
);
const { rerender } = render(tree());
rerender(tree());
expect(seen.length).toBeGreaterThan(1);
expect(seen[seen.length - 1].items).toBe(seen[0].items);
expect(seen[seen.length - 1].open).toBe(seen[0].open);
});
it("path: a different list of projects -> a new list of items", () => {
const seen: Captured[] = [];
const probe = seen.push(captured)} />;
const { rerender } = render(
{probe},
);
rerender(
{probe}
,
);
expect(seen[0].items).toHaveLength(4);
expect(seen[seen.length - 1].items).toHaveLength(2);
});
});