Files
portifolio-evandrodevbr/lib/og-card.test.tsx
T
Evandro Fonseca Junior e80f73d075 feat(cases): mídia no topo, títulos de busca curtos e CreativeWork
Case com mídia ao lado do título e play acessível; problema de cada cliente reescrito com base nos dados; serviços relacionados em 2 cards; FAQ antes do próximo passo e bloco 'Onde já apliquei isso'; Apolo citada em IoT e arquitetura. metaTitle até 43 caracteres e descrições até 155 com teste; JSON-LD CreativeWork; imagens de compartilhamento abaixo de 100 KB; 404 e robots corrigidos; server-only nos módulos com node:.
2026-10-14 14:15:25 -03:00

103 lines
3.5 KiB
TypeScript

import { statSync } from "node:fs";
import { render } from "@testing-library/react";
import { OG_IMAGE_MAX_BYTES, OgCard, readProjectOgImage } from "./og-card";
import { PROJECT_VIDEO_IDS } from "./project-showcase";
jest.mock("node:fs", () => {
const actual = jest.requireActual<typeof import("node:fs")>("node:fs");
return { ...actual, statSync: jest.fn(actual.statSync) };
});
const mockedStatSync = jest.mocked(statSync);
const actualStatSync =
jest.requireActual<typeof import("node:fs")>("node:fs").statSync;
afterEach(() => {
mockedStatSync.mockImplementation(actualStatSync);
});
/** Largura e altura de um JPEG, lidas do primeiro marcador de quadro (SOF). */
function jpegSize(image: Buffer) {
let offset = 2;
while (offset < image.length) {
const marker = image[offset + 1];
const length = image.readUInt16BE(offset + 2);
if (
marker >= 0xc0 &&
marker <= 0xcf &&
marker !== 0xc4 &&
marker !== 0xc8
) {
return {
height: image.readUInt16BE(offset + 5),
width: image.readUInt16BE(offset + 7),
};
}
offset += 2 + length;
}
throw new Error("JPEG sem marcador de quadro");
}
describe("readProjectOgImage", () => {
it("returns the recorded cover of a showcase project as it is, in JPEG", () => {
const image = readProjectOgImage("nutriscan");
expect(image?.subarray(0, 2).toString("hex")).toBe("ffd8");
expect(image?.length).toBeGreaterThan(5_000);
});
it("serves every recorded cover below 150 KB and in the 1200x630 card size", () => {
expect(OG_IMAGE_MAX_BYTES).toBe(150_000);
for (const id of PROJECT_VIDEO_IDS) {
const image = readProjectOgImage(id);
expect(image).toBeDefined();
expect(image?.length ?? Infinity).toBeLessThan(150_000);
expect(jpegSize(image as Buffer)).toEqual({ width: 1200, height: 630 });
}
});
it("returns undefined for a cover that weighs the limit or more, so the plain card is used", () => {
mockedStatSync.mockReturnValue({
size: OG_IMAGE_MAX_BYTES,
} as ReturnType<typeof statSync>);
expect(readProjectOgImage("nutriscan")).toBeUndefined();
mockedStatSync.mockReturnValue({
size: OG_IMAGE_MAX_BYTES - 1,
} as ReturnType<typeof statSync>);
expect(readProjectOgImage("nutriscan")).toBeDefined();
});
it("returns undefined for projects without a recorded cover", () => {
expect(readProjectOgImage("twins-lab")).toBeUndefined();
expect(readProjectOgImage("../../etc/passwd")).toBeUndefined();
});
it("returns undefined when the file is missing on disk", () => {
mockedStatSync.mockImplementation(() => {
throw new Error("ENOENT");
});
expect(readProjectOgImage("nutriscan")).toBeUndefined();
});
});
describe("OgCard", () => {
const props = { eyebrow: "Case", title: "Título", description: "Resumo." };
it("keeps the plain dark card when there is no background", () => {
const { container } = render(<OgCard {...props} />);
// só a marca
expect(container.querySelectorAll("img")).toHaveLength(1);
});
it("puts the project cover behind the text with a darkening gradient", () => {
const { container } = render(
<OgCard {...props} backgroundImage="data:image/jpeg;base64,AAAA" />,
);
const images = [...container.querySelectorAll("img")];
expect(images).toHaveLength(2);
expect(images[0]).toHaveAttribute("src", "data:image/jpeg;base64,AAAA");
expect(images[0]).toHaveAttribute("alt", "");
expect(container.innerHTML).toContain("linear-gradient");
});
});