Files
portifolio-evandrodevbr/app/components/ClientStrip.test.tsx
T
Evandro Fonseca Junior 9e2d65a926 fix(home): oferta leva ao formulário, ofertas logo depois da vitrine
O botão das ofertas rola até o contato com o tipo marcado e não quebra mais as âncoras; ofertas com o que você recebe e primeiro passo, logo depois da vitrine; bloco de IA fora da home; cartão largo da SEV no hero do celular; separador da faixa de clientes só entre itens; favicon de 13 para 1,8 KB; pré-carregamento só no hover e nunca de /#... fora da home; X do menu e cabeçalho opaco; WhatsApp com "o case"; /ia com 3 passos e modelo de relatório ilustrativo; Sobre alinhado ao currículo; CSP Report-Only com os domínios do Ads.
2026-10-14 19:14:47 -03:00

110 lines
4.1 KiB
TypeScript

import { render, screen, within } from "@testing-library/react";
import ClientStrip from "./ClientStrip";
const clients = [
{ id: "sev-modaintima", name: "SEV Moda Íntima" },
{ id: "lavacao-047", name: "Lavação 047" },
];
it("lists each client as a link to its case", () => {
render(<ClientStrip clients={clients} />);
expect(screen.getByText("Já entregue para:")).toBeInTheDocument();
const list = screen.getByRole("list");
const links = within(list).getAllByRole("link");
expect(links.map((link) => link.textContent)).toEqual([
"SEV Moda Íntima",
"Lavação 047",
]);
expect(links.map((link) => link.getAttribute("href"))).toEqual([
"/cases/sev-modaintima",
"/cases/lavacao-047",
]);
});
it("renders nothing without clients", () => {
const { container } = render(<ClientStrip clients={[]} />);
expect(container).toBeEmptyDOMElement();
const withoutProp = render(<ClientStrip />);
expect(withoutProp.container).toBeEmptyDOMElement();
});
it("puts the years of experience in the same line, after the clients", () => {
render(<ClientStrip clients={clients} years={5} />);
const experience = screen.getByText("anos de experiência");
expect(screen.getByText("5")).toBeInTheDocument();
const lastClient = screen.getByRole("link", { name: "Lavação 047" });
expect(
lastClient.compareDocumentPosition(experience) &
Node.DOCUMENT_POSITION_FOLLOWING,
).toBeTruthy();
expect(experience.closest("div")).toBe(
screen.getByText("Já entregue para:").parentElement,
);
});
it("shows only the experience when there are no clients, and nothing without either", () => {
const only = render(<ClientStrip years={5} />);
expect(screen.queryByText("Já entregue para:")).toBeNull();
expect(screen.getByText("anos de experiência")).toBeInTheDocument();
only.unmount();
const none = render(<ClientStrip years={0} />);
expect(none.container).toBeEmptyDOMElement();
});
it("gives every client link a touch target of at least 44 px (min-h-11)", () => {
render(<ClientStrip clients={clients} />);
for (const link of screen.getAllByRole("link")) {
expect(link).toHaveClass("min-h-11");
}
});
it("puts the separator only BETWEEN items: none before the first, one before each of the others (years included)", () => {
const withYears = render(<ClientStrip clients={clients} years={5} />);
const items = withYears.container.querySelectorAll("li");
expect(items).toHaveLength(clients.length + 1);
expect(
Array.from(items).map(
(item) => item.querySelector("[aria-hidden='true']") !== null,
),
).toEqual([false, true, true]);
// nenhum item termina com o ponto: ele sempre abre o item, para a margem negativa escondê-lo no começo de uma linha
for (const item of items) {
expect(item.lastElementChild).not.toHaveAttribute("aria-hidden");
}
withYears.unmount();
// zero anos não escreve um "0" solto nem um ponto a mais
const zero = render(<ClientStrip clients={clients} years={0} />);
expect(
zero.container.querySelectorAll("li [aria-hidden='true']"),
).toHaveLength(clients.length - 1);
expect(zero.container).not.toHaveTextContent(/anos de experiência/);
expect(screen.queryByText("0")).toBeNull();
});
it("hides the separator of an item that wraps to the next line: negative margin on every item but the first, and the list clips the overflow on the x axis", () => {
const { container } = render(<ClientStrip clients={clients} years={5} />);
const list = container.querySelector("ul") as HTMLElement;
expect(list).toHaveClass("flex-wrap", "overflow-x-clip");
const items = Array.from(list.querySelectorAll("li"));
expect(items[0]).not.toHaveClass("-ml-4");
for (const item of items.slice(1)) {
expect(item).toHaveClass("-ml-4");
// o ponto ocupa os mesmos 16 px que a margem negativa
expect(item.querySelector("[aria-hidden='true']")).toHaveClass("w-4");
}
for (const item of items) expect(item).toHaveClass("pr-4");
});
it("keeps the years number in the display font (the mono font is not downloaded above the fold)", () => {
render(<ClientStrip clients={clients} years={5} />);
expect(screen.getByText("5").className).not.toContain("font-mono");
});