import { MeshPhongMaterial, Texture } from "three"; import { describe, expect, it } from "vitest"; import { TOOLCRAFT_DEFAULT_MODEL_IMPORT_LIMITS } from "../model-import-limits"; import { GLTF_APPEARANCE_PNG } from "../test-fixtures/gltf-appearance-fixtures"; import { createFbxPlaceholderRuntime, createFbxStaticAppearanceCatalog, } from "./fbx-static-appearance"; import type { ThreeStaticGeometrySourceBundle } from "./three-static-source-bundle"; function bundle(): ThreeStaticGeometrySourceBundle { return { files: [ { bytes: new Uint8Array([1]), path: "models/scene.fbx" }, { bytes: GLTF_APPEARANCE_PNG.slice(), path: "models/textures/diffuse.png", }, ], root: { bytes: new Uint8Array([1]), path: "models/scene.fbx" }, sourceByteLength: GLTF_APPEARANCE_PNG.byteLength + 1, }; } function loadPlaceholder( runtime: ReturnType, url: string, ): Texture { let texture: Texture | undefined; runtime.manager.getHandler(".png")!.load(url, (value) => { texture = value as Texture; }); if (!texture) throw new Error("Expected synchronous FBX placeholder texture."); return texture; } describe("FBX static appearance", () => { it("resolves placeholder texture identity through the verified package", () => { const runtime = createFbxPlaceholderRuntime(); const material = new MeshPhongMaterial({ map: loadPlaceholder(runtime, "textures/diffuse.png"), opacity: 0.75, shininess: 198, transparent: true, }); material.name = "Paint"; try { const catalog = createFbxStaticAppearanceCatalog( bundle(), [], TOOLCRAFT_DEFAULT_MODEL_IMPORT_LIMITS, ); const source = catalog.resolveMaterial(material); expect(source).toMatchObject({ baseColorTexture: { texture: { height: 3, width: 2 }, }, opacity: 0.75, roughness: 0.1, }); expect(catalog.diagnostics).toEqual([]); } finally { material.dispose(); runtime.dispose(); runtime.restoreObjectUrl(); } }); it("records a warning instead of fetching a remote image", () => { const runtime = createFbxPlaceholderRuntime(); const material = new MeshPhongMaterial({ map: loadPlaceholder(runtime, "https://example.com/diffuse.png"), }); material.name = "Remote"; try { const catalog = createFbxStaticAppearanceCatalog( bundle(), [], TOOLCRAFT_DEFAULT_MODEL_IMPORT_LIMITS, ); expect(catalog.resolveMaterial(material)?.baseColorTexture).toBeUndefined(); expect(catalog.diagnostics).toContainEqual(expect.objectContaining({ code: "blocked-remote-appearance-resource", severity: "warning", })); } finally { material.dispose(); runtime.dispose(); runtime.restoreObjectUrl(); } }); });