import { expect, test } from "@playwright/test"; import { Buffer } from "node:buffer"; for (const path of ["/", "/deep/nested/3d/"]) { test("inspects and transforms locally at " + path, async ({ page }) => { const external: string[] = []; page.on("request", (request) => { if (!request.url().startsWith("http://127.0.0.1:4211")) external.push(request.url()); }); await page.goto(path); await expect( page.getByRole("heading", { name: "Inspect geometry without uploading it.", }), ).toBeVisible(); await expect(page.getByText("4", { exact: true }).first()).toBeVisible(); await page.getByRole("button", { name: "Recalculate normals" }).click(); await expect(page.getByText(/vertex normals recalculated/u)).toBeVisible(); await expect(page.locator("canvas")).toBeVisible(); expect(external).toEqual([]); }); } test("parses and flattens glTF scene transforms in the worker", async ({ page, }) => { await page.goto("/"); await page.locator('input[type="file"]').setInputFiles({ name: "translated.gltf", mimeType: "model/gltf+json", buffer: gltfFixture(), }); await expect(page.locator("p.status")).toContainText("glTF parsed locally"); await expect( page.getByRole("heading", { name: "translated.gltf" }), ).toBeVisible(); await expect(page.getByRole("row", { name: /X 10 12 2/u })).toBeVisible(); }); test("keeps the installed application available offline", async ({ page, context, }) => { await page.goto("/"); await page.evaluate(async () => navigator.serviceWorker.ready); await page.reload(); await context.setOffline(true); try { await page.reload(); await expect( page.getByRole("heading", { name: "Inspect geometry without uploading it.", }), ).toBeVisible(); } finally { await context.setOffline(false); } }); function gltfFixture(): Buffer { const binary = Buffer.alloc(42); const view = new DataView( binary.buffer, binary.byteOffset, binary.byteLength, ); [0, 0, 0, 1, 0, 0, 0, 1, 0].forEach((value, index) => view.setFloat32(index * 4, value, true), ); view.setUint16(36, 0, true); view.setUint16(38, 1, true); view.setUint16(40, 2, true); const document = { asset: { version: "2.0" }, scene: 0, scenes: [{ nodes: [0] }], buffers: [ { uri: `data:application/octet-stream;base64,${binary.toString("base64")}`, byteLength: binary.length, }, ], bufferViews: [ { buffer: 0, byteOffset: 0, byteLength: 36 }, { buffer: 0, byteOffset: 36, byteLength: 6 }, ], accessors: [ { bufferView: 0, componentType: 5126, count: 3, type: "VEC3" }, { bufferView: 1, componentType: 5123, count: 3, type: "SCALAR" }, ], meshes: [{ primitives: [{ attributes: { POSITION: 0 }, indices: 1 }] }], nodes: [ { name: "Parent", translation: [10, 0, 0], children: [1] }, { name: "Scaled", mesh: 0, scale: [2, 1, 1] }, ], }; return Buffer.from(JSON.stringify(document)); }