fix(home): oferta leva ao formulário, ofertas logo depois da vitrine

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.
This commit is contained in:
Evandro Fonseca Junior committed 2026-10-14 19:14:47 -03:00
1 parent fc44a69fb3
commit 9e2d65a926
51 files changed
+1730 -420

No files matched your search

+24 -8
View File
@@ -325,11 +325,15 @@ describe("Header: Esc e foco com o menu aberto", () => {
});
describe("Header: a barra de cookies aberta entra na armadilha de foco", () => {
/** Como no layout: a barra vem antes do cabeçalho e não fica inerte. */
/** Como no layout (GoogleAnalytics.tsx): a barra vem antes do cabeçalho e não fica inerte; link da política, Aceitar e Recusar. */
function PageWithCookieBar() {
return (
<>
<section id={COOKIE_BAR_ID} role="dialog" aria-label="Cookies">
<p>
Usamos métricas de navegação do Google só se você permitir.{" "}
<a href="/privacidade">Política de privacidade</a>
</p>
<button type="button">Aceitar</button>
<button type="button">Recusar</button>
</section>
@@ -338,31 +342,43 @@ describe("Header: a barra de cookies aberta entra na armadilha de foco", () => {
);
}
it("cycles through Aceitar and Recusar before the header, and back from the contact button", () => {
it("cycles through the policy link, Aceitar and Recusar before the header, and back from the contact button", () => {
render(<PageWithCookieBar />);
openMenu();
const policy = screen.getByRole("link", {
name: "Política de privacidade",
});
const accept = screen.getByRole("button", { name: "Aceitar" });
const decline = screen.getByRole("button", { name: "Recusar" });
const order = trapOrder();
const last = order[order.length - 1];
expect(policy).not.toHaveAttribute("inert");
expect(accept).not.toHaveAttribute("inert");
// do botão de contato (o último do cabeçalho) o Tab vai para Aceitar, em vez de dar a volta no cabeçalho
// do botão de contato (o último do cabeçalho) o Tab vai para o link da política, em vez de dar a volta no cabeçalho
act(() => last.focus());
expect(fireEvent.keyDown(last, { key: "Tab" })).toBe(false);
expect(accept).toHaveFocus();
expect(policy).toHaveFocus();
// entre Aceitar e Recusar o Tab segue normal; de Recusar vai para o logo, o primeiro do cabeçalho
// entre o link, Aceitar e Recusar o Tab segue normal; de Recusar vai para o logo, o primeiro do cabeçalho
expect(fireEvent.keyDown(policy, { key: "Tab" })).toBe(true);
act(() => accept.focus());
expect(fireEvent.keyDown(accept, { key: "Tab" })).toBe(true);
act(() => decline.focus());
expect(fireEvent.keyDown(decline, { key: "Tab" })).toBe(true);
// Shift+Tab de Aceitar (o primeiro do ciclo) volta ao botão de contato
act(() => accept.focus());
expect(fireEvent.keyDown(accept, { key: "Tab", shiftKey: true })).toBe(
// Shift+Tab do link da política (o primeiro do ciclo) volta ao botão de contato
act(() => policy.focus());
expect(fireEvent.keyDown(policy, { key: "Tab", shiftKey: true })).toBe(
false,
);
expect(last).toHaveFocus();
// e Shift+Tab de Aceitar ou de Recusar não é preso: o navegador anda um controle para trás
act(() => accept.focus());
expect(fireEvent.keyDown(accept, { key: "Tab", shiftKey: true })).toBe(
true,
);
});
it("closes with Escape and puts the focus back on the menu button, even from the cookie bar", () => {