Passagens com fade e 32 px, cena anterior termina em opacidade 0, sem visibility nem clip-path. 3D do hero como fundo ambiente, sob demanda e desligado em toque, aparelho fraco, saveData e movimento reduzido. Lenis fora do toque e salto direto em âncoras distantes. Vitrine só de clientes, até 3 capítulos, fixa só no desktop e carrossel no celular; vídeo só do projeto em cena com preload metadata. Rótulos mono a partir de 12 px e limão só no contato.
52 lines
1.3 KiB
TypeScript
52 lines
1.3 KiB
TypeScript
import { render } from "@testing-library/react";
|
|
import HeroFieldScene from "./HeroFieldScene";
|
|
|
|
type CanvasProps = {
|
|
dpr?: [number, number];
|
|
frameloop?: string;
|
|
gl?: Record<string, unknown>;
|
|
};
|
|
const mockCanvas: CanvasProps[] = [];
|
|
|
|
jest.mock("@react-three/fiber", () => ({
|
|
Canvas: (props: CanvasProps) => {
|
|
mockCanvas.push(props);
|
|
return null;
|
|
},
|
|
useFrame: jest.fn(),
|
|
useThree: jest.fn(),
|
|
}));
|
|
|
|
describe("HeroFieldScene (ambient 3D)", () => {
|
|
beforeEach(() => {
|
|
mockCanvas.length = 0;
|
|
});
|
|
|
|
it("draws on demand, never on a fixed 60 fps loop, and caps the pixel ratio at 1.5", () => {
|
|
render(
|
|
<HeroFieldScene
|
|
progressRef={{ current: 0 }}
|
|
visible
|
|
onReady={() => {}}
|
|
onError={() => {}}
|
|
/>,
|
|
);
|
|
const props = mockCanvas.at(-1);
|
|
expect(props?.frameloop).toBe("demand");
|
|
expect(props?.dpr).toEqual([1, 1.5]);
|
|
expect(props?.gl).toMatchObject({ alpha: true, antialias: false });
|
|
});
|
|
|
|
it("keeps the same on-demand loop when the hero is off screen (the pulse is what stops)", () => {
|
|
render(
|
|
<HeroFieldScene
|
|
progressRef={{ current: 0 }}
|
|
visible={false}
|
|
onReady={() => {}}
|
|
onError={() => {}}
|
|
/>,
|
|
);
|
|
expect(mockCanvas.at(-1)?.frameloop).toBe("demand");
|
|
});
|
|
});
|