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.
122 lines
4.8 KiB
TypeScript
122 lines
4.8 KiB
TypeScript
import { render, screen, within } from "@testing-library/react";
|
|
import HeroWork from "./HeroWork";
|
|
|
|
/**
|
|
* Os pôsteres do hero: pelo next/image com `sizes` do tamanho em que aparecem, sempre lazy e com prioridade baixa
|
|
* (o título é o LCP), e o cartão largo e clicável da SEV para as telas abaixo de 1024 px.
|
|
*/
|
|
|
|
const original = (image: Element) =>
|
|
new URL(image.getAttribute("src") ?? "", "http://localhost").searchParams.get(
|
|
"url",
|
|
);
|
|
|
|
describe("HeroWork: pôsteres no tamanho certo", () => {
|
|
it("serves the three posters through the image optimizer, each with a `sizes` that matches how it shows", () => {
|
|
render(<HeroWork />);
|
|
|
|
const desktop = within(screen.getByTestId("hero-work")).getAllByRole("img");
|
|
expect(desktop).toHaveLength(2);
|
|
expect(original(desktop[0])).toBe("/videos/sev-modaintima/desktop.webp");
|
|
expect(original(desktop[1])).toBe("/videos/as-servicos/mobile.webp");
|
|
// 1440x900 e 390x844 cheios para quadros de ~491x307 e ~130x299 era banda de sobra
|
|
expect(desktop[0]).toHaveAttribute(
|
|
"sizes",
|
|
"(min-width: 1400px) 500px, 36vw",
|
|
);
|
|
expect(desktop[1]).toHaveAttribute(
|
|
"sizes",
|
|
"(min-width: 1400px) 136px, 10vw",
|
|
);
|
|
|
|
// o cartão do celular usa o pôster largo da SEV, na largura da coluna (cerca de 350 px num celular de 390 px)
|
|
const small = screen
|
|
.getByTestId("hero-work-mobile")
|
|
.querySelector("img") as HTMLImageElement;
|
|
expect(original(small)).toBe("/videos/sev-modaintima/desktop.webp");
|
|
expect(small).toHaveAttribute("sizes", "(min-width: 1024px) 1px, 100vw");
|
|
});
|
|
|
|
it("keeps the dimensions of the files, so the frames reserve their space before the images load", () => {
|
|
render(<HeroWork />);
|
|
|
|
const [browser, phone] = within(
|
|
screen.getByTestId("hero-work"),
|
|
).getAllByRole("img");
|
|
expect(browser).toHaveAttribute("width", "1440");
|
|
expect(browser).toHaveAttribute("height", "900");
|
|
expect(phone).toHaveAttribute("width", "390");
|
|
expect(phone).toHaveAttribute("height", "844");
|
|
});
|
|
|
|
it("never asks for a high priority: lazy, low fetch priority and no preload, so the headline stays the LCP", () => {
|
|
const { container } = render(<HeroWork />);
|
|
|
|
const images = container.querySelectorAll("img");
|
|
expect(images).toHaveLength(3);
|
|
for (const image of images) {
|
|
expect(image).toHaveAttribute("loading", "lazy");
|
|
expect(image).toHaveAttribute("fetchpriority", "low");
|
|
}
|
|
// sem <link rel="preload">: o next/image só o insere com `preload` (ou fetchPriority="high")
|
|
expect(document.head.querySelector('link[rel="preload"]')).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("HeroWork: cartão do celular", () => {
|
|
it("shows a wide card with the SEV poster only below 1024px, while the column stays desktop-only", () => {
|
|
render(<HeroWork />);
|
|
|
|
const column = screen.getByTestId("hero-work");
|
|
expect(column).toHaveClass("hidden", "lg:block");
|
|
|
|
const card = screen.getByTestId("hero-work-mobile");
|
|
expect(card).toHaveClass("lg:hidden", "w-full");
|
|
// sem a moldura de celular de 65x160 px: a imagem é larga e ocupa a coluna inteira
|
|
expect(card.querySelector(".ds-phone")).toBeNull();
|
|
const imageBox = card.querySelector("img")?.parentElement as HTMLElement;
|
|
expect(imageBox).toHaveClass("w-full");
|
|
expect(imageBox.style.height).toBe("72px");
|
|
expect(card).toHaveTextContent("Site da SEV Moda Íntima");
|
|
expect(card).toHaveTextContent("Ver case");
|
|
});
|
|
|
|
it("is a link to the SEV case, with a touch target of at least 48px and its own focus ring", () => {
|
|
render(<HeroWork />);
|
|
|
|
const card = screen.getByRole("link", {
|
|
name: "Site da SEV Moda Íntima Ver case",
|
|
});
|
|
expect(card).toBe(screen.getByTestId("hero-work-mobile"));
|
|
expect(card).toHaveAttribute("href", "/cases/sev-modaintima");
|
|
expect(card).not.toHaveClass("pointer-events-none");
|
|
expect(card.className).toContain("focus-visible:outline-2");
|
|
expect(card.querySelector("span.min-h-12")).not.toBeNull();
|
|
// a imagem é decorativa: o texto do link já diz o que ela mostra
|
|
expect(card.querySelector("img")).toHaveAttribute("alt", "");
|
|
});
|
|
|
|
it("draws no other link: the card is the only one in HeroWork", () => {
|
|
render(<HeroWork />);
|
|
|
|
expect(screen.getAllByRole("link")).toHaveLength(1);
|
|
});
|
|
|
|
it("keeps the desktop column as a plain picture: not interactive, nothing to click", () => {
|
|
render(<HeroWork />);
|
|
|
|
expect(screen.getByTestId("hero-work")).toHaveClass("pointer-events-none");
|
|
expect(
|
|
within(screen.getByTestId("hero-work")).queryByRole("link"),
|
|
).toBeNull();
|
|
});
|
|
|
|
it("passes the address to the browser bar of the desktop frame", () => {
|
|
render(<HeroWork url={{ text: "sevmodaintima.com.br", secure: true }} />);
|
|
|
|
expect(
|
|
within(screen.getByTestId("hero-work")).getByText("sevmodaintima.com.br"),
|
|
).toBeInTheDocument();
|
|
});
|
|
});
|