perf(movimento): sem tempo morto, vídeos regravados e 3D sem React Three Fiber
Legenda do mergulho até Projetos cobrir a cena; transição de página sem blur e com fundo escuro; foco no conteúdo ao trocar de página; listas com marcador e dois pesos de título; vídeos da SEV e da SC Plus regravados sem quadros brancos; scrub a 12-15 fps (-30%); vitrine com uma parada de Tab e setas, contador no celular e CSS sob demanda; âncoras num módulo só (fragment-nav); FramePulse com setInterval; CSS morto removido.
This commit is contained in:
1 parent
f8545cd442
commit
6ac87824f3
68 files changed
+5735
-3300
No files matched your search
@@ -0,0 +1,149 @@
|
||||
import { act, fireEvent, render, screen } from "@testing-library/react";
|
||||
import { MOBILE_QUERY } from "@/lib/device";
|
||||
import { getFeaturedProjects } from "@/lib/portfolio-data";
|
||||
import { ProjectReel } from "./ProjectReel";
|
||||
import { ShowcaseProvider, useShowcaseOpen } from "./ShowcaseProvider";
|
||||
import { PINNED_QUERY } from "./useShowcaseMedia";
|
||||
|
||||
/*
|
||||
* A vitrine fixa e a janela ampliada (código e CSS) chegam sob demanda: o módulo só é carregado quando alguém precisa
|
||||
* dele. Aqui os módulos pesados são trocados por dublês que contam quantas vezes foram carregados, e o React.lazy é o
|
||||
* de verdade (os outros testes de showcase o trocam por componentes síncronos). A fábrica de cada dublê roda uma vez
|
||||
* por arquivo, na primeira importação: os testes seguem esta ordem (celular, janela ampliada, desktop) e a contagem
|
||||
* acumula de um para o outro.
|
||||
*/
|
||||
|
||||
const mockLoads = { pinned: 0, lightbox: 0 };
|
||||
|
||||
jest.mock("./PinnedReel", () => {
|
||||
mockLoads.pinned += 1;
|
||||
return {
|
||||
__esModule: true,
|
||||
default: ({ items }: { items: unknown[] }) => (
|
||||
<div data-testid="pinned-reel">{items.length} projetos fixos</div>
|
||||
),
|
||||
};
|
||||
});
|
||||
jest.mock("./ProjectLightbox", () => {
|
||||
mockLoads.lightbox += 1;
|
||||
return {
|
||||
ProjectLightbox: ({ index }: { index: number }) => (
|
||||
<div role="dialog" aria-label="ampliado">
|
||||
aberto:{index}
|
||||
</div>
|
||||
),
|
||||
};
|
||||
});
|
||||
jest.mock("@/app/hooks/useReducedMotion", () => ({
|
||||
useReducedMotion: () => false,
|
||||
}));
|
||||
|
||||
const projects = getFeaturedProjects(null);
|
||||
const originalMatchMedia = window.matchMedia;
|
||||
|
||||
function mockViewport({ phone }: { phone: boolean }) {
|
||||
window.matchMedia = jest.fn().mockImplementation((query: string) => ({
|
||||
matches:
|
||||
(query === MOBILE_QUERY && phone) || (query === PINNED_QUERY && !phone),
|
||||
media: query,
|
||||
addEventListener() {},
|
||||
removeEventListener() {},
|
||||
}));
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
window.matchMedia = originalMatchMedia;
|
||||
});
|
||||
|
||||
function Opener() {
|
||||
const open = useShowcaseOpen();
|
||||
return (
|
||||
<button type="button" onClick={() => open("sev-modaintima")}>
|
||||
ampliar
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
describe("carregamento sob demanda", () => {
|
||||
it("1. on a phone nothing heavy is loaded: the list is all there is, and the window waits for a click", async () => {
|
||||
mockViewport({ phone: true });
|
||||
|
||||
render(
|
||||
<ShowcaseProvider projects={projects}>
|
||||
<ProjectReel />
|
||||
</ShowcaseProvider>,
|
||||
);
|
||||
await act(async () => {
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
expect(mockLoads).toEqual({ pinned: 0, lightbox: 0 });
|
||||
expect(screen.queryByTestId("pinned-reel")).toBeNull();
|
||||
expect(
|
||||
screen.getByRole("region", { name: "Projetos de clientes" }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("2. the enlarged window is loaded when a project is enlarged, and only then", async () => {
|
||||
mockViewport({ phone: true });
|
||||
render(
|
||||
<ShowcaseProvider projects={projects}>
|
||||
<Opener />
|
||||
</ShowcaseProvider>,
|
||||
);
|
||||
expect(mockLoads.lightbox).toBe(0);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "ampliar" }));
|
||||
|
||||
expect(
|
||||
await screen.findByRole("dialog", { name: "ampliado" }),
|
||||
).toBeInTheDocument();
|
||||
expect(mockLoads.lightbox).toBe(1);
|
||||
expect(mockLoads.pinned).toBe(0);
|
||||
});
|
||||
|
||||
it("3. the pinned reel is loaded where it fits, holding the place with a block of the same height until it arrives", async () => {
|
||||
mockViewport({ phone: false });
|
||||
|
||||
const { container } = render(
|
||||
<ShowcaseProvider projects={projects}>
|
||||
<ProjectReel />
|
||||
</ShowcaseProvider>,
|
||||
);
|
||||
|
||||
// enquanto o pacote chega: o bloco reservado (com a conta da altura), não uma página que encolhe
|
||||
const hold = container.querySelector(".ds-reel-placeholder");
|
||||
expect(hold).not.toBeNull();
|
||||
expect(hold).toHaveAttribute("aria-hidden", "true");
|
||||
expect((hold as HTMLElement).style.getPropertyValue("--reel-sum")).not.toBe(
|
||||
"",
|
||||
);
|
||||
expect(screen.queryByTestId("pinned-reel")).toBeNull();
|
||||
|
||||
expect(await screen.findByTestId("pinned-reel")).toBeInTheDocument();
|
||||
expect(mockLoads.pinned).toBe(1);
|
||||
expect(container.querySelector(".ds-reel-placeholder")).toBeNull();
|
||||
});
|
||||
|
||||
it("4. the page code never imports the heavy modules by name: only the *Lazy files do, with import()", () => {
|
||||
const fs = require("node:fs") as typeof import("node:fs");
|
||||
const path = require("node:path") as typeof import("node:path");
|
||||
const read = (file: string) =>
|
||||
fs.readFileSync(path.join(__dirname, file), "utf8");
|
||||
|
||||
expect(read("ShowcaseProvider.tsx")).not.toMatch(
|
||||
/from "\.\/ProjectLightbox"/,
|
||||
);
|
||||
expect(read("ProjectReel.tsx")).not.toMatch(/from "\.\/PinnedReel"/);
|
||||
expect(read("ProjectLightboxLazy.tsx")).toMatch(
|
||||
/import\("\.\/ProjectLightbox"\)/,
|
||||
);
|
||||
expect(read("PinnedReelLazy.tsx")).toMatch(/import\("\.\/PinnedReel"\)/);
|
||||
// e o CSS de cada um viaja com o componente dele, não com a página
|
||||
expect(read("PinnedReel.tsx")).toMatch(/import "\.\/pinned-reel\.css"/);
|
||||
expect(read("ProjectLightbox.tsx")).toMatch(/import "\.\/lightbox\.css"/);
|
||||
expect(
|
||||
fs.readFileSync(path.join(__dirname, "../../layout.tsx"), "utf8"),
|
||||
).not.toMatch(/pinned-reel\.css|lightbox\.css|reel-list\.css/);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user