@quake2ts/test-utils 0.0.848 → 0.0.850
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 +235 -98
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +65 -1
- package/dist/index.d.ts +65 -1
- package/dist/index.js +233 -98
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/src/engine/builders/visual-testing.ts +2 -2
- package/src/index.ts +2 -0
- package/src/setup/webgpu-lifecycle.ts +102 -0
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
|
|
1626
|
-
|
|
1627
|
-
if (!
|
|
1628
|
-
|
|
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
|
-
...
|
|
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
|
|
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 { ...
|
|
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
|
|
1678
|
+
const base2 = {
|
|
1677
1679
|
id: def.id,
|
|
1678
1680
|
name: `Mock Ammo ${def.id}`
|
|
1679
1681
|
};
|
|
1680
1682
|
return {
|
|
1681
|
-
...
|
|
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
|
|
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
|
-
|
|
1696
|
+
base2.timer = duration;
|
|
1695
1697
|
}
|
|
1696
|
-
return { ...
|
|
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((
|
|
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
|
|
5215
|
-
writeVec3(view,
|
|
5216
|
-
view.setFloat32(
|
|
5217
|
-
view.setInt32(
|
|
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
|
|
5230
|
-
view.setInt32(
|
|
5231
|
-
view.setInt32(
|
|
5232
|
-
view.setInt32(
|
|
5233
|
-
view.setInt16(
|
|
5234
|
-
view.setInt16(
|
|
5235
|
-
view.setInt16(
|
|
5236
|
-
view.setInt16(
|
|
5237
|
-
view.setInt16(
|
|
5238
|
-
view.setInt16(
|
|
5239
|
-
view.setUint16(
|
|
5240
|
-
view.setUint16(
|
|
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
|
|
5248
|
-
writeVec3(view,
|
|
5249
|
-
view.setFloat32(
|
|
5250
|
-
writeVec3(view,
|
|
5251
|
-
view.setFloat32(
|
|
5252
|
-
view.setInt32(
|
|
5253
|
-
view.setInt32(
|
|
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),
|
|
5256
|
-
view.setInt32(
|
|
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
|
|
5264
|
-
view.setUint16(
|
|
5265
|
-
view.setInt16(
|
|
5266
|
-
view.setInt32(
|
|
5267
|
-
view.setInt16(
|
|
5268
|
-
view.setInt16(
|
|
5269
|
-
face.styles.forEach((style, sIndex) => view.setUint8(
|
|
5270
|
-
view.setInt32(
|
|
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
|
|
5278
|
-
view.setInt32(
|
|
5279
|
-
view.setInt16(
|
|
5280
|
-
view.setInt16(
|
|
5281
|
-
view.setInt16(
|
|
5282
|
-
view.setInt16(
|
|
5283
|
-
view.setInt16(
|
|
5284
|
-
view.setInt16(
|
|
5285
|
-
view.setInt16(
|
|
5286
|
-
view.setInt16(
|
|
5287
|
-
view.setUint16(
|
|
5288
|
-
view.setUint16(
|
|
5289
|
-
view.setUint16(
|
|
5290
|
-
view.setUint16(
|
|
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
|
|
5298
|
-
view.setUint16(
|
|
5299
|
-
view.setUint16(
|
|
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
|
|
5308
|
-
writeVec3(view,
|
|
5309
|
-
writeVec3(view,
|
|
5310
|
-
writeVec3(view,
|
|
5311
|
-
view.setInt32(
|
|
5312
|
-
view.setInt32(
|
|
5313
|
-
view.setInt32(
|
|
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
|
|
5321
|
-
view.setInt32(
|
|
5322
|
-
view.setInt32(
|
|
5323
|
-
view.setInt32(
|
|
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
|
|
5331
|
-
view.setUint16(
|
|
5332
|
-
view.setInt16(
|
|
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
|
|
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(
|
|
5431
|
-
view.setFloat32(
|
|
5432
|
-
view.setFloat32(
|
|
5433
|
-
view.setFloat32(
|
|
5434
|
-
view.setFloat32(
|
|
5435
|
-
view.setFloat32(
|
|
5436
|
-
writeCString(view,
|
|
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 =
|
|
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
|
|
5505
|
-
view.setInt16(
|
|
5506
|
-
view.setInt16(
|
|
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
|
|
5510
|
-
view.setUint16(
|
|
5511
|
-
view.setUint16(
|
|
5512
|
-
view.setUint16(
|
|
5513
|
-
view.setUint16(
|
|
5514
|
-
view.setUint16(
|
|
5515
|
-
view.setUint16(
|
|
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
|
|
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(
|
|
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,
|