67 lines
2.5 KiB
TypeScript
67 lines
2.5 KiB
TypeScript
import { expect, type Locator, test } from "@playwright/test";
|
|
import { CONTACT_HEADING, clientProjectNames, DESKTOP } from "./helpers";
|
|
|
|
/**
|
|
* (e) Com JavaScript desligado, a home mostra o texto do contato e o nome dos clientes: no HTML, visíveis e com
|
|
* opacidade calculada acima de 0,5 (um texto "visível" mas a 0,1 de opacidade, à espera de uma animação que não
|
|
* roda sem JavaScript, não serve a quem lê).
|
|
*/
|
|
|
|
const MIN_OPACITY = 0.5;
|
|
|
|
test.use({ viewport: DESKTOP, javaScriptEnabled: false });
|
|
|
|
/** Opacidade efetiva: o produto das opacidades calculadas do elemento e de todos os seus ancestrais. */
|
|
function effectiveOpacity(locator: Locator) {
|
|
return locator.evaluate((element) => {
|
|
let opacity = 1;
|
|
for (let node: Element | null = element; node; node = node.parentElement)
|
|
opacity *= Number.parseFloat(getComputedStyle(node).opacity);
|
|
return opacity;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Leva o texto ao meio da janela, como quem lê rolando (a passagem entre seções é um fade ligado à rolagem, em CSS
|
|
* puro: antes de a seção chegar à janela o conteúdo espera a 0, e isso não depende de JavaScript) e espera a
|
|
* opacidade passar de MIN_OPACITY: as animações de entrada em CSS levam um instante para terminar.
|
|
*/
|
|
async function expectReadable(locator: Locator, what: string) {
|
|
await locator.evaluate((element) =>
|
|
element.scrollIntoView({ block: "center", behavior: "instant" }),
|
|
);
|
|
await expect
|
|
.poll(() => effectiveOpacity(locator), {
|
|
message: `opacidade de ${what}`,
|
|
timeout: 5_000,
|
|
})
|
|
.toBeGreaterThan(MIN_OPACITY);
|
|
}
|
|
|
|
test("sem JavaScript a home mostra o contato e os nomes dos 5 clientes, legíveis", async ({
|
|
page,
|
|
}) => {
|
|
const clients = clientProjectNames();
|
|
expect(clients, "clientes em public/portfolio-data.json").toHaveLength(5);
|
|
|
|
const response = await page.goto("/", { waitUntil: "load" });
|
|
expect(response?.status()).toBe(200);
|
|
|
|
const heading = page.getByRole("heading", {
|
|
level: 2,
|
|
name: CONTACT_HEADING,
|
|
});
|
|
await expect(heading).toBeVisible();
|
|
await expectReadable(heading, "o texto do contato");
|
|
|
|
for (const name of clients) {
|
|
const text = page.getByText(name, { exact: false }).first();
|
|
await expect(text, `cliente "${name}"`).toBeVisible();
|
|
await expectReadable(text, `o cliente "${name}"`);
|
|
}
|
|
// o texto está no HTML entregue, não só na tela: vale também para quem lê sem renderizar
|
|
const html = await (await page.request.get("/")).text();
|
|
expect(html).toContain(CONTACT_HEADING);
|
|
for (const name of clients) expect(html).toContain(name);
|
|
});
|