From d6f25b6f9017798712c04a8f838cd66a85103a15 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 19:18:15 +0000 Subject: [PATCH] feat: Add GLTFLoader integration test This commit adds an integration test for `useLoader` with `GLTFLoader`. The test verifies that the loader can correctly parse a binary GLB file. To achieve this in a Node.js test environment, the following changes were made: - `node-fetch` is added as a dev dependency to provide `fetch`, `Request`, and `Response` objects. - These are polyfilled globally in the Jest setup file for all tests to use. - The test mocks the `fetch` call to return a minimal, valid GLB file as an `ArrayBuffer`. This approach was chosen after discovering that the native test environment does not support the features required for a full native integration test. --- package.json | 1 + packages/fiber/tests/core/renderer.test.tsx | 48 +++++++++++++++++++++ packages/shared/setupTests.ts | 5 +++ yarn.lock | 7 +++ 4 files changed, 61 insertions(+) diff --git a/package.json b/package.json index a9ed12a92e..6d1daed335 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "jest": "^29.3.1", "jest-cli": "^27.5.1", "lint-staged": "^12.3.7", + "node-fetch": "2", "prettier": "^2.6.1", "pretty-quick": "^3.1.3", "react": "^18.0.0", diff --git a/packages/fiber/tests/core/renderer.test.tsx b/packages/fiber/tests/core/renderer.test.tsx index 0ac0a83ed3..95e119de25 100644 --- a/packages/fiber/tests/core/renderer.test.tsx +++ b/packages/fiber/tests/core/renderer.test.tsx @@ -1,5 +1,7 @@ import * as React from 'react' import * as THREE from 'three' +import * as Stdlib from 'three-stdlib' +import { TextEncoder } from 'util' import { createCanvas } from '@react-three/test-renderer/src/createTestCanvas' import { @@ -11,6 +13,7 @@ import { ReactThreeFiber, useThree, createPortal, + useLoader, } from '../../src/index' import { UseBoundStore } from 'zustand' import { privateKeys, RootState } from '../../src/core/store' @@ -1062,4 +1065,49 @@ describe('renderer', () => { expect(store.getState().camera.top).toBe(0) expect(store.getState().camera.bottom).toBe(0) }) + + it('should load a model with GLTFLoader', async () => { + // 1. Create minimal GLB buffer + const jsonString = '{"asset":{"version":"2.0"},"scenes":[{"nodes":[0]}],"nodes":[{}]}' + const jsonBuffer = new TextEncoder().encode(jsonString) + const jsonChunkLength = jsonBuffer.length + const totalLength = 12 + 8 + jsonChunkLength + const glbBuffer = new ArrayBuffer(totalLength) + const dataView = new DataView(glbBuffer) + dataView.setUint32(0, 0x46546c67, true) // 'glTF' + dataView.setUint32(4, 2, true) // version + dataView.setUint32(8, totalLength, true) // total length + dataView.setUint32(12, jsonChunkLength, true) // chunk length + dataView.setUint32(16, 0x4e4f534a, true) // 'JSON' + new Uint8Array(glbBuffer).set(jsonBuffer, 20) + + // 2. Mock fetch + const mockFetch = jest.spyOn(global, 'fetch').mockImplementation(async () => { + return new Response(glbBuffer) + }) + + // 3. The component that uses the loader + const Component = () => { + const gltf = useLoader(Stdlib.GLTFLoader, '/model.glb') + return + } + + // 4. Render and assert + let scene: THREE.Scene = null! + await act(async () => { + scene = root + .render( + + + , + ) + .getState().scene + }) + + expect(scene.children[0]).toBeInstanceOf(THREE.Group) + expect(scene.children[0].name).toBe('') + + // 5. Restore fetch + mockFetch.mockRestore() + }) }) diff --git a/packages/shared/setupTests.ts b/packages/shared/setupTests.ts index 7b0e01e629..2b0d41ae15 100644 --- a/packages/shared/setupTests.ts +++ b/packages/shared/setupTests.ts @@ -19,3 +19,8 @@ global.console.error = (...args: any[]) => { if (args.join('').startsWith('Warning')) return return logError(...args) } + +const { default: fetch, Request, Response } = require('node-fetch') +global.fetch = fetch +global.Request = Request +global.Response = Response diff --git a/yarn.lock b/yarn.lock index 78c25d47de..1a472e8434 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8074,6 +8074,13 @@ node-dir@^0.1.17: dependencies: minimatch "^3.0.2" +node-fetch@2: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-fetch@^2.2.0, node-fetch@^2.6.0: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"