Files
portifolio-evandrodevbr/app/servicos/_components/ServiceDiagram.test.tsx
Evandro Fonseca Junior fc44a69fb3 feat(servicos): ofertas no topo de /servicos, capa por assunto e diagramas
/servicos abre com as 3 ofertas e depois outros serviços; H1 de criação de sites e de engenharia com o nome da oferta; capa de cada serviço pelo assunto (SEV fora do próprio case cai de ~11 para 2 imagens); diagrama de fluxo em SVG nos serviços sem case; cases com o que o cliente passou a poder fazer e contato logo depois de Como ficou; FAQ num componente só; lastmod por rota; ProfessionalService com areaServed.
2026-10-14 19:14:46 -03:00

71 lines
3.1 KiB
TypeScript

import { render, screen } from "@testing-library/react";
import type { ServiceDiagramKind } from "@/lib/site-content";
import { ServiceDiagram } from "./ServiceDiagram";
/** Esquema de fluxo do topo dos serviços sem case com captura: SVG em linha, acessível, sem dado real nem logo de cliente. */
const expected: Record<ServiceDiagramKind, string[]> = {
iot: ["Dispositivo ou sensor", "Gateway", "API", "Painel"],
arquitetura: ["Interface", "API", "Serviços", "Banco de dados"],
desktop: ["Aplicativo no computador", "Arquivos", "Sistemas locais"],
};
describe("ServiceDiagram", () => {
for (const kind of Object.keys(expected) as ServiceDiagramKind[]) {
it(`path: ${kind} -> an inline SVG image with the flow in its label and the steps in order`, () => {
const { container } = render(<ServiceDiagram kind={kind} />);
const svg = screen.getByRole("img");
expect(svg.tagName.toLowerCase()).toBe("svg");
expect(svg).toHaveAttribute("aria-label");
expect(svg.getAttribute("aria-label")?.length).toBeGreaterThan(60);
const labels = Array.from(container.querySelectorAll("svg text")).map(
(text) => text.textContent,
);
expect(labels).toEqual(expected[kind]);
// o texto do desenho está no rótulo da imagem: quem lê a tela ouve o fluxo inteiro
for (const label of expected[kind]) {
expect(svg.getAttribute("aria-label")?.toLowerCase()).toContain(
label.toLowerCase().replace("dispositivo ou sensor", "dispositivo"),
);
}
expect(container.querySelectorAll("svg img, svg image")).toHaveLength(0);
});
}
it("path: IoT and architecture -> three arrows between four steps; desktop -> two arrows, both ways", () => {
const iot = render(<ServiceDiagram kind="iot" />);
expect(iot.container.querySelectorAll("svg line")).toHaveLength(3);
// uma ponta por seta
expect(iot.container.querySelectorAll("svg polygon")).toHaveLength(3);
iot.unmount();
const arquitetura = render(<ServiceDiagram kind="arquitetura" />);
expect(arquitetura.container.querySelectorAll("svg line")).toHaveLength(3);
arquitetura.unmount();
const desktop = render(<ServiceDiagram kind="desktop" />);
expect(desktop.container.querySelectorAll("svg line")).toHaveLength(2);
// duas pontas por seta: a informação vai e volta
expect(desktop.container.querySelectorAll("svg polygon")).toHaveLength(4);
});
it("path: colors -> only site tokens (paper and white), never the lime that belongs to contact, never a client logo", () => {
const { container } = render(<ServiceDiagram kind="iot" />);
const html = container.innerHTML;
expect(html).toMatch(/var\(--paper\)/);
expect(html).toMatch(/var\(--white\)/);
expect(html).not.toMatch(/--slash|#ccff00|ccff00/i);
expect(html).not.toMatch(/<image|<img|href=/i);
});
it("path: caption -> says it is an illustration, with no client data", () => {
render(<ServiceDiagram kind="arquitetura" />);
expect(
screen.getByText("Esquema ilustrativo, sem dados de clientes."),
).toBeVisible();
});
});