test: e2e mais rígida e .gitattributes
Zero telas sem texto no computador e no celular; atalho de teclado em até 4 Tabs e linear em até 36 com o inventário das paradas; ciclo de foco do menu com a barra de cookies; oferta e cabeçalho levando ao formulário; foco vindo de outra página; separador da faixa de clientes; contagem de pôsteres da SEV. .gitattributes com eol=lf.
This commit is contained in:
1 parent
204ebd5fa5
commit
2cd4a98c55
10 files changed
+588
-87
No files matched your search
@@ -0,0 +1,123 @@
|
||||
import { expect, type Page, test } from "@playwright/test";
|
||||
import { clientProjectNames } from "./helpers";
|
||||
|
||||
/**
|
||||
* (i) Faixa "Já entregue para" do hero (ClientStrip), em larguras de celular a computador: o ponto separador (·) só
|
||||
* aparece ENTRE itens da mesma linha. O ponto abre cada item (menos o primeiro) e a margem negativa o esconde, pelo
|
||||
* `overflow-x: clip` da lista, quando o item abre uma linha nova. Então, para cada item depois do primeiro:
|
||||
* ponto visível <=> o item está na mesma linha do anterior.
|
||||
* Nenhuma linha começa nem termina com "·". O Jest só confere as classes; só o navegador mostra o corte.
|
||||
* "Visível" = o centro do ponto está dentro da caixa da lista (o que o corte deixa passar).
|
||||
*/
|
||||
|
||||
const WIDTHS = [320, 360, 390, 430, 560, 768, 1024, 1440];
|
||||
|
||||
async function stripItems(page: Page) {
|
||||
return page.evaluate(() => {
|
||||
const label = Array.from(document.querySelectorAll("p")).find(
|
||||
(paragraph) => paragraph.textContent?.trim() === "Já entregue para:",
|
||||
);
|
||||
const list = label?.parentElement?.querySelector("ul");
|
||||
if (!list) return null;
|
||||
const listBox = list.getBoundingClientRect();
|
||||
const items = Array.from(list.querySelectorAll("li")).map((item) => {
|
||||
const dot = item.querySelector("[aria-hidden='true']");
|
||||
const dotBox = dot?.getBoundingClientRect();
|
||||
return {
|
||||
text: (item.textContent ?? "").replace(/\s+/g, " ").trim(),
|
||||
// o centro vertical: um item mais baixo (os anos) fica centrado na linha e tem outro topo
|
||||
center: Math.round(
|
||||
item.getBoundingClientRect().top +
|
||||
item.getBoundingClientRect().height / 2,
|
||||
),
|
||||
hasDot: Boolean(dot),
|
||||
dotCenter: dotBox ? dotBox.left + dotBox.width / 2 : null,
|
||||
};
|
||||
});
|
||||
return {
|
||||
items,
|
||||
listLeft: listBox.left,
|
||||
listRight: listBox.right,
|
||||
overflowX: getComputedStyle(list).overflowX,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/** Confere a regra "ponto visível <=> mesma linha do anterior" na faixa como ela está agora. Devolve quantas quebras há. */
|
||||
async function expectDotsOnlyBetweenItemsOfOneLine(page: Page, where: string) {
|
||||
const strip = await stripItems(page);
|
||||
expect(strip, `${where}: a faixa 'Já entregue para:' no hero`).not.toBeNull();
|
||||
if (!strip) return 0;
|
||||
const { items, listLeft, listRight, overflowX } = strip;
|
||||
// 4 clientes + os anos de experiência
|
||||
expect(items.length, `${where}: itens da faixa`).toBeGreaterThanOrEqual(
|
||||
clientProjectNames().length,
|
||||
);
|
||||
expect(overflowX, `${where}: o corte do ponto depende de overflow-x`).toBe(
|
||||
"clip",
|
||||
);
|
||||
expect(items[0].hasDot, `${where}: o primeiro item não tem ponto`).toBe(
|
||||
false,
|
||||
);
|
||||
|
||||
const report = items
|
||||
.map(
|
||||
(item) =>
|
||||
`${item.center}px ${item.hasDot ? `ponto em ${Math.round(item.dotCenter ?? 0)}` : "sem ponto"} "${item.text}"`,
|
||||
)
|
||||
.join("\n");
|
||||
let wraps = 0;
|
||||
for (let index = 1; index < items.length; index++) {
|
||||
const item = items[index];
|
||||
const sameLine = Math.abs(item.center - items[index - 1].center) < 12;
|
||||
if (!sameLine) wraps += 1;
|
||||
const visible =
|
||||
item.dotCenter !== null &&
|
||||
item.dotCenter >= listLeft &&
|
||||
item.dotCenter <= listRight;
|
||||
expect(
|
||||
visible,
|
||||
`${where}, "${item.text}": ${sameLine ? "na mesma linha do anterior, o ponto precisa aparecer" : "abre uma linha nova, o ponto precisa ficar escondido"} (lista de ${Math.round(listLeft)} a ${Math.round(listRight)}px)\n${report}`,
|
||||
).toBe(sameLine);
|
||||
}
|
||||
return wraps;
|
||||
}
|
||||
|
||||
for (const width of WIDTHS) {
|
||||
test(`faixa de clientes a ${width}px: o ponto só aparece entre itens da mesma linha`, async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
await page.goto("/", { waitUntil: "load" });
|
||||
await page.waitForTimeout(800);
|
||||
|
||||
await expectDotsOnlyBetweenItemsOfOneLine(page, `${width}px`);
|
||||
});
|
||||
}
|
||||
|
||||
test("faixa de clientes em colunas estreitas (quebra forçada): nenhuma linha começa nem termina com o ponto", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.setViewportSize({ width: 1440, height: 900 });
|
||||
await page.goto("/", { waitUntil: "load" });
|
||||
await page.waitForTimeout(800);
|
||||
|
||||
let wrappedAtLeastOnce = false;
|
||||
for (const columnWidth of [140, 200, 260, 320, 380, 440, 520, 600]) {
|
||||
await page.evaluate((px) => {
|
||||
const label = Array.from(document.querySelectorAll("p")).find(
|
||||
(paragraph) => paragraph.textContent?.trim() === "Já entregue para:",
|
||||
);
|
||||
const wrapper = label?.parentElement;
|
||||
if (wrapper) wrapper.style.maxWidth = `${px}px`;
|
||||
}, columnWidth);
|
||||
const wraps = await expectDotsOnlyBetweenItemsOfOneLine(
|
||||
page,
|
||||
`coluna de ${columnWidth}px`,
|
||||
);
|
||||
if (wraps > 0) wrappedAtLeastOnce = true;
|
||||
}
|
||||
expect(wrappedAtLeastOnce, "alguma largura quebrou a faixa em linhas").toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user