chore: testes de ponta a ponta no CI e limpeza do repositório
Job e2e separado no CI; testes de teclado, rolagem, sem JS, axe no celular e menu do celular; limites de metadados derivados do sitemap; sai @react-three/fiber e @react-three/drei; pastas de ferramentas (.augment, .kiro, .claude/settings.local.json) fora do Git.
This commit is contained in:
1 parent
6ac87824f3
commit
1a60795107
57 files changed
+625
-12090
No files matched your search
+46
-10
@@ -1,11 +1,44 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
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. */
|
||||
/**
|
||||
* (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 });
|
||||
|
||||
test("sem JavaScript a home mostra o contato e os nomes dos 4 clientes", async ({
|
||||
/** 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 4 clientes, legíveis", async ({
|
||||
page,
|
||||
}) => {
|
||||
const clients = clientProjectNames();
|
||||
@@ -14,14 +47,17 @@ test("sem JavaScript a home mostra o contato e os nomes dos 4 clientes", async (
|
||||
const response = await page.goto("/", { waitUntil: "load" });
|
||||
expect(response?.status()).toBe(200);
|
||||
|
||||
await expect(
|
||||
page.getByRole("heading", { level: 2, name: CONTACT_HEADING }),
|
||||
).toBeVisible();
|
||||
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) {
|
||||
await expect(
|
||||
page.getByText(name, { exact: false }).first(),
|
||||
`cliente "${name}"`,
|
||||
).toBeVisible();
|
||||
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();
|
||||
|
||||
Reference in new issue
Block a user