175 lines
5.3 KiB
TypeScript
175 lines
5.3 KiB
TypeScript
import { fireEvent, render, screen } from "@testing-library/react";
|
|
import { getFeaturedProjects } from "@/lib/portfolio-data";
|
|
import {
|
|
buildShowcaseItems,
|
|
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,
|
|
}));
|
|
|
|
/** A janela ampliada é testada em ProjectLightbox.test.tsx; aqui ela é um dublê que só mostra o índice e navega. */
|
|
jest.mock("./ProjectLightbox", () => ({
|
|
ProjectLightbox: ({
|
|
index,
|
|
onClose,
|
|
onNavigate,
|
|
}: {
|
|
index: number;
|
|
onClose: () => void;
|
|
onNavigate: (index: number) => void;
|
|
}) => (
|
|
<div role="dialog" aria-label="ampliado">
|
|
aberto:{index}
|
|
<button type="button" onClick={onClose}>
|
|
fechar
|
|
</button>
|
|
<button type="button" onClick={() => onNavigate(0)}>
|
|
ir para o primeiro
|
|
</button>
|
|
<button type="button" onClick={() => onNavigate(99)}>
|
|
ir para um que não existe
|
|
</button>
|
|
</div>
|
|
),
|
|
}));
|
|
|
|
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 (
|
|
<button type="button" onClick={() => open(id)}>
|
|
abrir {id}
|
|
</button>
|
|
);
|
|
}
|
|
|
|
describe("buildShowcaseItems", () => {
|
|
it("lists only projects that have a recorded showcase, in showcase order", () => {
|
|
const items = buildShowcaseItems(projects);
|
|
expect(items.map((item) => item.config.id)).toEqual([
|
|
"sev-modaintima",
|
|
"lavacao-047",
|
|
"nutriscan",
|
|
"sc-plus",
|
|
"as-servicos",
|
|
"julia-beauty",
|
|
]);
|
|
expect(
|
|
buildShowcaseItems(projects.filter((p) => p.id === "twins-lab")),
|
|
).toEqual([]);
|
|
});
|
|
|
|
it("serves the reel with only the client projects the home passes in, in showcase order", () => {
|
|
expect(buildShowcaseItems(clients).map((item) => item.config.id)).toEqual([
|
|
"sev-modaintima",
|
|
"lavacao-047",
|
|
"sc-plus",
|
|
"as-servicos",
|
|
]);
|
|
});
|
|
|
|
it("ignores projects missing from the list and builds nothing from an empty one", () => {
|
|
const only = projects.filter((project) =>
|
|
["as-servicos", "sev-modaintima"].includes(project.id),
|
|
);
|
|
|
|
expect(buildShowcaseItems(only).map((item) => item.config.id)).toEqual([
|
|
"sev-modaintima",
|
|
"as-servicos",
|
|
]);
|
|
expect(buildShowcaseItems([])).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe("ShowcaseProvider", () => {
|
|
it("shares the same list of items with whoever is inside it", () => {
|
|
function Count() {
|
|
return <p>itens:{useShowcaseItems().length}</p>;
|
|
}
|
|
render(
|
|
<ShowcaseProvider projects={clients}>
|
|
<Count />
|
|
</ShowcaseProvider>,
|
|
);
|
|
|
|
expect(screen.getByText("itens:4")).toBeInTheDocument();
|
|
});
|
|
|
|
it("opens the enlarged window on the project's position in the list, and closes it", () => {
|
|
render(
|
|
<ShowcaseProvider projects={clients}>
|
|
<Opener id="sc-plus" />
|
|
</ShowcaseProvider>,
|
|
);
|
|
expect(screen.queryByRole("dialog")).toBeNull();
|
|
|
|
fireEvent.click(screen.getByRole("button", { name: "abrir sc-plus" }));
|
|
// posição 3 de 4 na lista que a home passou (o NutriScan não está nela)
|
|
expect(screen.getByRole("dialog", { name: "ampliado" })).toHaveTextContent(
|
|
"aberto:2",
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole("button", { name: "fechar" }));
|
|
expect(screen.queryByRole("dialog")).toBeNull();
|
|
});
|
|
|
|
it("does nothing when asked to open a project that is not in the showcase", () => {
|
|
render(
|
|
<ShowcaseProvider projects={projects}>
|
|
<Opener id="reddit-explorer" />
|
|
</ShowcaseProvider>,
|
|
);
|
|
|
|
fireEvent.click(
|
|
screen.getByRole("button", { name: "abrir reddit-explorer" }),
|
|
);
|
|
|
|
expect(screen.queryByRole("dialog")).toBeNull();
|
|
});
|
|
|
|
it("changes project when the window navigates to a valid index, and closes on an invalid one", () => {
|
|
render(
|
|
<ShowcaseProvider projects={clients}>
|
|
<Opener id="lavacao-047" />
|
|
</ShowcaseProvider>,
|
|
);
|
|
fireEvent.click(screen.getByRole("button", { name: "abrir lavacao-047" }));
|
|
expect(screen.getByRole("dialog")).toHaveTextContent("aberto:1");
|
|
|
|
fireEvent.click(screen.getByRole("button", { name: "ir para o primeiro" }));
|
|
expect(screen.getByRole("dialog")).toHaveTextContent("aberto:0");
|
|
|
|
fireEvent.click(
|
|
screen.getByRole("button", { name: "ir para um que não existe" }),
|
|
);
|
|
expect(screen.queryByRole("dialog")).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("hooks used outside the provider", () => {
|
|
it("give an empty list, and opening does nothing", () => {
|
|
function Outsider() {
|
|
const items = useShowcaseItems();
|
|
const open = useShowcaseOpen();
|
|
return (
|
|
<button type="button" onClick={() => open("sev-modaintima")}>
|
|
itens:{items.length}
|
|
</button>
|
|
);
|
|
}
|
|
render(<Outsider />);
|
|
|
|
const button = screen.getByRole("button", { name: "itens:0" });
|
|
expect(() => fireEvent.click(button)).not.toThrow();
|
|
expect(screen.queryByRole("dialog")).toBeNull();
|
|
});
|
|
});
|