From ac5c656b0e34b1845e0bce9d3b526c4b518013e2 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Mon, 18 May 2026 16:16:31 +0200 Subject: [PATCH] Test: Add serialization tests for asset bundling (images, GLTF) --- tests/serialization/project-package.test.ts | 75 +++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/tests/serialization/project-package.test.ts b/tests/serialization/project-package.test.ts index 9ecd4c49..ea6630de 100644 --- a/tests/serialization/project-package.test.ts +++ b/tests/serialization/project-package.test.ts @@ -25,6 +25,7 @@ import { createEmptySceneDocument, createProjectDocumentFromSceneDocument } from "../../src/document/scene-document"; +import { createCustomMaterialDef } from "../../src/materials/starter-material-library"; import { loadProjectPackage, PROJECT_PACKAGE_SCENE_PATH, @@ -308,6 +309,80 @@ describe("project package serialization", () => { ); }); + it("bundles image assets referenced only by custom material texture slots", async () => { + const storage = createInMemoryProjectAssetStorage(); + const imageAsset = { + id: "asset-image-material-package", + kind: "image", + sourceName: "custom-material-map.png", + mimeType: "image/png", + storageKey: createProjectAssetStorageKey( + "asset-image-material-package" + ), + byteLength: 4, + metadata: { + kind: "image", + width: 1, + height: 1, + hasAlpha: false, + warnings: [] + } + } satisfies ImageAssetRecord; + const material = createCustomMaterialDef({ + id: "material-package-custom", + textures: { + albedo: null, + normal: { + assetId: imageAsset.id + }, + roughness: null, + metallic: null + } + }); + + await storage.putAsset(imageAsset.storageKey, { + files: { + [imageAsset.sourceName]: { + bytes: new Uint8Array([255, 255, 255, 255]).buffer, + mimeType: imageAsset.mimeType + } + } + }); + + const document = createProjectDocument({ + ...createEmptySceneDocument({ name: "Material Package Scene" }), + assets: { + [imageAsset.id]: imageAsset + }, + materials: { + ...createEmptySceneDocument().materials, + [material.id]: material + } + }); + + const packageBytes = await saveProjectPackage(document, storage); + const restoredStorage = createInMemoryProjectAssetStorage(); + const restoredDocument = await loadProjectPackage( + packageBytes, + restoredStorage + ); + + expect(restoredDocument).toEqual(document); + expect(listPackagedFiles(packageBytes)).toEqual( + expect.arrayContaining([ + "assets/project-asset:asset-image-material-package/custom-material-map.png" + ]) + ); + await expect(restoredStorage.getAsset(imageAsset.storageKey)).resolves.toEqual({ + files: { + [imageAsset.sourceName]: { + bytes: expect.any(ArrayBuffer), + mimeType: imageAsset.mimeType + } + } + }); + }); + it("preserves multi-file gltf asset bundles inside the packaged assets directory", async () => { const gltfBytes = await readFile(externalTriangleGltfPath); const binBytes = await readFile(externalTriangleBinPath);