@quake2ts/test-utils 0.0.1
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/README.md +454 -0
- package/dist/index.cjs +5432 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2150 -0
- package/dist/index.d.ts +2150 -0
- package/dist/index.js +5165 -0
- package/dist/index.js.map +1 -0
- package/package.json +82 -0
- package/src/client/helpers/hud.ts +114 -0
- package/src/client/helpers/prediction.ts +136 -0
- package/src/client/helpers/view.ts +201 -0
- package/src/client/mocks/console.ts +75 -0
- package/src/client/mocks/download.ts +48 -0
- package/src/client/mocks/input.ts +246 -0
- package/src/client/mocks/network.ts +148 -0
- package/src/client/mocks/state.ts +148 -0
- package/src/e2e/network.ts +47 -0
- package/src/e2e/playwright.ts +90 -0
- package/src/e2e/visual.ts +172 -0
- package/src/engine/helpers/pipeline-test-template.ts +113 -0
- package/src/engine/helpers/webgpu-rendering.ts +251 -0
- package/src/engine/mocks/assets.ts +129 -0
- package/src/engine/mocks/audio.ts +152 -0
- package/src/engine/mocks/buffers.ts +88 -0
- package/src/engine/mocks/lighting.ts +64 -0
- package/src/engine/mocks/particles.ts +76 -0
- package/src/engine/mocks/renderer.ts +218 -0
- package/src/engine/mocks/webgl.ts +267 -0
- package/src/engine/mocks/webgpu.ts +262 -0
- package/src/engine/rendering.ts +103 -0
- package/src/game/factories.ts +204 -0
- package/src/game/helpers/physics.ts +171 -0
- package/src/game/helpers/save.ts +232 -0
- package/src/game/helpers.ts +310 -0
- package/src/game/mocks/ai.ts +67 -0
- package/src/game/mocks/combat.ts +61 -0
- package/src/game/mocks/items.ts +166 -0
- package/src/game/mocks.ts +105 -0
- package/src/index.ts +93 -0
- package/src/server/helpers/bandwidth.ts +127 -0
- package/src/server/helpers/multiplayer.ts +158 -0
- package/src/server/helpers/snapshot.ts +241 -0
- package/src/server/mockNetDriver.ts +106 -0
- package/src/server/mockTransport.ts +50 -0
- package/src/server/mocks/commands.ts +93 -0
- package/src/server/mocks/connection.ts +139 -0
- package/src/server/mocks/master.ts +97 -0
- package/src/server/mocks/physics.ts +32 -0
- package/src/server/mocks/state.ts +162 -0
- package/src/server/mocks/transport.ts +161 -0
- package/src/setup/audio.ts +118 -0
- package/src/setup/browser.ts +249 -0
- package/src/setup/canvas.ts +142 -0
- package/src/setup/node.ts +21 -0
- package/src/setup/storage.ts +60 -0
- package/src/setup/timing.ts +142 -0
- package/src/setup/webgl.ts +8 -0
- package/src/setup/webgpu.ts +113 -0
- package/src/shared/bsp.ts +145 -0
- package/src/shared/collision.ts +64 -0
- package/src/shared/factories.ts +88 -0
- package/src/shared/math.ts +65 -0
- package/src/shared/mocks.ts +243 -0
- package/src/shared/pak-loader.ts +45 -0
- package/src/visual/snapshots.ts +292 -0
package/README.md
ADDED
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
# @quake2ts/test-utils
|
|
2
|
+
|
|
3
|
+
Shared test utilities, mocks, and setup helpers for Quake 2 TypeScript.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
### Browser Environment Setup
|
|
8
|
+
|
|
9
|
+
In your `vitest.setup.ts`:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { setupBrowserEnvironment } from '@quake2ts/test-utils';
|
|
13
|
+
|
|
14
|
+
setupBrowserEnvironment({
|
|
15
|
+
url: 'http://localhost',
|
|
16
|
+
enableWebGL2: true,
|
|
17
|
+
enablePointerLock: true
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Engine & Rendering Testing
|
|
22
|
+
|
|
23
|
+
#### WebGL & Buffer Mocks
|
|
24
|
+
|
|
25
|
+
Create mocks for WebGL contexts and resources:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import {
|
|
29
|
+
createMockWebGL2Context,
|
|
30
|
+
createMockVertexBuffer,
|
|
31
|
+
createMockIndexBuffer,
|
|
32
|
+
createMockShaderProgram
|
|
33
|
+
} from '@quake2ts/test-utils';
|
|
34
|
+
|
|
35
|
+
// Context
|
|
36
|
+
const gl = createMockWebGL2Context();
|
|
37
|
+
|
|
38
|
+
// Buffers
|
|
39
|
+
const vb = createMockVertexBuffer(new Float32Array([1, 0, 1]));
|
|
40
|
+
const ib = createMockIndexBuffer(new Uint16Array([0, 1, 2]));
|
|
41
|
+
|
|
42
|
+
// Shaders
|
|
43
|
+
const program = createMockShaderProgram({
|
|
44
|
+
use: vi.fn(),
|
|
45
|
+
getUniformLocation: vi.fn().mockReturnValue(1)
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### Renderer Mocks
|
|
50
|
+
|
|
51
|
+
Mock the high-level renderer or specific pipelines:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import {
|
|
55
|
+
createMockRenderer,
|
|
56
|
+
createMockFrameRenderer,
|
|
57
|
+
createMockMd2Pipeline
|
|
58
|
+
} from '@quake2ts/test-utils';
|
|
59
|
+
|
|
60
|
+
const renderer = createMockRenderer();
|
|
61
|
+
renderer.renderFrame(scene);
|
|
62
|
+
|
|
63
|
+
const md2Pipeline = createMockMd2Pipeline();
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
#### Lighting Mocks
|
|
67
|
+
|
|
68
|
+
Test dynamic lighting and lightmaps:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import {
|
|
72
|
+
createMockDLight,
|
|
73
|
+
createMockDLightManager,
|
|
74
|
+
createMockLightmap
|
|
75
|
+
} from '@quake2ts/test-utils';
|
|
76
|
+
|
|
77
|
+
const dlight = createMockDLight({ x: 10, y: 10, z: 10 }, { x: 1, y: 0, z: 0 }, 300);
|
|
78
|
+
const manager = createMockDLightManager();
|
|
79
|
+
manager.addLight(dlight);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### Particle System Mocks
|
|
83
|
+
|
|
84
|
+
Test particle effects and systems:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import {
|
|
88
|
+
createMockParticle,
|
|
89
|
+
createMockParticleSystem
|
|
90
|
+
} from '@quake2ts/test-utils';
|
|
91
|
+
|
|
92
|
+
const particle = createMockParticle({ size: 5, lifetime: 2.0 });
|
|
93
|
+
const system = createMockParticleSystem();
|
|
94
|
+
system.spawn(particle);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### Asset Mocks
|
|
98
|
+
|
|
99
|
+
Mock the asset manager and resources:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import {
|
|
103
|
+
createMockAssetManager,
|
|
104
|
+
createMockMd2Model,
|
|
105
|
+
createMockTexture
|
|
106
|
+
} from '@quake2ts/test-utils';
|
|
107
|
+
|
|
108
|
+
const assets = createMockAssetManager();
|
|
109
|
+
const model = createMockMd2Model();
|
|
110
|
+
const texture = createMockTexture(64, 64);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### WebGPU Testing
|
|
114
|
+
|
|
115
|
+
#### Unit Tests (Mocked)
|
|
116
|
+
|
|
117
|
+
For testing logic without GPU:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { createMockWebGPUContext } from '@quake2ts/test-utils';
|
|
121
|
+
|
|
122
|
+
test('creates uniform buffer', () => {
|
|
123
|
+
const { device } = createMockWebGPUContext();
|
|
124
|
+
const buffer = device.createBuffer({
|
|
125
|
+
size: 256,
|
|
126
|
+
usage: GPUBufferUsage.UNIFORM
|
|
127
|
+
});
|
|
128
|
+
expect(buffer.size).toBe(256);
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Integration Tests (Headless)
|
|
133
|
+
|
|
134
|
+
For testing actual rendering with @webgpu/dawn (in Node.js):
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { createRenderTestSetup, renderAndCapture } from '@quake2ts/test-utils';
|
|
138
|
+
|
|
139
|
+
test('renders triangle', async () => {
|
|
140
|
+
const setup = await createRenderTestSetup();
|
|
141
|
+
const pixels = await renderAndCapture(setup, (pass) => {
|
|
142
|
+
// ... render triangle
|
|
143
|
+
});
|
|
144
|
+
// Validate pixels
|
|
145
|
+
await setup.cleanup();
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Client Utilities
|
|
150
|
+
|
|
151
|
+
The library includes mocks and helpers for testing client-side systems like input, view/camera, HUD, and network.
|
|
152
|
+
|
|
153
|
+
#### Input Mocks
|
|
154
|
+
```typescript
|
|
155
|
+
import {
|
|
156
|
+
createMockPointerLock,
|
|
157
|
+
createInputInjector,
|
|
158
|
+
createMockKeyboardEvent,
|
|
159
|
+
createMockMouseEvent
|
|
160
|
+
} from '@quake2ts/test-utils';
|
|
161
|
+
|
|
162
|
+
// Mock Pointer Lock API
|
|
163
|
+
const pl = createMockPointerLock(document.body);
|
|
164
|
+
pl.request();
|
|
165
|
+
|
|
166
|
+
// Inject Input Events
|
|
167
|
+
const injector = createInputInjector();
|
|
168
|
+
injector.keyDown('KeyW');
|
|
169
|
+
injector.mouseMove(10, 5);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### View/Camera Helpers
|
|
173
|
+
```typescript
|
|
174
|
+
import {
|
|
175
|
+
createMockCamera,
|
|
176
|
+
createMockViewState,
|
|
177
|
+
createViewTestScenario,
|
|
178
|
+
simulateCameraMovement
|
|
179
|
+
} from '@quake2ts/test-utils';
|
|
180
|
+
|
|
181
|
+
// Create a camera with overrides
|
|
182
|
+
const camera = createMockCamera({ position: { x: 100, y: 0, z: 0 }, fov: 110 });
|
|
183
|
+
|
|
184
|
+
// Setup a predefined scenario
|
|
185
|
+
const scenario = createViewTestScenario('firstPerson');
|
|
186
|
+
|
|
187
|
+
// Simulate movement
|
|
188
|
+
simulateCameraMovement(camera, { forward: 100 }, 0.016);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### HUD Utilities
|
|
192
|
+
```typescript
|
|
193
|
+
import {
|
|
194
|
+
createMockHudState,
|
|
195
|
+
createMockScoreboard,
|
|
196
|
+
createMockChatMessage,
|
|
197
|
+
createMockNotification
|
|
198
|
+
} from '@quake2ts/test-utils';
|
|
199
|
+
|
|
200
|
+
const hud = createMockHudState({ health: 50, armor: 100 });
|
|
201
|
+
const chat = createMockChatMessage("Hello World", "Player1");
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### Client Network Mocks
|
|
205
|
+
```typescript
|
|
206
|
+
import {
|
|
207
|
+
createMockServerMessage,
|
|
208
|
+
createMockSnapshot,
|
|
209
|
+
createMockDeltaFrame,
|
|
210
|
+
simulateNetworkDelay,
|
|
211
|
+
simulatePacketLoss
|
|
212
|
+
} from '@quake2ts/test-utils';
|
|
213
|
+
|
|
214
|
+
// Create frame data
|
|
215
|
+
const snapshot = createMockSnapshot(100, [], { origin: { x: 0, y: 0, z: 0 } });
|
|
216
|
+
|
|
217
|
+
// Create network messages
|
|
218
|
+
const msg = createMockServerMessage(1, new Uint8Array([1, 2, 3]));
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### Console Mocks
|
|
222
|
+
```typescript
|
|
223
|
+
import { createMockConsole, createMockCommand } from '@quake2ts/test-utils';
|
|
224
|
+
|
|
225
|
+
const consoleMock = createMockConsole();
|
|
226
|
+
consoleMock.print('Hello');
|
|
227
|
+
expect(consoleMock.getHistory()).toContain('Hello');
|
|
228
|
+
|
|
229
|
+
const cmd = createMockCommand('god', () => { /* ... */ });
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Shared Utilities
|
|
233
|
+
|
|
234
|
+
The library includes common utilities for testing game logic, collisions, math, and networking.
|
|
235
|
+
|
|
236
|
+
#### BSP & Collision Helpers
|
|
237
|
+
```typescript
|
|
238
|
+
import {
|
|
239
|
+
makePlane,
|
|
240
|
+
makeAxisBrush,
|
|
241
|
+
makeNode,
|
|
242
|
+
makeBspModel,
|
|
243
|
+
makeLeaf,
|
|
244
|
+
createTraceMock,
|
|
245
|
+
createSurfaceMock
|
|
246
|
+
} from '@quake2ts/test-utils';
|
|
247
|
+
|
|
248
|
+
// Create a simple box brush
|
|
249
|
+
const brush = makeAxisBrush(32);
|
|
250
|
+
|
|
251
|
+
// Create a mock collision trace result
|
|
252
|
+
const trace = createTraceMock({
|
|
253
|
+
fraction: 0.5,
|
|
254
|
+
endpos: { x: 10, y: 0, z: 0 },
|
|
255
|
+
contents: 1 // CONTENTS_SOLID
|
|
256
|
+
});
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
#### Math Helpers
|
|
260
|
+
```typescript
|
|
261
|
+
import {
|
|
262
|
+
createVector3,
|
|
263
|
+
createBounds,
|
|
264
|
+
createTransform,
|
|
265
|
+
randomVector3
|
|
266
|
+
} from '@quake2ts/test-utils';
|
|
267
|
+
|
|
268
|
+
const v = createVector3(10, 20, 30);
|
|
269
|
+
const bounds = createBounds(); // Unit cube
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### Binary & Network Mocks
|
|
273
|
+
```typescript
|
|
274
|
+
import {
|
|
275
|
+
createBinaryWriterMock,
|
|
276
|
+
createBinaryStreamMock,
|
|
277
|
+
createNetChanMock,
|
|
278
|
+
createMessageWriterMock,
|
|
279
|
+
createPacketMock
|
|
280
|
+
} from '@quake2ts/test-utils';
|
|
281
|
+
|
|
282
|
+
const writer = createBinaryWriterMock();
|
|
283
|
+
writer.writeByte(123);
|
|
284
|
+
expect(writer.writeByte).toHaveBeenCalledWith(123);
|
|
285
|
+
|
|
286
|
+
const netchan = createNetChanMock();
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
#### Factories
|
|
290
|
+
```typescript
|
|
291
|
+
import {
|
|
292
|
+
createCvarMock,
|
|
293
|
+
createConfigStringMock
|
|
294
|
+
} from '@quake2ts/test-utils';
|
|
295
|
+
|
|
296
|
+
const cvar = createCvarMock('g_gravity', '800');
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Server Testing Utilities
|
|
300
|
+
|
|
301
|
+
The library includes comprehensive mocks and helpers for testing server logic without needing a full network stack.
|
|
302
|
+
|
|
303
|
+
#### Network Transport Mocks
|
|
304
|
+
```typescript
|
|
305
|
+
import { createMockTransport, createMockUDPSocket } from '@quake2ts/test-utils';
|
|
306
|
+
|
|
307
|
+
// Mock transport for direct message injection/capture
|
|
308
|
+
const transport = createMockTransport();
|
|
309
|
+
transport.send(new Uint8Array([0x01]));
|
|
310
|
+
const msg = transport.receive();
|
|
311
|
+
|
|
312
|
+
// Mock UDP socket
|
|
313
|
+
const socket = createMockUDPSocket();
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
#### Server State & Simulation
|
|
317
|
+
```typescript
|
|
318
|
+
import {
|
|
319
|
+
createMockServer,
|
|
320
|
+
createMockServerState,
|
|
321
|
+
simulateServerTick
|
|
322
|
+
} from '@quake2ts/test-utils';
|
|
323
|
+
|
|
324
|
+
// Create a mock server instance
|
|
325
|
+
const server = createMockServer();
|
|
326
|
+
|
|
327
|
+
// Initialize state
|
|
328
|
+
server.state = createMockServerState();
|
|
329
|
+
|
|
330
|
+
// Simulate a game loop tick
|
|
331
|
+
simulateServerTick(server, 0.1);
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
#### Multiplayer Helpers
|
|
335
|
+
```typescript
|
|
336
|
+
import {
|
|
337
|
+
createMultiplayerTestScenario,
|
|
338
|
+
simulatePlayerJoin,
|
|
339
|
+
simulatePlayerInput
|
|
340
|
+
} from '@quake2ts/test-utils';
|
|
341
|
+
|
|
342
|
+
// Setup a scenario with connected players
|
|
343
|
+
const scenario = createMultiplayerTestScenario(4);
|
|
344
|
+
|
|
345
|
+
// Simulate a new player joining
|
|
346
|
+
const newClient = await simulatePlayerJoin(scenario.server, { name: 'Player 5' });
|
|
347
|
+
|
|
348
|
+
// Simulate input
|
|
349
|
+
simulatePlayerInput(newClient, {
|
|
350
|
+
angles: { x: 0, y: 90, z: 0 },
|
|
351
|
+
forwardmove: 200
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
#### Snapshot Utilities
|
|
356
|
+
```typescript
|
|
357
|
+
import { createServerSnapshot, measureSnapshotSize } from '@quake2ts/test-utils';
|
|
358
|
+
|
|
359
|
+
const snapshot = createServerSnapshot(server.state, 0);
|
|
360
|
+
console.log('Snapshot size:', measureSnapshotSize(snapshot));
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### WebGL/Canvas Mocks
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
import { createMockCanvas, createMockWebGL2Context } from '@quake2ts/test-utils';
|
|
367
|
+
|
|
368
|
+
const canvas = createMockCanvas(800, 600);
|
|
369
|
+
const gl = createMockWebGL2Context(canvas);
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Playwright E2E Helpers
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { createPlaywrightTestClient } from '@quake2ts/test-utils';
|
|
376
|
+
|
|
377
|
+
const client = await createPlaywrightTestClient();
|
|
378
|
+
await client.navigate('http://localhost:3000');
|
|
379
|
+
await client.waitForGame();
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Network Simulation
|
|
383
|
+
|
|
384
|
+
Simulate network conditions in E2E tests:
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
import { simulateNetworkCondition, throttleBandwidth } from '@quake2ts/test-utils';
|
|
388
|
+
|
|
389
|
+
// Simulate a slow connection
|
|
390
|
+
const simulator = simulateNetworkCondition('slow');
|
|
391
|
+
// Apply logic to packets/requests
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Visual Regression
|
|
395
|
+
|
|
396
|
+
Capture and compare screenshots:
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
import { captureGameScreenshot, compareScreenshots } from '@quake2ts/test-utils';
|
|
400
|
+
|
|
401
|
+
// Capture screenshot
|
|
402
|
+
const buffer = await captureGameScreenshot(page, 'map-start');
|
|
403
|
+
|
|
404
|
+
// Compare against baseline
|
|
405
|
+
const result = compareScreenshots(baselineBuffer, buffer);
|
|
406
|
+
if (result.diffPercentage > 0) {
|
|
407
|
+
console.warn('Visual regression detected');
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Audio Testing
|
|
412
|
+
|
|
413
|
+
Mock and capture audio events:
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
import { setupMockAudioContext, captureAudioEvents } from '@quake2ts/test-utils';
|
|
417
|
+
|
|
418
|
+
setupMockAudioContext();
|
|
419
|
+
const context = new AudioContext();
|
|
420
|
+
|
|
421
|
+
// Run code that uses audio...
|
|
422
|
+
|
|
423
|
+
const events = captureAudioEvents(context);
|
|
424
|
+
// Verify calls like createOscillator, start, etc.
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Storage Testing
|
|
428
|
+
|
|
429
|
+
Helper for storage scenarios (Local, Session, IndexedDB):
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import { createStorageTestScenario } from '@quake2ts/test-utils';
|
|
433
|
+
|
|
434
|
+
const scenario = createStorageTestScenario('local');
|
|
435
|
+
scenario.localStorage.setItem('foo', 'bar');
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
## Features
|
|
439
|
+
|
|
440
|
+
- **Browser Mocks:** JSDOM enhancement, Pointer Lock, RAF, Performance.
|
|
441
|
+
- **Client Mocks:** Input, View, HUD, Network, Console.
|
|
442
|
+
- **Engine Mocks:** Rendering, Audio, Assets, Lighting, Particles, WebGL.
|
|
443
|
+
- **Shared Utilities:** BSP construction, Collision tracing, Math helpers, Binary mocks.
|
|
444
|
+
- **Server Utilities:** Network mocks, Server state factories, Multiplayer simulation, Snapshot analysis.
|
|
445
|
+
- **Canvas/WebGL:** Mock implementations for headless testing.
|
|
446
|
+
- **WebGPU:** Headless testing with @webgpu/dawn and comprehensive mocks.
|
|
447
|
+
- **Storage:** LocalStorage, SessionStorage, IndexedDB mocks.
|
|
448
|
+
- **Audio:** Basic Web Audio API mock with event capturing.
|
|
449
|
+
- **E2E:** Playwright wrappers, network simulation, visual regression helpers.
|
|
450
|
+
- **Game Factories:** Helpers for creating entities, items, and game state.
|
|
451
|
+
|
|
452
|
+
## Migration Guide
|
|
453
|
+
|
|
454
|
+
For detailed instructions on migrating existing tests to use this package, see [MIGRATION.md](./MIGRATION.md).
|