Files
portifolio-evandrodevbr/app/components/animations/LazyRevealImage.paths.test.tsx
Evandro Fonseca Junior 318a764190 perf(movimento): sem tela vazia, passagens em CSS e vitrine leve
Projetos sobem sobre o palco do hero e o celular tem hero de uma tela sem mergulho; passagens com animation-timeline em CSS, sem GSAP nem motion; troca da vitrine sem texto duplicado; moldura de celular só com pôster e scrub reencodado em 960 px (9,4 para 5,2 MB); 3D monta na primeira interação e para quando parado; transição entre páginas do mesmo segmento; foco em anel duplo; texto de 15 px no celular; código morto removido.
2026-10-14 14:15:50 -03:00

108 lines
3.3 KiB
TypeScript

import { act, render, screen } from "@testing-library/react";
import { LazyRevealImage } from "./LazyRevealImage";
/**
* Testes de caminhos-base de LazyRevealImage (complemento de Reveal.test.tsx): a imagem que ainda carrega, o desenho de baixa resolução só para
* imagem importada e os valores padrão de `sizes` e da classe da imagem.
*/
afterEach(() => {
jest.restoreAllMocks();
});
function mockComplete(complete: boolean, naturalWidth: number) {
jest
.spyOn(HTMLImageElement.prototype, "complete", "get")
.mockReturnValue(complete);
jest
.spyOn(HTMLImageElement.prototype, "naturalWidth", "get")
.mockReturnValue(naturalWidth);
}
async function renderImage(ui: React.ReactElement) {
let view: ReturnType<typeof render> | undefined;
await act(async () => {
view = render(ui);
});
if (!view) throw new Error("render failed");
return view;
}
describe("LazyRevealImage", () => {
it("path: not complete yet -> waits for the load event, then marks it", async () => {
mockComplete(false, 0);
const { container } = await renderImage(
<LazyRevealImage src="/foto.webp" alt="Foto" />,
);
const wrapper = container.firstElementChild as HTMLElement;
expect(wrapper).not.toHaveAttribute("data-loaded");
await act(async () => {
screen.getByAltText("Foto").dispatchEvent(new Event("load"));
});
expect(wrapper).toHaveAttribute("data-loaded");
});
it("path: defaults -> lazy loading, the half-width size hint and the cover class on the image", async () => {
const { container } = await renderImage(
<LazyRevealImage src="/foto.webp" alt="Foto" />,
);
const image = screen.getByAltText("Foto");
expect(image).toHaveAttribute("loading", "lazy");
expect(image).toHaveAttribute("sizes", "(max-width: 1024px) 100vw, 50vw");
expect(image).toHaveClass("object-cover");
expect(container.firstElementChild?.className).toBe(
"ds-lazy-reveal relative",
);
});
it("path: custom sizes and image class -> used instead of the defaults", async () => {
await renderImage(
<LazyRevealImage
src="/foto.webp"
alt="Foto"
sizes="320px"
imageClassName="object-contain"
className="h-40"
/>,
);
const image = screen.getByAltText("Foto");
expect(image).toHaveAttribute("sizes", "320px");
expect(image).toHaveClass("object-contain");
expect(image).not.toHaveClass("object-cover");
});
it("path: an imported image (with a blur) -> the low-resolution preview style is on the image until it loads", async () => {
mockComplete(false, 0);
await renderImage(
<LazyRevealImage
src={{
src: "/importada.png",
width: 40,
height: 20,
blurDataURL: "data:image/png;base64,AAAA",
}}
alt="Importada"
/>,
);
// o jsdom descarta o `background-image` do SVG que o next/image monta, mas o restante do estilo do desfoque fica
expect(screen.getByAltText("Importada").getAttribute("style")).toContain(
"background-size: cover",
);
});
it("path: a path string -> no preview style on the image", async () => {
mockComplete(false, 0);
await renderImage(<LazyRevealImage src="/foto.webp" alt="Foto" />);
expect(
screen.getByAltText("Foto").getAttribute("style") ?? "",
).not.toContain("background-size");
});
});