@quake2ts/test-utils 0.0.847 → 0.0.849

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -245,6 +245,7 @@ __export(index_exports, {
245
245
  createVisualTestScenario: () => createVisualTestScenario,
246
246
  createWebGLPlaywrightSetup: () => createWebGLPlaywrightSetup,
247
247
  createWebGLRenderTestSetup: () => createWebGLRenderTestSetup,
248
+ createWebGPULifecycle: () => createWebGPULifecycle,
248
249
  encodedVisForClusters: () => encodedVisForClusters,
249
250
  expectAnimationSnapshot: () => expectAnimationSnapshot,
250
251
  expectNoDoubleTransform: () => expectNoDoubleTransform,
@@ -309,6 +310,7 @@ __export(index_exports, {
309
310
  teardownBrowserEnvironment: () => teardownBrowserEnvironment,
310
311
  teardownMockAudioContext: () => teardownMockAudioContext,
311
312
  teardownNodeEnvironment: () => teardownNodeEnvironment,
313
+ test: () => test,
312
314
  testComputeShader: () => testComputeShader,
313
315
  testPipelineRendering: () => testPipelineRendering,
314
316
  testWebGLAnimation: () => testWebGLAnimation,
@@ -1622,22 +1624,22 @@ function createMockInventory(overrides = {}) {
1622
1624
  return inventory;
1623
1625
  }
1624
1626
  function createMockItem(id, overrides = {}) {
1625
- let base;
1626
- base = import_game7.WEAPON_ITEMS[id] || import_game7.HEALTH_ITEMS[id] || import_game7.ARMOR_ITEMS[id] || import_game7.POWERUP_ITEMS[id] || import_game7.POWER_ARMOR_ITEMS[id] || import_game7.KEY_ITEMS[id] || import_game7.FLAG_ITEMS[id];
1627
- if (!base) {
1628
- base = {
1627
+ let base2;
1628
+ base2 = import_game7.WEAPON_ITEMS[id] || import_game7.HEALTH_ITEMS[id] || import_game7.ARMOR_ITEMS[id] || import_game7.POWERUP_ITEMS[id] || import_game7.POWER_ARMOR_ITEMS[id] || import_game7.KEY_ITEMS[id] || import_game7.FLAG_ITEMS[id];
1629
+ if (!base2) {
1630
+ base2 = {
1629
1631
  id,
1630
1632
  name: `Mock Item ${id}`
1631
1633
  };
1632
1634
  }
1633
1635
  return {
1634
- ...base,
1636
+ ...base2,
1635
1637
  ...overrides
1636
1638
  };
1637
1639
  }
1638
1640
  function createMockWeaponItem(weaponId, overrides = {}) {
1639
1641
  const found = Object.values(import_game7.WEAPON_ITEMS).find((w) => w.weaponId === weaponId);
1640
- const base = found ? { ...found } : {
1642
+ const base2 = found ? { ...found } : {
1641
1643
  type: "weapon",
1642
1644
  id: `weapon_${weaponId}`,
1643
1645
  name: `Mock Weapon ${weaponId}`,
@@ -1647,7 +1649,7 @@ function createMockWeaponItem(weaponId, overrides = {}) {
1647
1649
  pickupAmmo: 0,
1648
1650
  fireRate: 1
1649
1651
  };
1650
- return { ...base, ...overrides };
1652
+ return { ...base2, ...overrides };
1651
1653
  }
1652
1654
  function createMockHealthItem(amount, overrides = {}) {
1653
1655
  return {
@@ -1673,27 +1675,27 @@ function createMockAmmoItem(ammoItemId, overrides = {}) {
1673
1675
  if (!def) {
1674
1676
  throw new Error(`Unknown ammo item id: ${ammoItemId}`);
1675
1677
  }
1676
- const base = {
1678
+ const base2 = {
1677
1679
  id: def.id,
1678
1680
  name: `Mock Ammo ${def.id}`
1679
1681
  };
1680
1682
  return {
1681
- ...base,
1683
+ ...base2,
1682
1684
  ...overrides
1683
1685
  };
1684
1686
  }
1685
1687
  function createMockPowerupItem(id, duration, overrides = {}) {
1686
1688
  const found = import_game7.POWERUP_ITEMS[id];
1687
- const base = found ? { ...found } : {
1689
+ const base2 = found ? { ...found } : {
1688
1690
  type: "powerup",
1689
1691
  id,
1690
1692
  name: `Mock Powerup ${id}`,
1691
1693
  timer: duration
1692
1694
  };
1693
1695
  if (duration !== void 0 && !found) {
1694
- base.timer = duration;
1696
+ base2.timer = duration;
1695
1697
  }
1696
- return { ...base, ...overrides };
1698
+ return { ...base2, ...overrides };
1697
1699
  }
1698
1700
 
1699
1701
  // src/server/mocks/transport.ts
@@ -3255,6 +3257,45 @@ async function createHeadlessTestContext() {
3255
3257
  };
3256
3258
  }
3257
3259
 
3260
+ // src/setup/webgpu-lifecycle.ts
3261
+ function createWebGPULifecycle() {
3262
+ const devices = [];
3263
+ const renderers = [];
3264
+ return {
3265
+ track(device) {
3266
+ devices.push(device);
3267
+ },
3268
+ trackRenderer(renderer) {
3269
+ renderers.push(renderer);
3270
+ },
3271
+ async cleanup() {
3272
+ for (const renderer of renderers) {
3273
+ try {
3274
+ renderer.dispose();
3275
+ } catch (e) {
3276
+ console.warn("Error disposing renderer:", e);
3277
+ }
3278
+ }
3279
+ renderers.length = 0;
3280
+ const allDevices = [...devices];
3281
+ devices.length = 0;
3282
+ if (allDevices.length === 0) return;
3283
+ const lostPromises = allDevices.map((d) => d.lost);
3284
+ for (const device of allDevices) {
3285
+ try {
3286
+ device.destroy();
3287
+ } catch (e) {
3288
+ console.warn("Error destroying device:", e);
3289
+ }
3290
+ }
3291
+ await Promise.all(lostPromises);
3292
+ },
3293
+ count() {
3294
+ return devices.length + renderers.length;
3295
+ }
3296
+ };
3297
+ }
3298
+
3258
3299
  // src/setup/headless-webgl.ts
3259
3300
  function createHeadlessWebGL(options = {}) {
3260
3301
  const width = options.width ?? 256;
@@ -3962,7 +4003,7 @@ function createMockAssetManager(overrides) {
3962
4003
  getMemoryUsage: import_vitest13.vi.fn().mockReturnValue({ textures: 0, audio: 0 }),
3963
4004
  clearCache: import_vitest13.vi.fn(),
3964
4005
  preloadAssets: import_vitest13.vi.fn().mockResolvedValue(void 0),
3965
- queueLoad: import_vitest13.vi.fn().mockImplementation((path6) => Promise.resolve({})),
4006
+ queueLoad: import_vitest13.vi.fn().mockImplementation((path7) => Promise.resolve({})),
3966
4007
  ...overrides
3967
4008
  };
3968
4009
  }
@@ -5211,10 +5252,10 @@ function writeVec3(view, offset, vec) {
5211
5252
  function encodePlanes(planes) {
5212
5253
  const view = allocBuffer(planes.length * 20);
5213
5254
  planes.forEach((plane, index) => {
5214
- const base = index * 20;
5215
- writeVec3(view, base, plane.normal);
5216
- view.setFloat32(base + 12, plane.dist, true);
5217
- view.setInt32(base + 16, plane.type, true);
5255
+ const base2 = index * 20;
5256
+ writeVec3(view, base2, plane.normal);
5257
+ view.setFloat32(base2 + 12, plane.dist, true);
5258
+ view.setInt32(base2 + 16, plane.type, true);
5218
5259
  });
5219
5260
  return new Uint8Array(view.buffer);
5220
5261
  }
@@ -5226,77 +5267,77 @@ function encodeVertices(vertices) {
5226
5267
  function encodeNodes(nodes) {
5227
5268
  const view = allocBuffer(nodes.length * 28);
5228
5269
  nodes.forEach((node, index) => {
5229
- const base = index * 28;
5230
- view.setInt32(base, node.planeIndex, true);
5231
- view.setInt32(base + 4, node.children[0], true);
5232
- view.setInt32(base + 8, node.children[1], true);
5233
- view.setInt16(base + 12, node.mins[0], true);
5234
- view.setInt16(base + 14, node.mins[1], true);
5235
- view.setInt16(base + 16, node.mins[2], true);
5236
- view.setInt16(base + 18, node.maxs[0], true);
5237
- view.setInt16(base + 20, node.maxs[1], true);
5238
- view.setInt16(base + 22, node.maxs[2], true);
5239
- view.setUint16(base + 24, node.firstFace, true);
5240
- view.setUint16(base + 26, node.numFaces, true);
5270
+ const base2 = index * 28;
5271
+ view.setInt32(base2, node.planeIndex, true);
5272
+ view.setInt32(base2 + 4, node.children[0], true);
5273
+ view.setInt32(base2 + 8, node.children[1], true);
5274
+ view.setInt16(base2 + 12, node.mins[0], true);
5275
+ view.setInt16(base2 + 14, node.mins[1], true);
5276
+ view.setInt16(base2 + 16, node.mins[2], true);
5277
+ view.setInt16(base2 + 18, node.maxs[0], true);
5278
+ view.setInt16(base2 + 20, node.maxs[1], true);
5279
+ view.setInt16(base2 + 22, node.maxs[2], true);
5280
+ view.setUint16(base2 + 24, node.firstFace, true);
5281
+ view.setUint16(base2 + 26, node.numFaces, true);
5241
5282
  });
5242
5283
  return new Uint8Array(view.buffer);
5243
5284
  }
5244
5285
  function encodeTexInfo(texInfos) {
5245
5286
  const view = allocBuffer(texInfos.length * 76);
5246
5287
  texInfos.forEach((tex, index) => {
5247
- const base = index * 76;
5248
- writeVec3(view, base, tex.s);
5249
- view.setFloat32(base + 12, tex.sOffset, true);
5250
- writeVec3(view, base + 16, tex.t);
5251
- view.setFloat32(base + 28, tex.tOffset, true);
5252
- view.setInt32(base + 32, tex.flags, true);
5253
- view.setInt32(base + 36, tex.value, true);
5288
+ const base2 = index * 76;
5289
+ writeVec3(view, base2, tex.s);
5290
+ view.setFloat32(base2 + 12, tex.sOffset, true);
5291
+ writeVec3(view, base2 + 16, tex.t);
5292
+ view.setFloat32(base2 + 28, tex.tOffset, true);
5293
+ view.setInt32(base2 + 32, tex.flags, true);
5294
+ view.setInt32(base2 + 36, tex.value, true);
5254
5295
  const textureBytes = new TextEncoder().encode(tex.texture);
5255
- new Uint8Array(view.buffer).set(textureBytes.slice(0, 32), base + 40);
5256
- view.setInt32(base + 72, tex.nextTexInfo, true);
5296
+ new Uint8Array(view.buffer).set(textureBytes.slice(0, 32), base2 + 40);
5297
+ view.setInt32(base2 + 72, tex.nextTexInfo, true);
5257
5298
  });
5258
5299
  return new Uint8Array(view.buffer);
5259
5300
  }
5260
5301
  function encodeFaces(faces) {
5261
5302
  const view = allocBuffer(faces.length * 20);
5262
5303
  faces.forEach((face, index) => {
5263
- const base = index * 20;
5264
- view.setUint16(base, face.planeIndex, true);
5265
- view.setInt16(base + 2, face.side, true);
5266
- view.setInt32(base + 4, face.firstEdge, true);
5267
- view.setInt16(base + 8, face.numEdges, true);
5268
- view.setInt16(base + 10, face.texInfo, true);
5269
- face.styles.forEach((style, sIndex) => view.setUint8(base + 12 + sIndex, style));
5270
- view.setInt32(base + 16, face.lightOffset, true);
5304
+ const base2 = index * 20;
5305
+ view.setUint16(base2, face.planeIndex, true);
5306
+ view.setInt16(base2 + 2, face.side, true);
5307
+ view.setInt32(base2 + 4, face.firstEdge, true);
5308
+ view.setInt16(base2 + 8, face.numEdges, true);
5309
+ view.setInt16(base2 + 10, face.texInfo, true);
5310
+ face.styles.forEach((style, sIndex) => view.setUint8(base2 + 12 + sIndex, style));
5311
+ view.setInt32(base2 + 16, face.lightOffset, true);
5271
5312
  });
5272
5313
  return new Uint8Array(view.buffer);
5273
5314
  }
5274
5315
  function encodeLeafs(leafs) {
5275
5316
  const view = allocBuffer(leafs.length * 28);
5276
5317
  leafs.forEach((leaf, index) => {
5277
- const base = index * 28;
5278
- view.setInt32(base, leaf.contents, true);
5279
- view.setInt16(base + 4, leaf.cluster, true);
5280
- view.setInt16(base + 6, leaf.area, true);
5281
- view.setInt16(base + 8, leaf.mins[0], true);
5282
- view.setInt16(base + 10, leaf.mins[1], true);
5283
- view.setInt16(base + 12, leaf.mins[2], true);
5284
- view.setInt16(base + 14, leaf.maxs[0], true);
5285
- view.setInt16(base + 16, leaf.maxs[1], true);
5286
- view.setInt16(base + 18, leaf.maxs[2], true);
5287
- view.setUint16(base + 20, leaf.firstLeafFace, true);
5288
- view.setUint16(base + 22, leaf.numLeafFaces, true);
5289
- view.setUint16(base + 24, leaf.firstLeafBrush, true);
5290
- view.setUint16(base + 26, leaf.numLeafBrushes, true);
5318
+ const base2 = index * 28;
5319
+ view.setInt32(base2, leaf.contents, true);
5320
+ view.setInt16(base2 + 4, leaf.cluster, true);
5321
+ view.setInt16(base2 + 6, leaf.area, true);
5322
+ view.setInt16(base2 + 8, leaf.mins[0], true);
5323
+ view.setInt16(base2 + 10, leaf.mins[1], true);
5324
+ view.setInt16(base2 + 12, leaf.mins[2], true);
5325
+ view.setInt16(base2 + 14, leaf.maxs[0], true);
5326
+ view.setInt16(base2 + 16, leaf.maxs[1], true);
5327
+ view.setInt16(base2 + 18, leaf.maxs[2], true);
5328
+ view.setUint16(base2 + 20, leaf.firstLeafFace, true);
5329
+ view.setUint16(base2 + 22, leaf.numLeafFaces, true);
5330
+ view.setUint16(base2 + 24, leaf.firstLeafBrush, true);
5331
+ view.setUint16(base2 + 26, leaf.numLeafBrushes, true);
5291
5332
  });
5292
5333
  return new Uint8Array(view.buffer);
5293
5334
  }
5294
5335
  function encodeEdges(edges) {
5295
5336
  const view = allocBuffer(edges.length * 4);
5296
5337
  edges.forEach((edge, index) => {
5297
- const base = index * 4;
5298
- view.setUint16(base, edge[0], true);
5299
- view.setUint16(base + 2, edge[1], true);
5338
+ const base2 = index * 4;
5339
+ view.setUint16(base2, edge[0], true);
5340
+ view.setUint16(base2 + 2, edge[1], true);
5300
5341
  });
5301
5342
  return new Uint8Array(view.buffer);
5302
5343
  }
@@ -5304,32 +5345,32 @@ function encodeModels(models) {
5304
5345
  const entrySize = 48;
5305
5346
  const view = allocBuffer(models.length * entrySize);
5306
5347
  models.forEach((model, index) => {
5307
- const base = index * entrySize;
5308
- writeVec3(view, base, model.mins);
5309
- writeVec3(view, base + 12, model.maxs);
5310
- writeVec3(view, base + 24, model.origin);
5311
- view.setInt32(base + 36, model.headNode, true);
5312
- view.setInt32(base + 40, model.firstFace, true);
5313
- view.setInt32(base + 44, model.numFaces, true);
5348
+ const base2 = index * entrySize;
5349
+ writeVec3(view, base2, model.mins);
5350
+ writeVec3(view, base2 + 12, model.maxs);
5351
+ writeVec3(view, base2 + 24, model.origin);
5352
+ view.setInt32(base2 + 36, model.headNode, true);
5353
+ view.setInt32(base2 + 40, model.firstFace, true);
5354
+ view.setInt32(base2 + 44, model.numFaces, true);
5314
5355
  });
5315
5356
  return new Uint8Array(view.buffer);
5316
5357
  }
5317
5358
  function encodeBrushes(brushes) {
5318
5359
  const view = allocBuffer(brushes.length * 12);
5319
5360
  brushes.forEach((brush, index) => {
5320
- const base = index * 12;
5321
- view.setInt32(base, brush.firstSide, true);
5322
- view.setInt32(base + 4, brush.numSides, true);
5323
- view.setInt32(base + 8, brush.contents, true);
5361
+ const base2 = index * 12;
5362
+ view.setInt32(base2, brush.firstSide, true);
5363
+ view.setInt32(base2 + 4, brush.numSides, true);
5364
+ view.setInt32(base2 + 8, brush.contents, true);
5324
5365
  });
5325
5366
  return new Uint8Array(view.buffer);
5326
5367
  }
5327
5368
  function encodeBrushSides(sides) {
5328
5369
  const view = allocBuffer(sides.length * 4);
5329
5370
  sides.forEach((side, index) => {
5330
- const base = index * 4;
5331
- view.setUint16(base, side.planeIndex, true);
5332
- view.setInt16(base + 2, side.texInfo, true);
5371
+ const base2 = index * 4;
5372
+ view.setUint16(base2, side.planeIndex, true);
5373
+ view.setInt16(base2 + 2, side.texInfo, true);
5333
5374
  });
5334
5375
  return new Uint8Array(view.buffer);
5335
5376
  }
@@ -5424,18 +5465,18 @@ function encodeFrames(frames, numVertices) {
5424
5465
  const frameSize = 40 + numVertices * 4;
5425
5466
  const view = allocBuffer2(frames.length * frameSize);
5426
5467
  frames.forEach((frame, frameIndex) => {
5427
- const base = frameIndex * frameSize;
5468
+ const base2 = frameIndex * frameSize;
5428
5469
  const scale = frame.scale ?? { x: 1, y: 1, z: 1 };
5429
5470
  const translate = frame.translate ?? { x: 0, y: 0, z: 0 };
5430
- view.setFloat32(base, scale.x, true);
5431
- view.setFloat32(base + 4, scale.y, true);
5432
- view.setFloat32(base + 8, scale.z, true);
5433
- view.setFloat32(base + 12, translate.x, true);
5434
- view.setFloat32(base + 16, translate.y, true);
5435
- view.setFloat32(base + 20, translate.z, true);
5436
- writeCString(view, base + 24, frame.name, 16);
5471
+ view.setFloat32(base2, scale.x, true);
5472
+ view.setFloat32(base2 + 4, scale.y, true);
5473
+ view.setFloat32(base2 + 8, scale.z, true);
5474
+ view.setFloat32(base2 + 12, translate.x, true);
5475
+ view.setFloat32(base2 + 16, translate.y, true);
5476
+ view.setFloat32(base2 + 20, translate.z, true);
5477
+ writeCString(view, base2 + 24, frame.name, 16);
5437
5478
  frame.vertices.forEach((vertex, index) => {
5438
- const offset = base + 40 + index * 4;
5479
+ const offset = base2 + 40 + index * 4;
5439
5480
  view.setUint8(offset, Math.round((vertex.position.x - translate.x) / scale.x));
5440
5481
  view.setUint8(offset + 1, Math.round((vertex.position.y - translate.y) / scale.y));
5441
5482
  view.setUint8(offset + 2, Math.round((vertex.position.z - translate.z) / scale.z));
@@ -5501,18 +5542,18 @@ function buildMd2(options) {
5501
5542
  view.setInt32(64, offsetEnd, true);
5502
5543
  skins.forEach((skin, index) => writeCString(view, offsetSkins + index * 64, skin, 64));
5503
5544
  options.texCoords.forEach((coord, index) => {
5504
- const base = offsetTexCoords + index * 4;
5505
- view.setInt16(base, coord.s, true);
5506
- view.setInt16(base + 2, coord.t, true);
5545
+ const base2 = offsetTexCoords + index * 4;
5546
+ view.setInt16(base2, coord.s, true);
5547
+ view.setInt16(base2 + 2, coord.t, true);
5507
5548
  });
5508
5549
  options.triangles.forEach((tri, index) => {
5509
- const base = offsetTriangles + index * 12;
5510
- view.setUint16(base, tri.vertexIndices[0], true);
5511
- view.setUint16(base + 2, tri.vertexIndices[1], true);
5512
- view.setUint16(base + 4, tri.vertexIndices[2], true);
5513
- view.setUint16(base + 6, tri.texCoordIndices[0], true);
5514
- view.setUint16(base + 8, tri.texCoordIndices[1], true);
5515
- view.setUint16(base + 10, tri.texCoordIndices[2], true);
5550
+ const base2 = offsetTriangles + index * 12;
5551
+ view.setUint16(base2, tri.vertexIndices[0], true);
5552
+ view.setUint16(base2 + 2, tri.vertexIndices[1], true);
5553
+ view.setUint16(base2 + 4, tri.vertexIndices[2], true);
5554
+ view.setUint16(base2 + 6, tri.texCoordIndices[0], true);
5555
+ view.setUint16(base2 + 8, tri.texCoordIndices[1], true);
5556
+ view.setUint16(base2 + 10, tri.texCoordIndices[2], true);
5516
5557
  });
5517
5558
  new Uint8Array(view.buffer, offsetFrames, frameBlockSize).set(encodeFrames(options.frames, numVertices));
5518
5559
  new Uint8Array(view.buffer, offsetGlCommands, glSize).set(glData);
@@ -6295,6 +6336,100 @@ var verifySmoothing = (states) => {
6295
6336
  };
6296
6337
  };
6297
6338
 
6339
+ // src/engine/builders/visual-testing.ts
6340
+ var import_vitest23 = require("vitest");
6341
+ var import_path4 = __toESM(require("path"), 1);
6342
+ var test = import_vitest23.test.extend({
6343
+ expectSnapshot: async ({ task }, use) => {
6344
+ const impl = async (pixels, nameOrOptions) => {
6345
+ const updateBaseline = process.env.UPDATE_VISUAL === "1" || process.argv.includes("--update-snapshots") || process.argv.includes("-u");
6346
+ const testFile = task.file?.filepath;
6347
+ const testDir = testFile ? import_path4.default.dirname(testFile) : import_path4.default.join(process.cwd(), "tests");
6348
+ const snapshotDir = import_path4.default.join(testDir, "__snapshots__");
6349
+ const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions.name;
6350
+ const description = typeof nameOrOptions === "string" ? void 0 : nameOrOptions.description;
6351
+ await expectSnapshot(pixels, {
6352
+ name,
6353
+ description,
6354
+ width: 256,
6355
+ height: 256,
6356
+ updateBaseline,
6357
+ snapshotDir
6358
+ });
6359
+ };
6360
+ await use(impl);
6361
+ },
6362
+ renderAndExpectSnapshot: async ({ task }, use) => {
6363
+ const updateBaseline = process.env.UPDATE_VISUAL === "1" || process.argv.includes("--update-snapshots") || process.argv.includes("-u");
6364
+ const testFile = task.file?.filepath;
6365
+ const testDir = testFile ? import_path4.default.dirname(testFile) : import_path4.default.join(process.cwd(), "tests");
6366
+ const snapshotDir = import_path4.default.join(testDir, "__snapshots__");
6367
+ let setup;
6368
+ const impl = async (fn, nameOrOptions) => {
6369
+ const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions.name;
6370
+ const description = typeof nameOrOptions === "string" ? void 0 : nameOrOptions.description;
6371
+ const depth = typeof nameOrOptions === "string" ? false : !!nameOrOptions.depth;
6372
+ setup = await createRenderTestSetup(256, 256, { depth });
6373
+ const { device } = setup.context;
6374
+ try {
6375
+ const commandEncoder = device.createCommandEncoder();
6376
+ const renderFn = await fn(
6377
+ device,
6378
+ setup.context.format || "rgba8unorm",
6379
+ commandEncoder,
6380
+ setup.renderTargetView
6381
+ );
6382
+ device.pushErrorScope("validation");
6383
+ if (typeof renderFn === "function") {
6384
+ const passDescriptor = {
6385
+ colorAttachments: [{
6386
+ view: setup.renderTargetView,
6387
+ loadOp: "clear",
6388
+ clearValue: { r: 0, g: 0, b: 0, a: 0 },
6389
+ storeOp: "store"
6390
+ }]
6391
+ };
6392
+ if (setup.depthTargetView) {
6393
+ passDescriptor.depthStencilAttachment = {
6394
+ view: setup.depthTargetView,
6395
+ depthClearValue: 1,
6396
+ depthLoadOp: "clear",
6397
+ depthStoreOp: "discard"
6398
+ };
6399
+ }
6400
+ const pass = commandEncoder.beginRenderPass(passDescriptor);
6401
+ renderFn(pass);
6402
+ pass.end();
6403
+ } else {
6404
+ }
6405
+ device.queue.submit([commandEncoder.finish()]);
6406
+ const error = await device.popErrorScope();
6407
+ if (error) {
6408
+ throw new Error(`WebGPU validation error: ${error.message}`);
6409
+ }
6410
+ const pixels = await captureTexture(device, setup.renderTarget, setup.width, setup.height);
6411
+ await expectSnapshot(pixels, {
6412
+ name,
6413
+ description,
6414
+ width: setup.width,
6415
+ height: setup.height,
6416
+ updateBaseline,
6417
+ snapshotDir
6418
+ });
6419
+ } finally {
6420
+ if (setup) {
6421
+ await setup.cleanup();
6422
+ setup = void 0;
6423
+ }
6424
+ }
6425
+ };
6426
+ await use(impl);
6427
+ if (setup) {
6428
+ await setup.cleanup();
6429
+ }
6430
+ }
6431
+ });
6432
+
6298
6433
  // src/e2e/playwright.ts
6299
6434
  async function createPlaywrightTestClient(options = {}) {
6300
6435
  let playwright;
@@ -6379,7 +6514,7 @@ function throttleBandwidth(bytesPerSecond) {
6379
6514
  var import_pngjs2 = require("pngjs");
6380
6515
  var import_pixelmatch2 = __toESM(require("pixelmatch"), 1);
6381
6516
  var import_promises3 = __toESM(require("fs/promises"), 1);
6382
- var import_path4 = __toESM(require("path"), 1);
6517
+ var import_path5 = __toESM(require("path"), 1);
6383
6518
  async function captureGameScreenshot(page, name) {
6384
6519
  const canvasElement = page.locator("canvas");
6385
6520
  if (await canvasElement.count() > 0) {
@@ -6398,7 +6533,7 @@ async function takeScreenshot(canvas, filepath) {
6398
6533
  } else {
6399
6534
  throw new Error("Unsupported canvas type for screenshot");
6400
6535
  }
6401
- await import_promises3.default.mkdir(import_path4.default.dirname(filepath), { recursive: true });
6536
+ await import_promises3.default.mkdir(import_path5.default.dirname(filepath), { recursive: true });
6402
6537
  await import_promises3.default.writeFile(filepath, buffer);
6403
6538
  }
6404
6539
  function compareScreenshots(baseline, current, threshold = 0.01) {
@@ -6657,6 +6792,7 @@ function createVisualTestScenario(sceneName) {
6657
6792
  createVisualTestScenario,
6658
6793
  createWebGLPlaywrightSetup,
6659
6794
  createWebGLRenderTestSetup,
6795
+ createWebGPULifecycle,
6660
6796
  encodedVisForClusters,
6661
6797
  expectAnimationSnapshot,
6662
6798
  expectNoDoubleTransform,
@@ -6721,6 +6857,7 @@ function createVisualTestScenario(sceneName) {
6721
6857
  teardownBrowserEnvironment,
6722
6858
  teardownMockAudioContext,
6723
6859
  teardownNodeEnvironment,
6860
+ test,
6724
6861
  testComputeShader,
6725
6862
  testPipelineRendering,
6726
6863
  testWebGLAnimation,