@react-three-dom/playwright 0.1.1 → 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 +1302 -147
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +587 -73
- package/dist/index.d.ts +587 -73
- package/dist/index.js +1295 -148
- package/dist/index.js.map +1 -1
- package/package.json +11 -9
package/dist/index.d.ts
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,10 +82,32 @@ 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>;
|
|
92
|
+
interface WaitForObjectOptions {
|
|
93
|
+
/** Time to wait for the bridge to appear. Default: 30_000 */
|
|
94
|
+
bridgeTimeout?: number;
|
|
95
|
+
/** Time to wait for the object to appear after bridge is ready. Default: 40_000 */
|
|
96
|
+
objectTimeout?: number;
|
|
97
|
+
/** Poll interval in ms. Default: 200 */
|
|
98
|
+
pollIntervalMs?: number;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Wait until `window.__R3F_DOM__` is ready and an object with the given
|
|
102
|
+
* testId or uuid exists in the scene.
|
|
103
|
+
*
|
|
104
|
+
* Use this instead of `waitForSceneReady` when the scene object count never
|
|
105
|
+
* stabilizes (e.g. continuous loading, animations adding/removing objects,
|
|
106
|
+
* or GLTF/models loading asynchronously).
|
|
107
|
+
*
|
|
108
|
+
* Fails fast if the bridge reports `_ready: false` with an `_error`.
|
|
109
|
+
*/
|
|
110
|
+
declare function waitForObject(page: Page, idOrUuid: string, options?: WaitForObjectOptions): Promise<void>;
|
|
84
111
|
interface WaitForIdleOptions {
|
|
85
112
|
/** Number of consecutive idle frames required. Default: 10 */
|
|
86
113
|
idleFrames?: number;
|
|
@@ -94,14 +121,82 @@ interface WaitForIdleOptions {
|
|
|
94
121
|
* This works by taking successive snapshots and comparing them. When the
|
|
95
122
|
* JSON representation is unchanged for `idleFrames` consecutive rAF
|
|
96
123
|
* callbacks, the scene is considered idle.
|
|
124
|
+
*
|
|
125
|
+
* Checks `_ready === true` before starting. Fails fast if `_error` is set.
|
|
97
126
|
*/
|
|
98
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>;
|
|
99
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
|
+
}
|
|
100
185
|
declare class R3FFixture {
|
|
101
186
|
private readonly _page;
|
|
102
|
-
|
|
187
|
+
private _debugListenerAttached;
|
|
188
|
+
constructor(_page: Page, opts?: R3FFixtureOptions);
|
|
103
189
|
/** The underlying Playwright Page. */
|
|
104
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;
|
|
105
200
|
/** Get object metadata by testId or uuid. Returns null if not found. */
|
|
106
201
|
getObject(idOrUuid: string): Promise<ObjectMetadata | null>;
|
|
107
202
|
/** Get heavy inspection data (Tier 2) by testId or uuid. */
|
|
@@ -110,37 +205,142 @@ declare class R3FFixture {
|
|
|
110
205
|
snapshot(): Promise<SceneSnapshot | null>;
|
|
111
206
|
/** Get the total number of tracked objects. */
|
|
112
207
|
getCount(): Promise<number>;
|
|
113
|
-
/**
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
+
*/
|
|
122
279
|
drag(idOrUuid: string, delta: {
|
|
123
280
|
x: number;
|
|
124
281
|
y: number;
|
|
125
282
|
z: number;
|
|
126
|
-
}): Promise<void>;
|
|
127
|
-
/**
|
|
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
|
+
*/
|
|
128
288
|
wheel(idOrUuid: string, options?: {
|
|
129
289
|
deltaY?: number;
|
|
130
290
|
deltaX?: number;
|
|
131
|
-
}): Promise<void>;
|
|
132
|
-
/**
|
|
133
|
-
|
|
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
|
+
}>;
|
|
134
319
|
/**
|
|
135
320
|
* Wait until the scene is ready — `window.__R3F_DOM__` is available and
|
|
136
321
|
* the object count has stabilised across several consecutive checks.
|
|
137
322
|
*/
|
|
138
323
|
waitForSceneReady(options?: WaitForSceneReadyOptions): Promise<void>;
|
|
324
|
+
/**
|
|
325
|
+
* Wait until the bridge is available and an object with the given testId or
|
|
326
|
+
* uuid exists. Use this instead of waitForSceneReady when the scene count
|
|
327
|
+
* never stabilizes (e.g. async model loading, continuous animations).
|
|
328
|
+
*/
|
|
329
|
+
waitForObject(idOrUuid: string, options?: WaitForObjectOptions): Promise<void>;
|
|
139
330
|
/**
|
|
140
331
|
* Wait until no object properties have changed for a number of consecutive
|
|
141
332
|
* animation frames. Useful after triggering interactions or animations.
|
|
142
333
|
*/
|
|
143
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>;
|
|
144
344
|
/** Select a 3D object by testId or uuid (highlights in scene). */
|
|
145
345
|
select(idOrUuid: string): Promise<void>;
|
|
146
346
|
/** Clear the current selection. */
|
|
@@ -149,34 +349,42 @@ declare class R3FFixture {
|
|
|
149
349
|
declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & {
|
|
150
350
|
r3f: R3FFixture;
|
|
151
351
|
}, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
|
|
152
|
-
|
|
153
352
|
/**
|
|
154
|
-
*
|
|
353
|
+
* Create a custom test.extend with debug enabled for all tests:
|
|
155
354
|
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
* test('chair exists', async ({ page, r3f }) => {
|
|
161
|
-
* await r3f.waitForSceneReady();
|
|
162
|
-
* await expect(r3f).toExist('chair-primary');
|
|
163
|
-
* });
|
|
355
|
+
* ```typescript
|
|
356
|
+
* import { createR3FTest } from '@react-three-dom/playwright';
|
|
357
|
+
* export const test = createR3FTest({ debug: true });
|
|
164
358
|
* ```
|
|
165
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
|
+
};
|
|
166
376
|
declare const expect: _playwright_test.Expect<{
|
|
167
|
-
toExist(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver,
|
|
377
|
+
toExist(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, opts?: MatcherOptions): Promise<{
|
|
168
378
|
pass: boolean;
|
|
169
379
|
message: () => string;
|
|
170
380
|
name: string;
|
|
171
381
|
expected: string;
|
|
172
|
-
actual:
|
|
382
|
+
actual: null;
|
|
173
383
|
}>;
|
|
174
|
-
toBeVisible(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver,
|
|
175
|
-
pass:
|
|
384
|
+
toBeVisible(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, opts?: MatcherOptions): Promise<{
|
|
385
|
+
pass: boolean;
|
|
176
386
|
message: () => string;
|
|
177
387
|
name: string;
|
|
178
|
-
expected?: undefined;
|
|
179
|
-
actual?: undefined;
|
|
180
388
|
} | {
|
|
181
389
|
pass: boolean;
|
|
182
390
|
message: () => string;
|
|
@@ -184,48 +392,141 @@ declare const expect: _playwright_test.Expect<{
|
|
|
184
392
|
expected: boolean;
|
|
185
393
|
actual: boolean;
|
|
186
394
|
}>;
|
|
187
|
-
|
|
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
|
+
} | {
|
|
188
400
|
pass: false;
|
|
189
401
|
message: () => string;
|
|
190
402
|
name: string;
|
|
191
|
-
expected
|
|
192
|
-
actual
|
|
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;
|
|
193
410
|
} | {
|
|
411
|
+
pass: false;
|
|
412
|
+
message: () => string;
|
|
413
|
+
name: string;
|
|
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<{
|
|
194
418
|
pass: boolean;
|
|
195
419
|
message: () => string;
|
|
196
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;
|
|
432
|
+
} | {
|
|
433
|
+
pass: false;
|
|
434
|
+
message: () => string;
|
|
435
|
+
name: string;
|
|
197
436
|
expected: string;
|
|
198
|
-
actual:
|
|
199
|
-
min: [number, number, number];
|
|
200
|
-
max: [number, number, number];
|
|
201
|
-
};
|
|
437
|
+
actual: string;
|
|
202
438
|
}>;
|
|
203
|
-
|
|
439
|
+
toHaveName(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedName: string, opts?: MatcherOptions): Promise<{
|
|
440
|
+
pass: boolean;
|
|
441
|
+
message: () => string;
|
|
442
|
+
name: string;
|
|
443
|
+
} | {
|
|
204
444
|
pass: false;
|
|
205
445
|
message: () => string;
|
|
206
446
|
name: string;
|
|
207
|
-
expected
|
|
208
|
-
actual
|
|
447
|
+
expected: string;
|
|
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;
|
|
209
454
|
} | {
|
|
455
|
+
pass: false;
|
|
456
|
+
message: () => string;
|
|
457
|
+
name: string;
|
|
458
|
+
expected: string;
|
|
459
|
+
actual: string | undefined;
|
|
460
|
+
}>;
|
|
461
|
+
toHaveMaterialType(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedMat: string, opts?: MatcherOptions): Promise<{
|
|
210
462
|
pass: boolean;
|
|
211
463
|
message: () => string;
|
|
212
464
|
name: string;
|
|
213
|
-
|
|
214
|
-
|
|
465
|
+
} | {
|
|
466
|
+
pass: false;
|
|
467
|
+
message: () => string;
|
|
468
|
+
name: string;
|
|
469
|
+
expected: string;
|
|
470
|
+
actual: string | undefined;
|
|
215
471
|
}>;
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
472
|
+
toHaveChildCount(this: _playwright_test.ExpectMatcherState, r3f: R3FMatcherReceiver, id: string, expectedCount: number, opts?: MatcherOptions): Promise<{
|
|
473
|
+
pass: boolean;
|
|
474
|
+
message: () => string;
|
|
475
|
+
name: string;
|
|
476
|
+
} | {
|
|
477
|
+
pass: boolean;
|
|
478
|
+
message: () => string;
|
|
479
|
+
name: string;
|
|
480
|
+
expected: number;
|
|
481
|
+
actual: number;
|
|
482
|
+
}>;
|
|
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
|
+
} | {
|
|
220
488
|
pass: false;
|
|
221
489
|
message: () => string;
|
|
222
490
|
name: string;
|
|
223
|
-
expected
|
|
224
|
-
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;
|
|
498
|
+
} | {
|
|
499
|
+
pass: boolean;
|
|
500
|
+
message: () => string;
|
|
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;
|
|
225
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<{
|
|
226
523
|
pass: boolean;
|
|
227
524
|
message: () => string;
|
|
228
525
|
name: string;
|
|
526
|
+
} | {
|
|
527
|
+
pass: false;
|
|
528
|
+
message: () => string;
|
|
529
|
+
name: string;
|
|
229
530
|
expected: {
|
|
230
531
|
min: [number, number, number];
|
|
231
532
|
max: [number, number, number];
|
|
@@ -235,12 +536,54 @@ declare const expect: _playwright_test.Expect<{
|
|
|
235
536
|
max: [number, number, number];
|
|
236
537
|
};
|
|
237
538
|
}>;
|
|
238
|
-
|
|
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
|
+
} | {
|
|
239
566
|
pass: false;
|
|
240
567
|
message: () => string;
|
|
241
568
|
name: string;
|
|
242
|
-
expected
|
|
243
|
-
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;
|
|
576
|
+
} | {
|
|
577
|
+
pass: boolean;
|
|
578
|
+
message: () => string;
|
|
579
|
+
name: string;
|
|
580
|
+
expected: number;
|
|
581
|
+
actual: number;
|
|
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;
|
|
244
587
|
} | {
|
|
245
588
|
pass: boolean;
|
|
246
589
|
message: () => string;
|
|
@@ -248,32 +591,203 @@ declare const expect: _playwright_test.Expect<{
|
|
|
248
591
|
expected: number;
|
|
249
592
|
actual: number;
|
|
250
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
|
+
}>;
|
|
251
684
|
}>;
|
|
252
|
-
interface R3FMatcherReceiver {
|
|
253
|
-
getObject(idOrUuid: string): Promise<ObjectMetadata | null>;
|
|
254
|
-
inspect(idOrUuid: string): Promise<ObjectInspection | null>;
|
|
255
|
-
}
|
|
256
685
|
|
|
257
|
-
/** Click a 3D object by its testId or uuid. */
|
|
258
|
-
declare function click(page: Page, idOrUuid: string): Promise<void>;
|
|
259
|
-
/** Double-click a 3D object by its testId or uuid. */
|
|
260
|
-
declare function doubleClick(page: Page, idOrUuid: string): Promise<void>;
|
|
261
|
-
/** Right-click / context-menu a 3D object
|
|
262
|
-
declare function contextMenu(page: Page, idOrUuid: string): Promise<void>;
|
|
263
|
-
/** Hover over a 3D object
|
|
264
|
-
declare function hover(page: Page, idOrUuid: string): Promise<void>;
|
|
265
|
-
/** 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. */
|
|
266
695
|
declare function drag(page: Page, idOrUuid: string, delta: {
|
|
267
696
|
x: number;
|
|
268
697
|
y: number;
|
|
269
698
|
z: number;
|
|
270
|
-
}): Promise<void>;
|
|
271
|
-
/** 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. */
|
|
272
701
|
declare function wheel(page: Page, idOrUuid: string, options?: {
|
|
273
702
|
deltaY?: number;
|
|
274
703
|
deltaX?: number;
|
|
275
|
-
}): Promise<void>;
|
|
276
|
-
/** Click empty space to trigger onPointerMissed handlers. */
|
|
277
|
-
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[];
|
|
278
792
|
|
|
279
|
-
export { type ObjectInspection, type ObjectMetadata, R3FFixture, type SceneSnapshot, type SnapshotNode, type WaitForIdleOptions, type WaitForSceneReadyOptions, click, contextMenu, doubleClick, drag, expect, hover, pointerMiss, test, waitForIdle, 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 };
|