CI / verify (push) Failing after 5m29s
Estado do disco em 14/10/2026, sem filtrar. Inclui as copias .sync-conflict-* do Syncthing de 07/10 e os 15 arquivos que o Syncthing apagou; todo esse conteudo ja existia em outros commits. So havia fora do Git: AGENTS.md, CLAUDE.md e a alteracao em data/project-health.json.
104 lines
3.5 KiB
TypeScript
104 lines
3.5 KiB
TypeScript
import { act, fireEvent, render, screen } from "@testing-library/react";
|
|
import { useHomeFragmentNavigation } from "./useHomeFragmentNavigation";
|
|
|
|
function HomeNavigation() {
|
|
const onLayoutReady = useHomeFragmentNavigation();
|
|
return (
|
|
<>
|
|
<button type="button" onClick={onLayoutReady}>
|
|
Establish notebook layout
|
|
</button>
|
|
<a href="/#about">Sobre</a>
|
|
<a href="/#contact">Contato</a>
|
|
<section id="about" aria-label="Sobre">
|
|
<button type="button">Read biography</button>
|
|
</section>
|
|
<section id="contact" aria-label="Contato">
|
|
<button type="button">Send message</button>
|
|
</section>
|
|
</>
|
|
);
|
|
}
|
|
|
|
const originalScrollIntoView = HTMLElement.prototype.scrollIntoView;
|
|
|
|
beforeEach(() => {
|
|
window.history.replaceState(null, "", "/");
|
|
HTMLElement.prototype.scrollIntoView = jest.fn();
|
|
});
|
|
|
|
afterEach(() => {
|
|
window.history.replaceState(null, "", "/");
|
|
if (originalScrollIntoView) {
|
|
HTMLElement.prototype.scrollIntoView = originalScrollIntoView;
|
|
} else {
|
|
Reflect.deleteProperty(HTMLElement.prototype, "scrollIntoView");
|
|
}
|
|
});
|
|
|
|
describe("home fragment navigation", () => {
|
|
it("waits for the notebook layout on fragment arrival, then never steals focus on refresh", () => {
|
|
window.history.replaceState(null, "", "/#contact");
|
|
render(<HomeNavigation />);
|
|
const contact = screen.getByRole("region", { name: "Contato" });
|
|
expect(contact).not.toHaveFocus();
|
|
|
|
fireEvent.click(
|
|
screen.getByRole("button", { name: "Establish notebook layout" }),
|
|
);
|
|
expect(contact).toHaveFocus();
|
|
screen.getByRole("button", { name: "Read biography" }).focus();
|
|
fireEvent.click(
|
|
screen.getByRole("button", { name: "Establish notebook layout" }),
|
|
);
|
|
expect(
|
|
screen.getByRole("button", { name: "Read biography" }),
|
|
).toHaveFocus();
|
|
});
|
|
|
|
it("abandons a pending arrival when the visitor intentionally scrolls", () => {
|
|
window.history.replaceState(null, "", "/#about");
|
|
render(<HomeNavigation />);
|
|
const message = screen.getByRole("button", { name: "Send message" });
|
|
message.focus();
|
|
fireEvent.wheel(window, { deltaY: 200 });
|
|
fireEvent.click(
|
|
screen.getByRole("button", { name: "Establish notebook layout" }),
|
|
);
|
|
expect(message).toHaveFocus();
|
|
});
|
|
|
|
it("keeps repeated same-fragment links native while moving focus to the destination", () => {
|
|
window.history.replaceState(null, "", "/#about");
|
|
render(<HomeNavigation />);
|
|
fireEvent.click(
|
|
screen.getByRole("button", { name: "Establish notebook layout" }),
|
|
);
|
|
const link = screen.getByRole("link", { name: "Sobre" });
|
|
link.focus();
|
|
expect(fireEvent.click(link)).toBe(true);
|
|
expect(screen.getByRole("region", { name: "Sobre" })).toHaveFocus();
|
|
link.focus();
|
|
expect(fireEvent.click(link)).toBe(true);
|
|
expect(screen.getByRole("region", { name: "Sobre" })).toHaveFocus();
|
|
link.focus();
|
|
fireEvent.click(link, { ctrlKey: true });
|
|
expect(link).toHaveFocus();
|
|
});
|
|
|
|
it("does not resurrect a stale fragment when the URL changes before readiness", () => {
|
|
window.history.replaceState(null, "", "/#about");
|
|
render(<HomeNavigation />);
|
|
const message = screen.getByRole("button", { name: "Send message" });
|
|
message.focus();
|
|
act(() => {
|
|
window.history.replaceState(null, "", "/#contact");
|
|
window.dispatchEvent(new HashChangeEvent("hashchange"));
|
|
});
|
|
fireEvent.click(
|
|
screen.getByRole("button", { name: "Establish notebook layout" }),
|
|
);
|
|
expect(message).toHaveFocus();
|
|
});
|
|
});
|