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:.
This commit is contained in:
1 parent
c9a0b80656
commit
e80f73d075
52 files changed
+2593
-439
No files matched your search
@@ -0,0 +1,85 @@
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import { getShowcaseAssets } from "@/lib/project-showcase";
|
||||
import { CasePlayer } from "./CasePlayer";
|
||||
|
||||
const title = "SEV Moda Íntima";
|
||||
|
||||
describe("CasePlayer", () => {
|
||||
it("shows the poster and an accessible play button instead of a paused video", () => {
|
||||
const { container } = render(
|
||||
<div className="relative">
|
||||
<CasePlayer
|
||||
assets={getShowcaseAssets("sev-modaintima", "desktop")}
|
||||
title={title}
|
||||
device="desktop"
|
||||
/>
|
||||
</div>,
|
||||
);
|
||||
|
||||
expect(container.querySelector("video")).toBeNull();
|
||||
// a imagem é decorativa: o botão já diz o que o quadro mostra
|
||||
const poster = container.querySelector("img");
|
||||
expect(poster).toHaveAttribute("alt", "");
|
||||
expect(poster?.getAttribute("src")).toContain(
|
||||
encodeURIComponent("/videos/sev-modaintima/desktop.webp"),
|
||||
);
|
||||
const button = screen.getByRole("button", {
|
||||
name: `Reproduzir o vídeo do site ${title} no computador`,
|
||||
});
|
||||
expect(button).toHaveAttribute("type", "button");
|
||||
// só botão de contato é limão: o de play é escuro, com contorno branco
|
||||
expect(button.innerHTML).not.toContain("--slash");
|
||||
expect(button.querySelector("[aria-hidden='true']")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("mounts the video with its sources only after the click, muted and looping, with focus on it", () => {
|
||||
const assets = getShowcaseAssets("lavacao-047", "desktop");
|
||||
render(
|
||||
<div className="relative">
|
||||
<CasePlayer assets={assets} title="Lavação 047" device="desktop" />
|
||||
</div>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button"));
|
||||
|
||||
const video = screen.getByLabelText(
|
||||
"Vídeo do site Lavação 047 no computador",
|
||||
);
|
||||
expect(video).toHaveFocus();
|
||||
expect(video).toHaveAttribute("controls");
|
||||
expect(video).toHaveAttribute("poster", assets.poster);
|
||||
expect(video).toHaveAttribute("width", String(assets.width));
|
||||
expect(video).toHaveAttribute("height", String(assets.height));
|
||||
expect((video as HTMLVideoElement).muted).toBe(true);
|
||||
expect((video as HTMLVideoElement).loop).toBe(true);
|
||||
expect(
|
||||
[...video.querySelectorAll("source")].map((source) => [
|
||||
source.getAttribute("src"),
|
||||
source.getAttribute("type"),
|
||||
]),
|
||||
).toEqual(assets.sources.map(({ src, type }) => [src, type]));
|
||||
expect(screen.queryByRole("button")).toBeNull();
|
||||
});
|
||||
|
||||
it("leaves the poster to the phone frame on mobile and names the device in the labels", () => {
|
||||
const { container } = render(
|
||||
<div className="relative">
|
||||
<CasePlayer
|
||||
assets={getShowcaseAssets("sc-plus", "mobile")}
|
||||
title="SC Plus Aquicultura"
|
||||
device="mobile"
|
||||
/>
|
||||
</div>,
|
||||
);
|
||||
|
||||
expect(container.querySelector("img")).toBeNull();
|
||||
fireEvent.click(
|
||||
screen.getByRole("button", {
|
||||
name: "Reproduzir o vídeo do site SC Plus Aquicultura no celular",
|
||||
}),
|
||||
);
|
||||
expect(
|
||||
screen.getByLabelText("Vídeo do site SC Plus Aquicultura no celular"),
|
||||
).toHaveAttribute("poster", "/videos/sc-plus/mobile.webp");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user