@react-three-dom/playwright 0.1.2 → 0.2.0
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 +1272 -152
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +565 -74
- package/dist/index.d.ts +565 -74
- package/dist/index.js +1266 -153
- package/dist/index.js.map +1 -1
- package/package.json +11 -9
package/dist/index.d.cts
CHANGED
|
@@ -67,6 +67,11 @@ interface SceneSnapshot {
|
|
|
67
67
|
objectCount: number;
|
|
68
68
|
tree: SnapshotNode;
|
|
69
69
|
}
|
|
70
|
+
declare global {
|
|
71
|
+
interface Window {
|
|
72
|
+
__R3F_DOM_DEBUG__?: boolean;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
70
75
|
|
|
71
76
|
interface WaitForSceneReadyOptions {
|
|
72
77
|
/** How many consecutive stable polls are required. Default: 3 */
|
|
@@ -77,8 +82,11 @@ interface WaitForSceneReadyOptions {
|
|
|
77
82
|
timeout?: number;
|
|
78
83
|
}
|
|
79
84
|
/**
|
|
80
|
-
* Wait until `window.__R3F_DOM__` is available
|
|
81
|
-
*
|
|
85
|
+
* Wait until `window.__R3F_DOM__` is available, `_ready === true`, and the
|
|
86
|
+
* scene's object count has stabilised over several consecutive checks.
|
|
87
|
+
*
|
|
88
|
+
* If the bridge exists but `_ready` is false and `_error` is set, this
|
|
89
|
+
* fails immediately with a rich diagnostic message instead of timing out.
|
|
82
90
|
*/
|
|
83
91
|
declare function waitForSceneReady(page: Page, options?: WaitForSceneReadyOptions): Promise<void>;
|
|
84
92
|
interface WaitForObjectOptions {
|
|
@@ -90,12 +98,14 @@ interface WaitForObjectOptions {
|
|
|
90
98
|
pollIntervalMs?: number;
|
|
91
99
|
}
|
|
92
100
|
/**
|
|
93
|
-
* Wait until `window.__R3F_DOM__` is
|
|
101
|
+
* Wait until `window.__R3F_DOM__` is ready and an object with the given
|
|
94
102
|
* testId or uuid exists in the scene.
|
|
95
103
|
*
|
|
96
104
|
* Use this instead of `waitForSceneReady` when the scene object count never
|
|
97
105
|
* stabilizes (e.g. continuous loading, animations adding/removing objects,
|
|
98
106
|
* or GLTF/models loading asynchronously).
|
|
107
|
+
*
|
|
108
|
+
* Fails fast if the bridge reports `_ready: false` with an `_error`.
|
|
99
109
|
*/
|
|
100
110
|
declare function waitForObject(page: Page, idOrUuid: string, options?: WaitForObjectOptions): Promise<void>;
|
|
101
111
|
interface WaitForIdleOptions {
|
|
@@ -111,14 +121,82 @@ interface WaitForIdleOptions {
|
|
|
111
121
|
* This works by taking successive snapshots and comparing them. When the
|
|
112
122
|
* JSON representation is unchanged for `idleFrames` consecutive rAF
|
|
113
123
|
* callbacks, the scene is considered idle.
|
|
124
|
+
*
|
|
125
|
+
* Checks `_ready === true` before starting. Fails fast if `_error` is set.
|
|
114
126
|
*/
|
|
115
127
|
declare function waitForIdle(page: Page, options?: WaitForIdleOptions): Promise<void>;
|
|
128
|
+
interface WaitForNewObjectOptions {
|
|
129
|
+
/**
|
|
130
|
+
* Only consider new objects of this Three.js type (e.g. "Mesh", "Line").
|
|
131
|
+
* If not set, any new object type qualifies.
|
|
132
|
+
*/
|
|
133
|
+
type?: string;
|
|
134
|
+
/**
|
|
135
|
+
* If provided, the new object's name must contain this substring.
|
|
136
|
+
* Useful for apps that name objects predictably (e.g. "stroke-", "wall-").
|
|
137
|
+
*/
|
|
138
|
+
nameContains?: string;
|
|
139
|
+
/**
|
|
140
|
+
* Poll interval in ms. Default: 100
|
|
141
|
+
*/
|
|
142
|
+
pollIntervalMs?: number;
|
|
143
|
+
/**
|
|
144
|
+
* Overall timeout in ms. Default: 10_000
|
|
145
|
+
*/
|
|
146
|
+
timeout?: number;
|
|
147
|
+
}
|
|
148
|
+
/** Result returned when new objects are detected. */
|
|
149
|
+
interface WaitForNewObjectResult {
|
|
150
|
+
/** Metadata of all newly added objects (matching the filter). */
|
|
151
|
+
newObjects: ObjectMetadata[];
|
|
152
|
+
/** UUIDs of the newly added objects. */
|
|
153
|
+
newUuids: string[];
|
|
154
|
+
/** Total number of new objects detected. */
|
|
155
|
+
count: number;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Wait until one or more new objects appear in the scene that were not present
|
|
159
|
+
* at the time this function was called.
|
|
160
|
+
*
|
|
161
|
+
* This is designed for drawing/annotation apps where user interactions
|
|
162
|
+
* (like `drawPath`) create new Three.js objects asynchronously.
|
|
163
|
+
*
|
|
164
|
+
* @param page Playwright Page instance
|
|
165
|
+
* @param options Filter and timing options
|
|
166
|
+
* @returns Metadata of the newly added object(s)
|
|
167
|
+
* @throws If no new objects appear within the timeout
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* // Draw a stroke, then wait for the new Line object
|
|
172
|
+
* const before = await r3f.getCount();
|
|
173
|
+
* await r3f.drawPath(points);
|
|
174
|
+
* const result = await waitForNewObject(page, { type: 'Line' });
|
|
175
|
+
* expect(result.count).toBe(1);
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
declare function waitForNewObject(page: Page, options?: WaitForNewObjectOptions): Promise<WaitForNewObjectResult>;
|
|
116
179
|
|
|
180
|
+
/** Options for R3FFixture constructor. */
|
|
181
|
+
interface R3FFixtureOptions {
|
|
182
|
+
/** Auto-enable debug logging (forwards browser [r3f-dom:*] logs to test terminal). */
|
|
183
|
+
debug?: boolean;
|
|
184
|
+
}
|
|
117
185
|
declare class R3FFixture {
|
|
118
186
|
private readonly _page;
|
|
119
|
-
|
|
187
|
+
private _debugListenerAttached;
|
|
188
|
+
constructor(_page: Page, opts?: R3FFixtureOptions);
|
|
120
189
|
/** The underlying Playwright Page. */
|
|
121
190
|
get page(): Page;
|
|
191
|
+
/**
|
|
192
|
+
* Enable debug logging. Turns on `window.__R3F_DOM_DEBUG__` in the browser
|
|
193
|
+
* and forwards all `[r3f-dom:*]` console messages to the Node.js test terminal.
|
|
194
|
+
*
|
|
195
|
+
* Call before `page.goto()` to capture setup logs, or after to capture
|
|
196
|
+
* interaction logs.
|
|
197
|
+
*/
|
|
198
|
+
enableDebug(): Promise<void>;
|
|
199
|
+
private _attachDebugListener;
|
|
122
200
|
/** Get object metadata by testId or uuid. Returns null if not found. */
|
|
123
201
|
getObject(idOrUuid: string): Promise<ObjectMetadata | null>;
|
|
124
202
|
/** Get heavy inspection data (Tier 2) by testId or uuid. */
|
|
@@ -127,27 +205,117 @@ declare class R3FFixture {
|
|
|
127
205
|
snapshot(): Promise<SceneSnapshot | null>;
|
|
128
206
|
/** Get the total number of tracked objects. */
|
|
129
207
|
getCount(): Promise<number>;
|
|
130
|
-
/**
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
208
|
+
/**
|
|
209
|
+
* Get all objects of a given Three.js type (e.g. "Mesh", "Group", "Line").
|
|
210
|
+
* Useful for BIM/CAD apps to find all walls, doors, etc. by object type.
|
|
211
|
+
*/
|
|
212
|
+
getByType(type: string): Promise<ObjectMetadata[]>;
|
|
213
|
+
/**
|
|
214
|
+
* Get objects that have a specific userData key (and optionally matching value).
|
|
215
|
+
* Useful for BIM/CAD apps where objects are tagged with metadata like
|
|
216
|
+
* `userData.category = "wall"` or `userData.floorId = 2`.
|
|
217
|
+
*/
|
|
218
|
+
getByUserData(key: string, value?: unknown): Promise<ObjectMetadata[]>;
|
|
219
|
+
/**
|
|
220
|
+
* Count objects of a given Three.js type.
|
|
221
|
+
* More efficient than `getByType(type).then(arr => arr.length)`.
|
|
222
|
+
*/
|
|
223
|
+
getCountByType(type: string): Promise<number>;
|
|
224
|
+
/**
|
|
225
|
+
* Batch lookup: get metadata for multiple objects by testId or uuid in a
|
|
226
|
+
* single browser round-trip. Returns a record from id to metadata (or null).
|
|
227
|
+
*
|
|
228
|
+
* Much more efficient than calling `getObject()` in a loop for BIM/CAD
|
|
229
|
+
* scenes with many objects.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```typescript
|
|
233
|
+
* const results = await r3f.getObjects(['wall-1', 'door-2', 'window-3']);
|
|
234
|
+
* expect(results['wall-1']).not.toBeNull();
|
|
235
|
+
* expect(results['door-2']?.type).toBe('Mesh');
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
getObjects(ids: string[]): Promise<Record<string, ObjectMetadata | null>>;
|
|
239
|
+
/**
|
|
240
|
+
* Log the scene tree to the test terminal for debugging.
|
|
241
|
+
*
|
|
242
|
+
* Prints a human-readable tree like:
|
|
243
|
+
* ```
|
|
244
|
+
* Scene "root"
|
|
245
|
+
* ├─ Mesh "chair-primary" [testId: chair-primary] visible
|
|
246
|
+
* │ └─ BoxGeometry
|
|
247
|
+
* ├─ DirectionalLight "sun-light" [testId: sun-light] visible
|
|
248
|
+
* └─ Group "furniture"
|
|
249
|
+
* ├─ Mesh "table-top" [testId: table-top] visible
|
|
250
|
+
* └─ Mesh "vase" [testId: vase] visible
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
logScene(): Promise<void>;
|
|
254
|
+
/**
|
|
255
|
+
* Click a 3D object by testId or uuid.
|
|
256
|
+
* Auto-waits for the bridge and the object to exist before clicking.
|
|
257
|
+
* @param timeout Optional auto-wait timeout in ms. Default: 5000
|
|
258
|
+
*/
|
|
259
|
+
click(idOrUuid: string, timeout?: number): Promise<void>;
|
|
260
|
+
/**
|
|
261
|
+
* Double-click a 3D object by testId or uuid.
|
|
262
|
+
* Auto-waits for the object to exist.
|
|
263
|
+
*/
|
|
264
|
+
doubleClick(idOrUuid: string, timeout?: number): Promise<void>;
|
|
265
|
+
/**
|
|
266
|
+
* Right-click / context-menu a 3D object by testId or uuid.
|
|
267
|
+
* Auto-waits for the object to exist.
|
|
268
|
+
*/
|
|
269
|
+
contextMenu(idOrUuid: string, timeout?: number): Promise<void>;
|
|
270
|
+
/**
|
|
271
|
+
* Hover over a 3D object by testId or uuid.
|
|
272
|
+
* Auto-waits for the object to exist.
|
|
273
|
+
*/
|
|
274
|
+
hover(idOrUuid: string, timeout?: number): Promise<void>;
|
|
275
|
+
/**
|
|
276
|
+
* Drag a 3D object with a world-space delta vector.
|
|
277
|
+
* Auto-waits for the object to exist.
|
|
278
|
+
*/
|
|
139
279
|
drag(idOrUuid: string, delta: {
|
|
140
280
|
x: number;
|
|
141
281
|
y: number;
|
|
142
282
|
z: number;
|
|
143
|
-
}): Promise<void>;
|
|
144
|
-
/**
|
|
283
|
+
}, timeout?: number): Promise<void>;
|
|
284
|
+
/**
|
|
285
|
+
* Dispatch a wheel/scroll event on a 3D object.
|
|
286
|
+
* Auto-waits for the object to exist.
|
|
287
|
+
*/
|
|
145
288
|
wheel(idOrUuid: string, options?: {
|
|
146
289
|
deltaY?: number;
|
|
147
290
|
deltaX?: number;
|
|
148
|
-
}): Promise<void>;
|
|
149
|
-
/**
|
|
150
|
-
|
|
291
|
+
}, timeout?: number): Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Click empty space to trigger onPointerMissed handlers.
|
|
294
|
+
* Auto-waits for the bridge to be ready.
|
|
295
|
+
*/
|
|
296
|
+
pointerMiss(timeout?: number): Promise<void>;
|
|
297
|
+
/**
|
|
298
|
+
* Draw a freeform path on the canvas. Dispatches pointerdown → N × pointermove → pointerup.
|
|
299
|
+
* Designed for canvas drawing/annotation/whiteboard apps.
|
|
300
|
+
* Auto-waits for the bridge to be ready.
|
|
301
|
+
*
|
|
302
|
+
* @param points Array of screen-space points (min 2). { x, y } in CSS pixels relative to canvas.
|
|
303
|
+
* @param options Drawing options (stepDelayMs, pointerType, clickAtEnd)
|
|
304
|
+
* @param timeout Optional auto-wait timeout in ms. Default: 5000
|
|
305
|
+
* @returns { eventCount, pointCount }
|
|
306
|
+
*/
|
|
307
|
+
drawPath(points: Array<{
|
|
308
|
+
x: number;
|
|
309
|
+
y: number;
|
|
310
|
+
pressure?: number;
|
|
311
|
+
}>, options?: {
|
|
312
|
+
stepDelayMs?: number;
|
|
313
|
+
pointerType?: 'mouse' | 'pen' | 'touch';
|
|
314
|
+
clickAtEnd?: boolean;
|
|
315
|
+
}, timeout?: number): Promise<{
|
|
316
|
+
eventCount: number;
|
|
317
|
+
pointCount: number;
|
|
318
|
+
}>;
|
|
151
319
|
/**
|
|
152
320
|
* Wait until the scene is ready — `window.__R3F_DOM__` is available and
|
|
153
321
|
* the object count has stabilised across several consecutive checks.
|
|
@@ -164,6 +332,15 @@ declare class R3FFixture {
|
|
|
164
332
|
* animation frames. Useful after triggering interactions or animations.
|
|
165
333
|
*/
|
|
166
334
|
waitForIdle(options?: WaitForIdleOptions): Promise<void>;
|
|
335
|
+
/**
|
|
336
|
+
* Wait until one or more new objects appear in the scene that were not
|
|
337
|
+
* present when this call was made. Perfect for drawing apps where
|
|
338
|
+
* `drawPath()` creates new geometry asynchronously.
|
|
339
|
+
*
|
|
340
|
+
* @param options Filter by type, nameContains, timeout, pollInterval
|
|
341
|
+
* @returns Metadata of the newly added object(s)
|
|
342
|
+
*/
|
|
343
|
+
waitForNewObject(options?: WaitForNewObjectOptions): Promise<WaitForNewObjectResult>;
|
|
167
344
|
/** Select a 3D object by testId or uuid (highlights in scene). */
|
|
168
345
|
select(idOrUuid: string): Promise<void>;
|
|
169
346
|
/** Clear the current selection. */
|
|
@@ -172,34 +349,42 @@ declare class R3FFixture {
|
|
|
172
349
|
declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & {
|
|
173
350
|
r3f: R3FFixture;
|
|
174
351
|
}, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
|
|
175
|
-
|
|
176
352
|
/**
|
|
177
|
-
*
|
|
353
|
+
* Create a custom test.extend with debug enabled for all tests:
|
|
178
354
|
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* test('chair exists', async ({ page, r3f }) => {
|
|
184
|
-
* await r3f.waitForSceneReady();
|
|
185
|
-
* await expect(r3f).toExist('chair-primary');
|
|
186
|
-
* });
|
|
355
|
+
* ```typescript
|
|
356
|
+
* import { createR3FTest } from '@react-three-dom/playwright';
|
|
357
|
+
* export const test = createR3FTest({ debug: true });
|
|
187
358
|
* ```
|
|
188
359
|
*/
|
|
360
|
+
declare function createR3FTest(options?: R3FFixtureOptions): _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & {
|
|
361
|
+
r3f: R3FFixture;
|
|
362
|
+
}, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
|
|
363
|
+
|
|
364
|
+
interface R3FMatcherReceiver {
|
|
365
|
+
page: Page;
|
|
366
|
+
getObject(idOrUuid: string): Promise<ObjectMetadata | null>;
|
|
367
|
+
inspect(idOrUuid: string): Promise<ObjectInspection | null>;
|
|
368
|
+
}
|
|
369
|
+
interface MatcherOptions {
|
|
370
|
+
timeout?: number;
|
|
371
|
+
interval?: number;
|
|
372
|
+
}
|
|
373
|
+
type Vec3Opts = MatcherOptions & {
|
|
374
|
+
tolerance?: number;
|
|
375
|
+
};
|
|
189
376
|
declare const expect: _playwright_test.Expect<{
|
|
190
|
-
toExist(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver,
|
|
377
|
+
toExist(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, opts?: MatcherOptions): Promise<{
|
|
191
378
|
pass: boolean;
|
|
192
379
|
message: () => string;
|
|
193
380
|
name: string;
|
|
194
381
|
expected: string;
|
|
195
|
-
actual:
|
|
382
|
+
actual: null;
|
|
196
383
|
}>;
|
|
197
|
-
toBeVisible(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver,
|
|
198
|
-
pass:
|
|
384
|
+
toBeVisible(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, opts?: MatcherOptions): Promise<{
|
|
385
|
+
pass: boolean;
|
|
199
386
|
message: () => string;
|
|
200
387
|
name: string;
|
|
201
|
-
expected?: undefined;
|
|
202
|
-
actual?: undefined;
|
|
203
388
|
} | {
|
|
204
389
|
pass: boolean;
|
|
205
390
|
message: () => string;
|
|
@@ -207,48 +392,141 @@ declare const expect: _playwright_test.Expect<{
|
|
|
207
392
|
expected: boolean;
|
|
208
393
|
actual: boolean;
|
|
209
394
|
}>;
|
|
210
|
-
|
|
395
|
+
toHavePosition(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expected: [number, number, number], tolOpts?: number | Vec3Opts): Promise<{
|
|
396
|
+
pass: boolean;
|
|
397
|
+
message: () => string;
|
|
398
|
+
name: string;
|
|
399
|
+
} | {
|
|
400
|
+
pass: false;
|
|
401
|
+
message: () => string;
|
|
402
|
+
name: string;
|
|
403
|
+
expected: [number, number, number];
|
|
404
|
+
actual: [number, number, number];
|
|
405
|
+
}>;
|
|
406
|
+
toHaveRotation(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expected: [number, number, number], tolOpts?: number | Vec3Opts): Promise<{
|
|
407
|
+
pass: boolean;
|
|
408
|
+
message: () => string;
|
|
409
|
+
name: string;
|
|
410
|
+
} | {
|
|
211
411
|
pass: false;
|
|
212
412
|
message: () => string;
|
|
213
413
|
name: string;
|
|
214
|
-
expected
|
|
215
|
-
actual
|
|
414
|
+
expected: [number, number, number];
|
|
415
|
+
actual: [number, number, number];
|
|
416
|
+
}>;
|
|
417
|
+
toHaveScale(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expected: [number, number, number], tolOpts?: number | Vec3Opts): Promise<{
|
|
418
|
+
pass: boolean;
|
|
419
|
+
message: () => string;
|
|
420
|
+
name: string;
|
|
421
|
+
} | {
|
|
422
|
+
pass: false;
|
|
423
|
+
message: () => string;
|
|
424
|
+
name: string;
|
|
425
|
+
expected: [number, number, number];
|
|
426
|
+
actual: [number, number, number];
|
|
427
|
+
}>;
|
|
428
|
+
toHaveType(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedType: string, opts?: MatcherOptions): Promise<{
|
|
429
|
+
pass: boolean;
|
|
430
|
+
message: () => string;
|
|
431
|
+
name: string;
|
|
216
432
|
} | {
|
|
433
|
+
pass: false;
|
|
434
|
+
message: () => string;
|
|
435
|
+
name: string;
|
|
436
|
+
expected: string;
|
|
437
|
+
actual: string;
|
|
438
|
+
}>;
|
|
439
|
+
toHaveName(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedName: string, opts?: MatcherOptions): Promise<{
|
|
217
440
|
pass: boolean;
|
|
218
441
|
message: () => string;
|
|
219
442
|
name: string;
|
|
443
|
+
} | {
|
|
444
|
+
pass: false;
|
|
445
|
+
message: () => string;
|
|
446
|
+
name: string;
|
|
220
447
|
expected: string;
|
|
221
|
-
actual:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
448
|
+
actual: string;
|
|
449
|
+
}>;
|
|
450
|
+
toHaveGeometryType(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedGeo: string, opts?: MatcherOptions): Promise<{
|
|
451
|
+
pass: boolean;
|
|
452
|
+
message: () => string;
|
|
453
|
+
name: string;
|
|
454
|
+
} | {
|
|
455
|
+
pass: false;
|
|
456
|
+
message: () => string;
|
|
457
|
+
name: string;
|
|
458
|
+
expected: string;
|
|
459
|
+
actual: string | undefined;
|
|
225
460
|
}>;
|
|
226
|
-
|
|
461
|
+
toHaveMaterialType(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedMat: string, opts?: MatcherOptions): Promise<{
|
|
462
|
+
pass: boolean;
|
|
463
|
+
message: () => string;
|
|
464
|
+
name: string;
|
|
465
|
+
} | {
|
|
227
466
|
pass: false;
|
|
228
467
|
message: () => string;
|
|
229
468
|
name: string;
|
|
230
|
-
expected
|
|
231
|
-
actual
|
|
469
|
+
expected: string;
|
|
470
|
+
actual: string | undefined;
|
|
471
|
+
}>;
|
|
472
|
+
toHaveChildCount(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedCount: number, opts?: MatcherOptions): Promise<{
|
|
473
|
+
pass: boolean;
|
|
474
|
+
message: () => string;
|
|
475
|
+
name: string;
|
|
232
476
|
} | {
|
|
233
477
|
pass: boolean;
|
|
234
478
|
message: () => string;
|
|
235
479
|
name: string;
|
|
236
|
-
expected:
|
|
237
|
-
actual:
|
|
480
|
+
expected: number;
|
|
481
|
+
actual: number;
|
|
238
482
|
}>;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
483
|
+
toHaveParent(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedParent: string, opts?: MatcherOptions): Promise<{
|
|
484
|
+
pass: boolean;
|
|
485
|
+
message: () => string;
|
|
486
|
+
name: string;
|
|
487
|
+
} | {
|
|
243
488
|
pass: false;
|
|
244
489
|
message: () => string;
|
|
245
490
|
name: string;
|
|
246
|
-
expected
|
|
247
|
-
actual
|
|
491
|
+
expected: string;
|
|
492
|
+
actual: string | null;
|
|
493
|
+
}>;
|
|
494
|
+
toHaveInstanceCount(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedCount: number, opts?: MatcherOptions): Promise<{
|
|
495
|
+
pass: boolean;
|
|
496
|
+
message: () => string;
|
|
497
|
+
name: string;
|
|
248
498
|
} | {
|
|
249
499
|
pass: boolean;
|
|
250
500
|
message: () => string;
|
|
251
501
|
name: string;
|
|
502
|
+
expected: number;
|
|
503
|
+
actual: number;
|
|
504
|
+
}>;
|
|
505
|
+
toBeInFrustum(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, opts?: MatcherOptions): Promise<{
|
|
506
|
+
pass: boolean;
|
|
507
|
+
message: () => string;
|
|
508
|
+
name: string;
|
|
509
|
+
} | {
|
|
510
|
+
pass: false;
|
|
511
|
+
message: () => string;
|
|
512
|
+
name: string;
|
|
513
|
+
expected: string;
|
|
514
|
+
actual: {
|
|
515
|
+
min: [number, number, number];
|
|
516
|
+
max: [number, number, number];
|
|
517
|
+
};
|
|
518
|
+
}>;
|
|
519
|
+
toHaveBounds(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expected: {
|
|
520
|
+
min: [number, number, number];
|
|
521
|
+
max: [number, number, number];
|
|
522
|
+
}, tolOpts?: number | Vec3Opts): Promise<{
|
|
523
|
+
pass: boolean;
|
|
524
|
+
message: () => string;
|
|
525
|
+
name: string;
|
|
526
|
+
} | {
|
|
527
|
+
pass: false;
|
|
528
|
+
message: () => string;
|
|
529
|
+
name: string;
|
|
252
530
|
expected: {
|
|
253
531
|
min: [number, number, number];
|
|
254
532
|
max: [number, number, number];
|
|
@@ -258,12 +536,43 @@ declare const expect: _playwright_test.Expect<{
|
|
|
258
536
|
max: [number, number, number];
|
|
259
537
|
};
|
|
260
538
|
}>;
|
|
261
|
-
|
|
539
|
+
toHaveColor(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedColor: string, opts?: MatcherOptions): Promise<{
|
|
540
|
+
pass: boolean;
|
|
541
|
+
message: () => string;
|
|
542
|
+
name: string;
|
|
543
|
+
} | {
|
|
544
|
+
pass: false;
|
|
545
|
+
message: () => string;
|
|
546
|
+
name: string;
|
|
547
|
+
expected: string;
|
|
548
|
+
actual: string | undefined;
|
|
549
|
+
}>;
|
|
550
|
+
toHaveOpacity(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedOpacity: number, tolOpts?: number | Vec3Opts): Promise<{
|
|
551
|
+
pass: boolean;
|
|
552
|
+
message: () => string;
|
|
553
|
+
name: string;
|
|
554
|
+
} | {
|
|
555
|
+
pass: false;
|
|
556
|
+
message: () => string;
|
|
557
|
+
name: string;
|
|
558
|
+
expected: number;
|
|
559
|
+
actual: number | undefined;
|
|
560
|
+
}>;
|
|
561
|
+
toBeTransparent(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, opts?: MatcherOptions): Promise<{
|
|
562
|
+
pass: boolean;
|
|
563
|
+
message: () => string;
|
|
564
|
+
name: string;
|
|
565
|
+
} | {
|
|
262
566
|
pass: false;
|
|
263
567
|
message: () => string;
|
|
264
568
|
name: string;
|
|
265
|
-
expected
|
|
266
|
-
actual
|
|
569
|
+
expected: boolean;
|
|
570
|
+
actual: boolean | undefined;
|
|
571
|
+
}>;
|
|
572
|
+
toHaveVertexCount(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedCount: number, opts?: MatcherOptions): Promise<{
|
|
573
|
+
pass: boolean;
|
|
574
|
+
message: () => string;
|
|
575
|
+
name: string;
|
|
267
576
|
} | {
|
|
268
577
|
pass: boolean;
|
|
269
578
|
message: () => string;
|
|
@@ -271,32 +580,214 @@ declare const expect: _playwright_test.Expect<{
|
|
|
271
580
|
expected: number;
|
|
272
581
|
actual: number;
|
|
273
582
|
}>;
|
|
583
|
+
toHaveTriangleCount(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedCount: number, opts?: MatcherOptions): Promise<{
|
|
584
|
+
pass: boolean;
|
|
585
|
+
message: () => string;
|
|
586
|
+
name: string;
|
|
587
|
+
} | {
|
|
588
|
+
pass: boolean;
|
|
589
|
+
message: () => string;
|
|
590
|
+
name: string;
|
|
591
|
+
expected: number;
|
|
592
|
+
actual: number;
|
|
593
|
+
}>;
|
|
594
|
+
toHaveUserData(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, key: string, expectedValue?: unknown, opts?: MatcherOptions): Promise<{
|
|
595
|
+
pass: boolean;
|
|
596
|
+
message: () => string;
|
|
597
|
+
name: string;
|
|
598
|
+
} | {
|
|
599
|
+
pass: false;
|
|
600
|
+
message: () => string;
|
|
601
|
+
name: string;
|
|
602
|
+
expected: {};
|
|
603
|
+
actual: unknown;
|
|
604
|
+
}>;
|
|
605
|
+
toHaveMapTexture(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedName?: string, opts?: MatcherOptions): Promise<{
|
|
606
|
+
pass: boolean;
|
|
607
|
+
message: () => string;
|
|
608
|
+
name: string;
|
|
609
|
+
} | {
|
|
610
|
+
pass: false;
|
|
611
|
+
message: () => string;
|
|
612
|
+
name: string;
|
|
613
|
+
expected: string;
|
|
614
|
+
actual: string | undefined;
|
|
615
|
+
}>;
|
|
616
|
+
/**
|
|
617
|
+
* Assert the total number of objects in the scene.
|
|
618
|
+
* Auto-retries until the count matches or timeout.
|
|
619
|
+
*
|
|
620
|
+
* @example expect(r3f).toHaveObjectCount(42);
|
|
621
|
+
* @example expect(r3f).toHaveObjectCount(42, { timeout: 10_000 });
|
|
622
|
+
*/
|
|
623
|
+
toHaveObjectCount(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, expected: number, options?: MatcherOptions): Promise<{
|
|
624
|
+
pass: false;
|
|
625
|
+
message: () => string;
|
|
626
|
+
name: string;
|
|
627
|
+
expected: number;
|
|
628
|
+
actual: number;
|
|
629
|
+
}>;
|
|
630
|
+
/**
|
|
631
|
+
* Assert the total number of objects is at least `min`.
|
|
632
|
+
* Useful for BIM scenes where the exact count may vary slightly.
|
|
633
|
+
*
|
|
634
|
+
* @example expect(r3f).toHaveObjectCountGreaterThan(10);
|
|
635
|
+
*/
|
|
636
|
+
toHaveObjectCountGreaterThan(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, min: number, options?: MatcherOptions): Promise<{
|
|
637
|
+
pass: false;
|
|
638
|
+
message: () => string;
|
|
639
|
+
name: string;
|
|
640
|
+
expected: string;
|
|
641
|
+
actual: number;
|
|
642
|
+
}>;
|
|
643
|
+
/**
|
|
644
|
+
* Assert the count of objects of a specific Three.js type.
|
|
645
|
+
* Auto-retries until the count matches or timeout.
|
|
646
|
+
*
|
|
647
|
+
* @example expect(r3f).toHaveCountByType('Mesh', 5);
|
|
648
|
+
* @example expect(r3f).toHaveCountByType('Line', 10, { timeout: 10_000 });
|
|
649
|
+
*/
|
|
650
|
+
toHaveCountByType(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, type: string, expected: number, options?: MatcherOptions): Promise<{
|
|
651
|
+
pass: false;
|
|
652
|
+
message: () => string;
|
|
653
|
+
name: string;
|
|
654
|
+
expected: number;
|
|
655
|
+
actual: number;
|
|
656
|
+
}>;
|
|
657
|
+
/**
|
|
658
|
+
* Assert the total triangle count across all meshes in the scene.
|
|
659
|
+
* Use as a performance budget guard — fail if the scene exceeds a threshold.
|
|
660
|
+
*
|
|
661
|
+
* @example expect(r3f).toHaveTotalTriangleCount(50000);
|
|
662
|
+
* @example expect(r3f).not.toHaveTotalTriangleCountGreaterThan(100000); // budget guard
|
|
663
|
+
*/
|
|
664
|
+
toHaveTotalTriangleCount(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, expected: number, options?: MatcherOptions): Promise<{
|
|
665
|
+
pass: false;
|
|
666
|
+
message: () => string;
|
|
667
|
+
name: string;
|
|
668
|
+
expected: number;
|
|
669
|
+
actual: number;
|
|
670
|
+
}>;
|
|
671
|
+
/**
|
|
672
|
+
* Assert the total triangle count is at most `max`.
|
|
673
|
+
* Perfect as a performance budget guard to prevent scene bloat.
|
|
674
|
+
*
|
|
675
|
+
* @example expect(r3f).toHaveTotalTriangleCountLessThan(100_000);
|
|
676
|
+
*/
|
|
677
|
+
toHaveTotalTriangleCountLessThan(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, max: number, options?: MatcherOptions): Promise<{
|
|
678
|
+
pass: false;
|
|
679
|
+
message: () => string;
|
|
680
|
+
name: string;
|
|
681
|
+
expected: string;
|
|
682
|
+
actual: number;
|
|
683
|
+
}>;
|
|
274
684
|
}>;
|
|
275
|
-
interface R3FMatcherReceiver {
|
|
276
|
-
getObject(idOrUuid: string): Promise<ObjectMetadata | null>;
|
|
277
|
-
inspect(idOrUuid: string): Promise<ObjectInspection | null>;
|
|
278
|
-
}
|
|
279
685
|
|
|
280
|
-
/** Click a 3D object by its testId or uuid. */
|
|
281
|
-
declare function click(page: Page, idOrUuid: string): Promise<void>;
|
|
282
|
-
/** Double-click a 3D object by its testId or uuid. */
|
|
283
|
-
declare function doubleClick(page: Page, idOrUuid: string): Promise<void>;
|
|
284
|
-
/** Right-click / context-menu a 3D object
|
|
285
|
-
declare function contextMenu(page: Page, idOrUuid: string): Promise<void>;
|
|
286
|
-
/** Hover over a 3D object
|
|
287
|
-
declare function hover(page: Page, idOrUuid: string): Promise<void>;
|
|
288
|
-
/** Drag a 3D object
|
|
686
|
+
/** Click a 3D object by its testId or uuid. Auto-waits for the object. */
|
|
687
|
+
declare function click(page: Page, idOrUuid: string, timeout?: number): Promise<void>;
|
|
688
|
+
/** Double-click a 3D object by its testId or uuid. Auto-waits for the object. */
|
|
689
|
+
declare function doubleClick(page: Page, idOrUuid: string, timeout?: number): Promise<void>;
|
|
690
|
+
/** Right-click / context-menu a 3D object. Auto-waits for the object. */
|
|
691
|
+
declare function contextMenu(page: Page, idOrUuid: string, timeout?: number): Promise<void>;
|
|
692
|
+
/** Hover over a 3D object. Auto-waits for the object. */
|
|
693
|
+
declare function hover(page: Page, idOrUuid: string, timeout?: number): Promise<void>;
|
|
694
|
+
/** Drag a 3D object with a world-space delta. Auto-waits for the object. */
|
|
289
695
|
declare function drag(page: Page, idOrUuid: string, delta: {
|
|
290
696
|
x: number;
|
|
291
697
|
y: number;
|
|
292
698
|
z: number;
|
|
293
|
-
}): Promise<void>;
|
|
294
|
-
/** Dispatch a wheel/scroll event on a 3D object. */
|
|
699
|
+
}, timeout?: number): Promise<void>;
|
|
700
|
+
/** Dispatch a wheel/scroll event on a 3D object. Auto-waits for the object. */
|
|
295
701
|
declare function wheel(page: Page, idOrUuid: string, options?: {
|
|
296
702
|
deltaY?: number;
|
|
297
703
|
deltaX?: number;
|
|
298
|
-
}): Promise<void>;
|
|
299
|
-
/** Click empty space to trigger onPointerMissed handlers. */
|
|
300
|
-
declare function pointerMiss(page: Page): Promise<void>;
|
|
704
|
+
}, timeout?: number): Promise<void>;
|
|
705
|
+
/** Click empty space to trigger onPointerMissed handlers. Auto-waits for bridge. */
|
|
706
|
+
declare function pointerMiss(page: Page, timeout?: number): Promise<void>;
|
|
707
|
+
/** Draw a freeform path on the canvas. Auto-waits for bridge. */
|
|
708
|
+
declare function drawPathOnCanvas(page: Page, points: Array<{
|
|
709
|
+
x: number;
|
|
710
|
+
y: number;
|
|
711
|
+
pressure?: number;
|
|
712
|
+
}>, options?: {
|
|
713
|
+
stepDelayMs?: number;
|
|
714
|
+
pointerType?: 'mouse' | 'pen' | 'touch';
|
|
715
|
+
clickAtEnd?: boolean;
|
|
716
|
+
}, timeout?: number): Promise<{
|
|
717
|
+
eventCount: number;
|
|
718
|
+
pointCount: number;
|
|
719
|
+
}>;
|
|
720
|
+
|
|
721
|
+
/** A 2D screen-space point in CSS pixels, relative to the canvas top-left. */
|
|
722
|
+
interface DrawPoint {
|
|
723
|
+
/** X coordinate in CSS pixels from canvas left edge. */
|
|
724
|
+
x: number;
|
|
725
|
+
/** Y coordinate in CSS pixels from canvas top edge. */
|
|
726
|
+
y: number;
|
|
727
|
+
/** Optional pressure (0–1). Default: 0.5 */
|
|
728
|
+
pressure?: number;
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Generate points along a straight line.
|
|
732
|
+
*
|
|
733
|
+
* @param start Start point
|
|
734
|
+
* @param end End point
|
|
735
|
+
* @param steps Intermediate points (excluding start/end). Default: 10
|
|
736
|
+
* @param pressure Uniform pressure. Default: 0.5
|
|
737
|
+
*/
|
|
738
|
+
declare function linePath(start: {
|
|
739
|
+
x: number;
|
|
740
|
+
y: number;
|
|
741
|
+
}, end: {
|
|
742
|
+
x: number;
|
|
743
|
+
y: number;
|
|
744
|
+
}, steps?: number, pressure?: number): DrawPoint[];
|
|
745
|
+
/**
|
|
746
|
+
* Generate points along a quadratic bezier curve.
|
|
747
|
+
*
|
|
748
|
+
* @param start Start point
|
|
749
|
+
* @param control Control point
|
|
750
|
+
* @param end End point
|
|
751
|
+
* @param steps Number of steps. Default: 20
|
|
752
|
+
* @param pressure Uniform pressure. Default: 0.5
|
|
753
|
+
*/
|
|
754
|
+
declare function curvePath(start: {
|
|
755
|
+
x: number;
|
|
756
|
+
y: number;
|
|
757
|
+
}, control: {
|
|
758
|
+
x: number;
|
|
759
|
+
y: number;
|
|
760
|
+
}, end: {
|
|
761
|
+
x: number;
|
|
762
|
+
y: number;
|
|
763
|
+
}, steps?: number, pressure?: number): DrawPoint[];
|
|
764
|
+
/**
|
|
765
|
+
* Generate points forming a rectangle.
|
|
766
|
+
*
|
|
767
|
+
* @param topLeft Top-left corner
|
|
768
|
+
* @param bottomRight Bottom-right corner
|
|
769
|
+
* @param pointsPerSide Points per side. Default: 5
|
|
770
|
+
* @param pressure Uniform pressure. Default: 0.5
|
|
771
|
+
*/
|
|
772
|
+
declare function rectPath(topLeft: {
|
|
773
|
+
x: number;
|
|
774
|
+
y: number;
|
|
775
|
+
}, bottomRight: {
|
|
776
|
+
x: number;
|
|
777
|
+
y: number;
|
|
778
|
+
}, pointsPerSide?: number, pressure?: number): DrawPoint[];
|
|
779
|
+
/**
|
|
780
|
+
* Generate points forming a circle/ellipse.
|
|
781
|
+
*
|
|
782
|
+
* @param center Center point
|
|
783
|
+
* @param radiusX Horizontal radius in CSS pixels
|
|
784
|
+
* @param radiusY Vertical radius. Default: same as radiusX
|
|
785
|
+
* @param steps Number of points. Default: 36
|
|
786
|
+
* @param pressure Uniform pressure. Default: 0.5
|
|
787
|
+
*/
|
|
788
|
+
declare function circlePath(center: {
|
|
789
|
+
x: number;
|
|
790
|
+
y: number;
|
|
791
|
+
}, radiusX: number, radiusY?: number, steps?: number, pressure?: number): DrawPoint[];
|
|
301
792
|
|
|
302
|
-
export { type ObjectInspection, type ObjectMetadata, R3FFixture, type SceneSnapshot, type SnapshotNode, type WaitForIdleOptions, type WaitForObjectOptions, type WaitForSceneReadyOptions, click, contextMenu, doubleClick, drag, expect, hover, pointerMiss, test, waitForIdle, waitForObject, waitForSceneReady, wheel };
|
|
793
|
+
export { type DrawPoint, type ObjectInspection, type ObjectMetadata, R3FFixture, type R3FFixtureOptions, type SceneSnapshot, type SnapshotNode, type WaitForIdleOptions, type WaitForNewObjectOptions, type WaitForNewObjectResult, type WaitForObjectOptions, type WaitForSceneReadyOptions, circlePath, click, contextMenu, createR3FTest, curvePath, doubleClick, drag, drawPathOnCanvas, expect, hover, linePath, pointerMiss, rectPath, test, waitForIdle, waitForNewObject, waitForObject, waitForSceneReady, wheel };
|