perf(movimento): vitrine e 3D mais leves, WebGL por software lembrado na sessão e suporte ao WebKit
This commit is contained in:
1 parent
9fd1570426
commit
8903f3c57e
28 files changed
+854
-406
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import { act, render, screen } from "@testing-library/react";
|
||||
import { rememberSoftwareWebGL } from "@/lib/device";
|
||||
import HeroField, { DIVE_QUERY } from "./HeroField";
|
||||
|
||||
type SceneProps = {
|
||||
@@ -38,18 +39,6 @@ function mockMedia(active: string[] = [DIVE_QUERY]) {
|
||||
}));
|
||||
}
|
||||
|
||||
/** Um WebGL2 que abre, e que diz na extensão de depuração em que renderizador desenha. */
|
||||
function mockWebGLRenderer(renderer: string) {
|
||||
HTMLCanvasElement.prototype.getContext = (() => ({
|
||||
getExtension: (name: string) =>
|
||||
name === "WEBGL_debug_renderer_info"
|
||||
? { UNMASKED_RENDERER_WEBGL: 37446 }
|
||||
: null,
|
||||
getParameter: (parameter: number) =>
|
||||
parameter === 37446 ? renderer : null,
|
||||
})) as unknown as typeof HTMLCanvasElement.prototype.getContext;
|
||||
}
|
||||
|
||||
function mockNavigator(values: Record<string, unknown>) {
|
||||
for (const [key, value] of Object.entries(values))
|
||||
Object.defineProperty(navigator, key, { configurable: true, value });
|
||||
@@ -94,6 +83,7 @@ async function idle() {
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
sessionStorage.clear();
|
||||
mockScenes.length = 0;
|
||||
mockPrepare.mockClear();
|
||||
mockMedia();
|
||||
@@ -111,6 +101,7 @@ beforeEach(() => {
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
sessionStorage.clear();
|
||||
window.matchMedia = original.matchMedia;
|
||||
(window as unknown as Record<string, unknown>).WebGL2RenderingContext =
|
||||
original.webgl2;
|
||||
@@ -129,6 +120,19 @@ describe("HeroField (ambient background)", () => {
|
||||
expect(mockScenes.at(-1)?.visible).toBe(true);
|
||||
});
|
||||
|
||||
it("opens no WebGL context of its own, on hydration or when idle: the only one is the scene's", async () => {
|
||||
const probe = jest.fn(() => ({ getExtension: () => null }));
|
||||
HTMLCanvasElement.prototype.getContext =
|
||||
probe as unknown as typeof HTMLCanvasElement.prototype.getContext;
|
||||
|
||||
render(<Hero />);
|
||||
expect(probe).not.toHaveBeenCalled();
|
||||
await idle();
|
||||
|
||||
expect(probe).not.toHaveBeenCalled();
|
||||
expect(screen.getByTestId("scene")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("brings the geometry in before the Canvas, in a task of its own", async () => {
|
||||
render(<Hero />);
|
||||
|
||||
@@ -183,17 +187,11 @@ describe("HeroField (ambient background)", () => {
|
||||
undefined;
|
||||
},
|
||||
],
|
||||
...[
|
||||
"ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)",
|
||||
"llvmpipe (LLVM 15.0.7, 256 bits)",
|
||||
"ANGLE (Microsoft, Microsoft Basic Render Driver (0x0000008C) Direct3D11 vs_5_0 ps_5_0, D3D11)",
|
||||
].map(
|
||||
(renderer) =>
|
||||
[
|
||||
`software WebGL (${renderer.slice(0, 24)}...)`,
|
||||
() => mockWebGLRenderer(renderer),
|
||||
] as [string, () => void],
|
||||
),
|
||||
// o veredito vem do contexto da cena (HeroFieldScene), que o anota na sessão; a página seguinte já nasce estática
|
||||
[
|
||||
"a software WebGL found earlier in the session",
|
||||
() => rememberSoftwareWebGL(),
|
||||
],
|
||||
])(
|
||||
"keeps the light static background (no WebGL, no dive, no scroll work) with %s",
|
||||
async (_label, arrange) => {
|
||||
|
||||
Reference in new issue
Block a user