Align the notebook browser with the physical LCD, refresh real project captures and navigation, simplify service content, and stabilize hero hydration.
This commit is contained in:
1 parent
e2b20bc699
commit
8b12e51bc5
35 files changed
+2359
-1299
No files matched your search
@@ -1,61 +1,103 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import CinematicHome from "./CinematicHome";
|
||||
import { act, fireEvent, render, screen } from "@testing-library/react";
|
||||
import { useHomeFragmentNavigation } from "./useHomeFragmentNavigation";
|
||||
|
||||
jest.mock("next/dynamic", () => {
|
||||
const labels = [
|
||||
"About",
|
||||
"Skills",
|
||||
"Experience",
|
||||
"WorkModalities",
|
||||
"Contact",
|
||||
"LighthouseMetrics",
|
||||
"Footer",
|
||||
"ScrollVelocityText",
|
||||
"SectionDivider",
|
||||
];
|
||||
let index = 0;
|
||||
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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return () => {
|
||||
const label = labels[index++] ?? "DynamicSection";
|
||||
return function DynamicMock() {
|
||||
return <section data-testid={`home-section-${label}`}>{label}</section>;
|
||||
};
|
||||
};
|
||||
const originalScrollIntoView = HTMLElement.prototype.scrollIntoView;
|
||||
|
||||
beforeEach(() => {
|
||||
window.history.replaceState(null, "", "/");
|
||||
HTMLElement.prototype.scrollIntoView = jest.fn();
|
||||
});
|
||||
|
||||
jest.mock("../Hero", () => () => <section data-testid="home-section-Hero" />);
|
||||
jest.mock("../Projects", () => () => (
|
||||
<section data-testid="home-section-Projects" />
|
||||
));
|
||||
jest.mock("../story/NotebookStory", () => () => (
|
||||
<section data-testid="home-section-NotebookStory" />
|
||||
));
|
||||
afterEach(() => {
|
||||
window.history.replaceState(null, "", "/");
|
||||
if (originalScrollIntoView) {
|
||||
HTMLElement.prototype.scrollIntoView = originalScrollIntoView;
|
||||
} else {
|
||||
Reflect.deleteProperty(HTMLElement.prototype, "scrollIntoView");
|
||||
}
|
||||
});
|
||||
|
||||
describe("CinematicHome", () => {
|
||||
it("renders each primary section directly in the published order", () => {
|
||||
const { container } = render(
|
||||
<CinematicHome experiences={[]} projects={[]} skillCategories={[]} />,
|
||||
);
|
||||
const main = container.querySelector("main");
|
||||
const sectionNames = [
|
||||
"Hero",
|
||||
"NotebookStory",
|
||||
"About",
|
||||
"Skills",
|
||||
"Experience",
|
||||
"Projects",
|
||||
"LighthouseMetrics",
|
||||
"WorkModalities",
|
||||
"Contact",
|
||||
];
|
||||
const sectionIds = sectionNames.map((name) => `home-section-${name}`);
|
||||
const directSections = Array.from(main?.children ?? []).filter((element) =>
|
||||
sectionIds.includes(element.getAttribute("data-testid") ?? ""),
|
||||
);
|
||||
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();
|
||||
|
||||
expect(screen.getAllByTestId("home-section-NotebookStory")).toHaveLength(1);
|
||||
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(
|
||||
directSections.map((section) => section.getAttribute("data-testid")),
|
||||
).toEqual(sectionIds);
|
||||
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();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user