@react-three-dom/playwright 0.1.2 → 0.3.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 +2146 -204
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1022 -82
- package/dist/index.d.ts +1022 -82
- package/dist/index.js +2135 -205
- package/dist/index.js.map +1 -1
- package/package.json +11 -9
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _playwright_test from '@playwright/test';
|
|
2
|
-
import { Page } from '@playwright/test';
|
|
2
|
+
import { Page, Locator } from '@playwright/test';
|
|
3
3
|
|
|
4
4
|
interface ObjectMetadata {
|
|
5
5
|
uuid: string;
|
|
@@ -12,6 +12,10 @@ interface ObjectMetadata {
|
|
|
12
12
|
vertexCount?: number;
|
|
13
13
|
triangleCount?: number;
|
|
14
14
|
instanceCount?: number;
|
|
15
|
+
fov?: number;
|
|
16
|
+
near?: number;
|
|
17
|
+
far?: number;
|
|
18
|
+
zoom?: number;
|
|
15
19
|
position: [number, number, number];
|
|
16
20
|
rotation: [number, number, number];
|
|
17
21
|
scale: [number, number, number];
|
|
@@ -19,6 +23,10 @@ interface ObjectMetadata {
|
|
|
19
23
|
childrenUuids: string[];
|
|
20
24
|
boundsDirty: boolean;
|
|
21
25
|
}
|
|
26
|
+
/** Options for inspect(). Set includeGeometryData: true to get vertex/index buffers (higher cost). */
|
|
27
|
+
interface InspectOptions {
|
|
28
|
+
includeGeometryData?: boolean;
|
|
29
|
+
}
|
|
22
30
|
interface ObjectInspection {
|
|
23
31
|
metadata: ObjectMetadata;
|
|
24
32
|
worldMatrix: number[];
|
|
@@ -39,6 +47,10 @@ interface ObjectInspection {
|
|
|
39
47
|
center: [number, number, number];
|
|
40
48
|
radius: number;
|
|
41
49
|
};
|
|
50
|
+
/** Vertex positions (x,y,z per vertex). Only when inspect(..., { includeGeometryData: true }). */
|
|
51
|
+
positionData?: number[];
|
|
52
|
+
/** Triangle indices. Only when inspect(..., { includeGeometryData: true }) and geometry is indexed. */
|
|
53
|
+
indexData?: number[];
|
|
42
54
|
};
|
|
43
55
|
material?: {
|
|
44
56
|
type: string;
|
|
@@ -67,6 +79,138 @@ interface SceneSnapshot {
|
|
|
67
79
|
objectCount: number;
|
|
68
80
|
tree: SnapshotNode;
|
|
69
81
|
}
|
|
82
|
+
interface CameraState {
|
|
83
|
+
type: string;
|
|
84
|
+
position: [number, number, number];
|
|
85
|
+
rotation: [number, number, number];
|
|
86
|
+
target: [number, number, number];
|
|
87
|
+
fov?: number;
|
|
88
|
+
near: number;
|
|
89
|
+
far: number;
|
|
90
|
+
zoom: number;
|
|
91
|
+
aspect?: number;
|
|
92
|
+
left?: number;
|
|
93
|
+
right?: number;
|
|
94
|
+
top?: number;
|
|
95
|
+
bottom?: number;
|
|
96
|
+
}
|
|
97
|
+
interface BridgeDiagnostics {
|
|
98
|
+
version: string;
|
|
99
|
+
ready: boolean;
|
|
100
|
+
error?: string;
|
|
101
|
+
objectCount: number;
|
|
102
|
+
meshCount: number;
|
|
103
|
+
groupCount: number;
|
|
104
|
+
lightCount: number;
|
|
105
|
+
cameraCount: number;
|
|
106
|
+
materializedDomNodes: number;
|
|
107
|
+
maxDomNodes: number;
|
|
108
|
+
canvasWidth: number;
|
|
109
|
+
canvasHeight: number;
|
|
110
|
+
webglRenderer: string;
|
|
111
|
+
dirtyQueueSize: number;
|
|
112
|
+
}
|
|
113
|
+
declare global {
|
|
114
|
+
interface Window {
|
|
115
|
+
__R3F_DOM_DEBUG__?: boolean;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @module reporter
|
|
121
|
+
*
|
|
122
|
+
* Rich terminal reporter for Playwright tests. Outputs ANSI-colored status
|
|
123
|
+
* messages for bridge lifecycle events (waiting, connected, error), scene
|
|
124
|
+
* readiness, object lookups (with fuzzy-match suggestions on miss),
|
|
125
|
+
* interaction timings, assertion failures, and full bridge diagnostics.
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Formatted terminal reporter for react-three-dom Playwright tests.
|
|
130
|
+
* Logs bridge lifecycle, scene readiness, interaction timings, assertion
|
|
131
|
+
* failures, and full diagnostics with ANSI colors.
|
|
132
|
+
*/
|
|
133
|
+
declare class R3FReporter {
|
|
134
|
+
private readonly _page;
|
|
135
|
+
private _enabled;
|
|
136
|
+
private _canvasId?;
|
|
137
|
+
constructor(_page: Page, enabled?: boolean, canvasId?: string);
|
|
138
|
+
logBridgeWaiting(): void;
|
|
139
|
+
logBridgeConnected(diag?: BridgeDiagnostics): void;
|
|
140
|
+
logBridgeError(error: string): void;
|
|
141
|
+
logSceneReady(objectCount: number): void;
|
|
142
|
+
logObjectFound(idOrUuid: string, type: string, name?: string): void;
|
|
143
|
+
logObjectNotFound(idOrUuid: string, suggestions?: Array<{
|
|
144
|
+
testId?: string;
|
|
145
|
+
name: string;
|
|
146
|
+
uuid: string;
|
|
147
|
+
}>): void;
|
|
148
|
+
logInteraction(action: string, idOrUuid: string, extra?: string): void;
|
|
149
|
+
logInteractionDone(action: string, idOrUuid: string, durationMs: number): void;
|
|
150
|
+
logAssertionFailure(matcherName: string, id: string, detail: string, diag?: BridgeDiagnostics): void;
|
|
151
|
+
logDiagnostics(): Promise<void>;
|
|
152
|
+
fetchDiagnostics(): Promise<BridgeDiagnostics | null>;
|
|
153
|
+
fetchFuzzyMatches(query: string, limit?: number): Promise<Array<{
|
|
154
|
+
testId?: string;
|
|
155
|
+
name: string;
|
|
156
|
+
uuid: string;
|
|
157
|
+
}>>;
|
|
158
|
+
private _printDiagnosticsSummary;
|
|
159
|
+
private _printDiagnosticsFull;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @module diffSnapshots
|
|
164
|
+
*
|
|
165
|
+
* Pure scene-diff utility. Compares two {@link SceneSnapshot}s by UUID and
|
|
166
|
+
* returns added nodes, removed nodes, and per-field property changes
|
|
167
|
+
* (name, type, testId, visible, position, rotation, scale).
|
|
168
|
+
*
|
|
169
|
+
* Stateless and side-effect-free — safe to call from any context.
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
/** Describes a single property change on an object that exists in both snapshots. */
|
|
173
|
+
interface SceneDiffChange {
|
|
174
|
+
uuid: string;
|
|
175
|
+
field: string;
|
|
176
|
+
from: unknown;
|
|
177
|
+
to: unknown;
|
|
178
|
+
}
|
|
179
|
+
/** Result of diffing two scene snapshots. */
|
|
180
|
+
interface SceneDiff {
|
|
181
|
+
/** Nodes present in `after` but not in `before` (from `after` tree). */
|
|
182
|
+
added: SnapshotNode[];
|
|
183
|
+
/** Nodes present in `before` but not in `after` (from `before` tree). */
|
|
184
|
+
removed: SnapshotNode[];
|
|
185
|
+
/** Property changes for nodes that exist in both; each entry is one field that changed. */
|
|
186
|
+
changed: SceneDiffChange[];
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Compare two scene snapshots and return added nodes, removed nodes, and
|
|
190
|
+
* property changes for nodes that exist in both.
|
|
191
|
+
*
|
|
192
|
+
* - **added**: nodes in `after` whose uuid was not in `before`.
|
|
193
|
+
* - **removed**: nodes in `before` whose uuid was not in `after`.
|
|
194
|
+
* - **changed**: for each uuid present in both, lists field-level changes
|
|
195
|
+
* (name, type, testId, visible, position, rotation, scale).
|
|
196
|
+
*/
|
|
197
|
+
declare function diffSnapshots(before: SceneSnapshot, after: SceneSnapshot): SceneDiff;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @module waiters
|
|
201
|
+
*
|
|
202
|
+
* Polling-based wait utilities for Playwright tests. Each waiter polls the
|
|
203
|
+
* `window.__R3F_DOM__` bridge until a condition is met or a timeout fires.
|
|
204
|
+
*
|
|
205
|
+
* - {@link waitForSceneReady} — bridge ready + object count stabilised
|
|
206
|
+
* - {@link waitForObject} — bridge ready + specific object exists
|
|
207
|
+
* - {@link waitForIdle} — no property changes for N consecutive frames
|
|
208
|
+
* - {@link waitForNewObject} — new object(s) appear after a baseline snapshot
|
|
209
|
+
* - {@link waitForObjectRemoved} — object no longer in the scene
|
|
210
|
+
*
|
|
211
|
+
* All waiters fail fast with a rich diagnostic if the bridge reports an
|
|
212
|
+
* `_error` state, preventing silent timeouts.
|
|
213
|
+
*/
|
|
70
214
|
|
|
71
215
|
interface WaitForSceneReadyOptions {
|
|
72
216
|
/** How many consecutive stable polls are required. Default: 3 */
|
|
@@ -77,10 +221,15 @@ interface WaitForSceneReadyOptions {
|
|
|
77
221
|
timeout?: number;
|
|
78
222
|
}
|
|
79
223
|
/**
|
|
80
|
-
* Wait until `window.__R3F_DOM__` is available
|
|
81
|
-
*
|
|
224
|
+
* Wait until `window.__R3F_DOM__` is available, `_ready === true`, and the
|
|
225
|
+
* scene's object count has stabilised over several consecutive checks.
|
|
226
|
+
*
|
|
227
|
+
* If the bridge exists but `_ready` is false and `_error` is set, this
|
|
228
|
+
* fails immediately with a rich diagnostic message instead of timing out.
|
|
82
229
|
*/
|
|
83
|
-
declare function waitForSceneReady(page: Page, options?: WaitForSceneReadyOptions
|
|
230
|
+
declare function waitForSceneReady(page: Page, options?: WaitForSceneReadyOptions & {
|
|
231
|
+
canvasId?: string;
|
|
232
|
+
}): Promise<void>;
|
|
84
233
|
interface WaitForObjectOptions {
|
|
85
234
|
/** Time to wait for the bridge to appear. Default: 30_000 */
|
|
86
235
|
bridgeTimeout?: number;
|
|
@@ -90,14 +239,18 @@ interface WaitForObjectOptions {
|
|
|
90
239
|
pollIntervalMs?: number;
|
|
91
240
|
}
|
|
92
241
|
/**
|
|
93
|
-
* Wait until `window.__R3F_DOM__` is
|
|
242
|
+
* Wait until `window.__R3F_DOM__` is ready and an object with the given
|
|
94
243
|
* testId or uuid exists in the scene.
|
|
95
244
|
*
|
|
96
245
|
* Use this instead of `waitForSceneReady` when the scene object count never
|
|
97
246
|
* stabilizes (e.g. continuous loading, animations adding/removing objects,
|
|
98
247
|
* or GLTF/models loading asynchronously).
|
|
248
|
+
*
|
|
249
|
+
* Fails fast if the bridge reports `_ready: false` with an `_error`.
|
|
99
250
|
*/
|
|
100
|
-
declare function waitForObject(page: Page, idOrUuid: string, options?: WaitForObjectOptions
|
|
251
|
+
declare function waitForObject(page: Page, idOrUuid: string, options?: WaitForObjectOptions & {
|
|
252
|
+
canvasId?: string;
|
|
253
|
+
}): Promise<void>;
|
|
101
254
|
interface WaitForIdleOptions {
|
|
102
255
|
/** Number of consecutive idle frames required. Default: 10 */
|
|
103
256
|
idleFrames?: number;
|
|
@@ -111,46 +264,317 @@ interface WaitForIdleOptions {
|
|
|
111
264
|
* This works by taking successive snapshots and comparing them. When the
|
|
112
265
|
* JSON representation is unchanged for `idleFrames` consecutive rAF
|
|
113
266
|
* callbacks, the scene is considered idle.
|
|
267
|
+
*
|
|
268
|
+
* Checks `_ready === true` before starting. Fails fast if `_error` is set.
|
|
269
|
+
*/
|
|
270
|
+
declare function waitForIdle(page: Page, options?: WaitForIdleOptions & {
|
|
271
|
+
canvasId?: string;
|
|
272
|
+
}): Promise<void>;
|
|
273
|
+
interface WaitForNewObjectOptions {
|
|
274
|
+
/**
|
|
275
|
+
* Only consider new objects of this Three.js type (e.g. "Mesh", "Line").
|
|
276
|
+
* If not set, any new object type qualifies.
|
|
277
|
+
*/
|
|
278
|
+
type?: string;
|
|
279
|
+
/**
|
|
280
|
+
* If provided, the new object's name must contain this substring.
|
|
281
|
+
* Useful for apps that name objects predictably (e.g. "stroke-", "wall-").
|
|
282
|
+
*/
|
|
283
|
+
nameContains?: string;
|
|
284
|
+
/**
|
|
285
|
+
* Poll interval in ms. Default: 100
|
|
286
|
+
*/
|
|
287
|
+
pollIntervalMs?: number;
|
|
288
|
+
/**
|
|
289
|
+
* Overall timeout in ms. Default: 10_000
|
|
290
|
+
*/
|
|
291
|
+
timeout?: number;
|
|
292
|
+
}
|
|
293
|
+
/** Result returned when new objects are detected. */
|
|
294
|
+
interface WaitForNewObjectResult {
|
|
295
|
+
/** Metadata of all newly added objects (matching the filter). */
|
|
296
|
+
newObjects: ObjectMetadata[];
|
|
297
|
+
/** UUIDs of the newly added objects. */
|
|
298
|
+
newUuids: string[];
|
|
299
|
+
/** Total number of new objects detected. */
|
|
300
|
+
count: number;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Wait until one or more new objects appear in the scene that were not present
|
|
304
|
+
* at the time this function was called.
|
|
305
|
+
*
|
|
306
|
+
* This is designed for drawing/annotation apps where user interactions
|
|
307
|
+
* (like `drawPath`) create new Three.js objects asynchronously.
|
|
308
|
+
*
|
|
309
|
+
* @param page Playwright Page instance
|
|
310
|
+
* @param options Filter and timing options
|
|
311
|
+
* @returns Metadata of the newly added object(s)
|
|
312
|
+
* @throws If no new objects appear within the timeout
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* ```typescript
|
|
316
|
+
* // Draw a stroke, then wait for the new Line object
|
|
317
|
+
* const before = await r3f.getCount();
|
|
318
|
+
* await r3f.drawPath(points);
|
|
319
|
+
* const result = await waitForNewObject(page, { type: 'Line' });
|
|
320
|
+
* expect(result.count).toBe(1);
|
|
321
|
+
* ```
|
|
114
322
|
*/
|
|
115
|
-
declare function
|
|
323
|
+
declare function waitForNewObject(page: Page, options?: WaitForNewObjectOptions & {
|
|
324
|
+
canvasId?: string;
|
|
325
|
+
}): Promise<WaitForNewObjectResult>;
|
|
326
|
+
interface WaitForObjectRemovedOptions {
|
|
327
|
+
/** Time to wait for the bridge to appear. Default: 30_000 */
|
|
328
|
+
bridgeTimeout?: number;
|
|
329
|
+
/** Poll interval in ms. Default: 100 */
|
|
330
|
+
pollIntervalMs?: number;
|
|
331
|
+
/** Overall timeout in ms (after bridge is ready). Default: 10_000 */
|
|
332
|
+
timeout?: number;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Wait until the bridge is ready and an object with the given testId or uuid
|
|
336
|
+
* is no longer in the scene. Use for delete flows (e.g. user deletes an object,
|
|
337
|
+
* then you assert it's gone).
|
|
338
|
+
*
|
|
339
|
+
* @param page Playwright Page instance
|
|
340
|
+
* @param idOrUuid testId or uuid of the object that should be removed
|
|
341
|
+
* @param options Timing options
|
|
342
|
+
* @throws If the object is still present after the timeout
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```ts
|
|
346
|
+
* await r3f.click('delete-button');
|
|
347
|
+
* await r3f.waitForObjectRemoved('item-to-delete');
|
|
348
|
+
* await expect(r3f).not.toExist('item-to-delete');
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
declare function waitForObjectRemoved(page: Page, idOrUuid: string, options?: WaitForObjectRemovedOptions & {
|
|
352
|
+
canvasId?: string;
|
|
353
|
+
}): Promise<void>;
|
|
116
354
|
|
|
355
|
+
/** Options for R3FFixture constructor. */
|
|
356
|
+
interface R3FFixtureOptions {
|
|
357
|
+
/** Auto-enable debug logging (forwards browser [r3f-dom:*] logs to test terminal). */
|
|
358
|
+
debug?: boolean;
|
|
359
|
+
/**
|
|
360
|
+
* Enable rich diagnostic reporting in the terminal.
|
|
361
|
+
* Logs bridge status, scene readiness, interaction details, and
|
|
362
|
+
* failure context automatically. Default: true.
|
|
363
|
+
*/
|
|
364
|
+
report?: boolean;
|
|
365
|
+
/** Target a specific canvas by its canvasId. When omitted, uses the default bridge. */
|
|
366
|
+
canvasId?: string;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Main API object provided to Playwright tests for interacting with a
|
|
370
|
+
* react-three-dom scene. Wraps queries, interactions, waiters, snapshot
|
|
371
|
+
* diffing, and rich terminal diagnostics. Supports multi-canvas apps
|
|
372
|
+
* via {@link R3FFixture.forCanvas}.
|
|
373
|
+
*/
|
|
117
374
|
declare class R3FFixture {
|
|
118
375
|
private readonly _page;
|
|
119
|
-
|
|
376
|
+
private _debugListenerAttached;
|
|
377
|
+
private readonly _reporter;
|
|
378
|
+
/** Canvas ID for multi-canvas apps. Undefined = default bridge. */
|
|
379
|
+
readonly canvasId?: string;
|
|
380
|
+
constructor(_page: Page, opts?: R3FFixtureOptions);
|
|
120
381
|
/** The underlying Playwright Page. */
|
|
121
382
|
get page(): Page;
|
|
383
|
+
/** Access the reporter for custom diagnostic logging. */
|
|
384
|
+
get reporter(): R3FReporter;
|
|
385
|
+
/**
|
|
386
|
+
* Create a scoped fixture targeting a specific canvas instance.
|
|
387
|
+
* All queries, interactions, and assertions on the returned fixture
|
|
388
|
+
* will use `window.__R3F_DOM_INSTANCES__[canvasId]` instead of
|
|
389
|
+
* `window.__R3F_DOM__`.
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```typescript
|
|
393
|
+
* const mainR3f = r3f.forCanvas('main-viewport');
|
|
394
|
+
* const minimapR3f = r3f.forCanvas('minimap');
|
|
395
|
+
* await mainR3f.click('building-42');
|
|
396
|
+
* await expect(minimapR3f).toExist('building-42-marker');
|
|
397
|
+
* ```
|
|
398
|
+
*/
|
|
399
|
+
forCanvas(canvasId: string): R3FFixture;
|
|
400
|
+
/**
|
|
401
|
+
* List all active canvas IDs registered on the page.
|
|
402
|
+
* Returns an empty array if only the default (unnamed) bridge is active.
|
|
403
|
+
*/
|
|
404
|
+
getCanvasIds(): Promise<string[]>;
|
|
405
|
+
/**
|
|
406
|
+
* Enable debug logging. Turns on `window.__R3F_DOM_DEBUG__` in the browser
|
|
407
|
+
* and forwards all `[r3f-dom:*]` console messages to the Node.js test terminal.
|
|
408
|
+
*
|
|
409
|
+
* Call before `page.goto()` to capture setup logs, or after to capture
|
|
410
|
+
* interaction logs.
|
|
411
|
+
*/
|
|
412
|
+
enableDebug(): Promise<void>;
|
|
413
|
+
private _attachDebugListener;
|
|
122
414
|
/** Get object metadata by testId or uuid. Returns null if not found. */
|
|
123
415
|
getObject(idOrUuid: string): Promise<ObjectMetadata | null>;
|
|
124
|
-
/** Get
|
|
125
|
-
|
|
416
|
+
/** Get object metadata by testId (userData.testId). Returns null if not found. */
|
|
417
|
+
getByTestId(testId: string): Promise<ObjectMetadata | null>;
|
|
418
|
+
/** Get object metadata by UUID. Returns null if not found. */
|
|
419
|
+
getByUuid(uuid: string): Promise<ObjectMetadata | null>;
|
|
420
|
+
/** Get all objects with the given name (names are not unique in Three.js). */
|
|
421
|
+
getByName(name: string): Promise<ObjectMetadata[]>;
|
|
422
|
+
/** Get direct children of an object by testId or uuid. */
|
|
423
|
+
getChildren(idOrUuid: string): Promise<ObjectMetadata[]>;
|
|
424
|
+
/** Get parent of an object by testId or uuid. Returns null if root or not found. */
|
|
425
|
+
getParent(idOrUuid: string): Promise<ObjectMetadata | null>;
|
|
426
|
+
/** Get heavy inspection data (Tier 2) by testId or uuid. Pass { includeGeometryData: true } to include vertex positions and triangle indices. */
|
|
427
|
+
inspect(idOrUuid: string, options?: {
|
|
428
|
+
includeGeometryData?: boolean;
|
|
429
|
+
}): Promise<ObjectInspection | null>;
|
|
430
|
+
/**
|
|
431
|
+
* Get world-space position [x, y, z] of an object (from its world matrix).
|
|
432
|
+
* Use for nested objects where local position differs from world position.
|
|
433
|
+
*/
|
|
434
|
+
getWorldPosition(idOrUuid: string): Promise<[number, number, number] | null>;
|
|
126
435
|
/** Take a full scene snapshot. */
|
|
127
436
|
snapshot(): Promise<SceneSnapshot | null>;
|
|
437
|
+
/**
|
|
438
|
+
* Compare two scene snapshots: returns added nodes, removed nodes, and
|
|
439
|
+
* property changes (name, type, testId, visible, position, rotation, scale).
|
|
440
|
+
* Use after taking snapshots before/after an action to assert on scene changes.
|
|
441
|
+
*/
|
|
442
|
+
diffSnapshots(before: SceneSnapshot, after: SceneSnapshot): SceneDiff;
|
|
443
|
+
/**
|
|
444
|
+
* Run an async action and return how many objects were added and removed
|
|
445
|
+
* compared to before the action. Uses snapshots before/after so add and
|
|
446
|
+
* remove are both counted correctly when both happen.
|
|
447
|
+
*/
|
|
448
|
+
trackObjectCount(action: () => Promise<void>): Promise<{
|
|
449
|
+
added: number;
|
|
450
|
+
removed: number;
|
|
451
|
+
}>;
|
|
128
452
|
/** Get the total number of tracked objects. */
|
|
129
453
|
getCount(): Promise<number>;
|
|
130
|
-
/**
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
454
|
+
/**
|
|
455
|
+
* Return a Playwright locator for the R3F canvas element the bridge is attached to.
|
|
456
|
+
* The canvas has `data-r3f-canvas` set by the bridge (value is the canvasId or "true").
|
|
457
|
+
*/
|
|
458
|
+
getCanvasLocator(): Locator;
|
|
459
|
+
/**
|
|
460
|
+
* Get all objects of a given Three.js type (e.g. "Mesh", "Group", "Line").
|
|
461
|
+
*/
|
|
462
|
+
getByType(type: string): Promise<ObjectMetadata[]>;
|
|
463
|
+
/**
|
|
464
|
+
* Get all objects with a given geometry type (e.g. "BoxGeometry", "BufferGeometry").
|
|
465
|
+
*/
|
|
466
|
+
getByGeometryType(type: string): Promise<ObjectMetadata[]>;
|
|
467
|
+
/**
|
|
468
|
+
* Get all objects with a given material type (e.g. "MeshStandardMaterial").
|
|
469
|
+
*/
|
|
470
|
+
getByMaterialType(type: string): Promise<ObjectMetadata[]>;
|
|
471
|
+
/**
|
|
472
|
+
* Get objects that have a specific userData key (and optionally matching value).
|
|
473
|
+
*/
|
|
474
|
+
getByUserData(key: string, value?: unknown): Promise<ObjectMetadata[]>;
|
|
475
|
+
/**
|
|
476
|
+
* Count objects of a given Three.js type.
|
|
477
|
+
*/
|
|
478
|
+
getCountByType(type: string): Promise<number>;
|
|
479
|
+
/**
|
|
480
|
+
* Batch lookup: get metadata for multiple objects by testId or uuid in a
|
|
481
|
+
* single browser round-trip.
|
|
482
|
+
*/
|
|
483
|
+
getObjects(ids: string[]): Promise<Record<string, ObjectMetadata | null>>;
|
|
484
|
+
/**
|
|
485
|
+
* Log the scene tree to the test terminal for debugging.
|
|
486
|
+
*
|
|
487
|
+
* Prints a human-readable tree like:
|
|
488
|
+
* ```
|
|
489
|
+
* Scene "root"
|
|
490
|
+
* ├─ Mesh "chair-primary" [testId: chair-primary] visible
|
|
491
|
+
* │ └─ BoxGeometry
|
|
492
|
+
* ├─ DirectionalLight "sun-light" [testId: sun-light] visible
|
|
493
|
+
* └─ Group "furniture"
|
|
494
|
+
* ├─ Mesh "table-top" [testId: table-top] visible
|
|
495
|
+
* └─ Mesh "vase" [testId: vase] visible
|
|
496
|
+
* ```
|
|
497
|
+
*/
|
|
498
|
+
logScene(): Promise<void>;
|
|
499
|
+
/**
|
|
500
|
+
* Click a 3D object by testId or uuid.
|
|
501
|
+
* Auto-waits for the bridge and the object to exist before clicking.
|
|
502
|
+
* @param timeout Optional auto-wait timeout in ms. Default: 5000
|
|
503
|
+
*/
|
|
504
|
+
click(idOrUuid: string, timeout?: number): Promise<void>;
|
|
505
|
+
/**
|
|
506
|
+
* Double-click a 3D object by testId or uuid.
|
|
507
|
+
* Auto-waits for the object to exist.
|
|
508
|
+
*/
|
|
509
|
+
doubleClick(idOrUuid: string, timeout?: number): Promise<void>;
|
|
510
|
+
/**
|
|
511
|
+
* Right-click / context-menu a 3D object by testId or uuid.
|
|
512
|
+
* Auto-waits for the object to exist.
|
|
513
|
+
*/
|
|
514
|
+
contextMenu(idOrUuid: string, timeout?: number): Promise<void>;
|
|
515
|
+
/**
|
|
516
|
+
* Hover over a 3D object by testId or uuid.
|
|
517
|
+
* Auto-waits for the object to exist.
|
|
518
|
+
*/
|
|
519
|
+
hover(idOrUuid: string, timeout?: number): Promise<void>;
|
|
520
|
+
/**
|
|
521
|
+
* Unhover / pointer-leave — resets hover state by moving pointer off-canvas.
|
|
522
|
+
* Auto-waits for the bridge to be ready.
|
|
523
|
+
*/
|
|
524
|
+
unhover(timeout?: number): Promise<void>;
|
|
525
|
+
/**
|
|
526
|
+
* Drag a 3D object with a world-space delta vector.
|
|
527
|
+
* Auto-waits for the object to exist.
|
|
528
|
+
*/
|
|
139
529
|
drag(idOrUuid: string, delta: {
|
|
140
530
|
x: number;
|
|
141
531
|
y: number;
|
|
142
532
|
z: number;
|
|
143
|
-
}): Promise<void>;
|
|
144
|
-
/**
|
|
533
|
+
}, timeout?: number): Promise<void>;
|
|
534
|
+
/**
|
|
535
|
+
* Dispatch a wheel/scroll event on a 3D object.
|
|
536
|
+
* Auto-waits for the object to exist.
|
|
537
|
+
*/
|
|
145
538
|
wheel(idOrUuid: string, options?: {
|
|
146
539
|
deltaY?: number;
|
|
147
540
|
deltaX?: number;
|
|
148
|
-
}): Promise<void>;
|
|
149
|
-
/**
|
|
150
|
-
|
|
541
|
+
}, timeout?: number): Promise<void>;
|
|
542
|
+
/**
|
|
543
|
+
* Click empty space to trigger onPointerMissed handlers.
|
|
544
|
+
* Auto-waits for the bridge to be ready.
|
|
545
|
+
*/
|
|
546
|
+
pointerMiss(timeout?: number): Promise<void>;
|
|
547
|
+
/**
|
|
548
|
+
* Draw a freeform path on the canvas. Dispatches pointerdown → N × pointermove → pointerup.
|
|
549
|
+
* Designed for canvas drawing/annotation/whiteboard apps.
|
|
550
|
+
* Auto-waits for the bridge to be ready.
|
|
551
|
+
*
|
|
552
|
+
* @param points Array of screen-space points (min 2). { x, y } in CSS pixels relative to canvas.
|
|
553
|
+
* @param options Drawing options (stepDelayMs, pointerType, clickAtEnd)
|
|
554
|
+
* @param timeout Optional auto-wait timeout in ms. Default: 5000
|
|
555
|
+
* @returns { eventCount, pointCount }
|
|
556
|
+
*/
|
|
557
|
+
drawPath(points: Array<{
|
|
558
|
+
x: number;
|
|
559
|
+
y: number;
|
|
560
|
+
pressure?: number;
|
|
561
|
+
}>, options?: {
|
|
562
|
+
stepDelayMs?: number;
|
|
563
|
+
pointerType?: 'mouse' | 'pen' | 'touch';
|
|
564
|
+
clickAtEnd?: boolean;
|
|
565
|
+
}, timeout?: number): Promise<{
|
|
566
|
+
eventCount: number;
|
|
567
|
+
pointCount: number;
|
|
568
|
+
}>;
|
|
569
|
+
/**
|
|
570
|
+
* Get the current camera state (position, rotation, fov, near, far, zoom, target).
|
|
571
|
+
* Auto-waits for the bridge to be ready.
|
|
572
|
+
*/
|
|
573
|
+
getCameraState(timeout?: number): Promise<CameraState>;
|
|
151
574
|
/**
|
|
152
575
|
* Wait until the scene is ready — `window.__R3F_DOM__` is available and
|
|
153
576
|
* the object count has stabilised across several consecutive checks.
|
|
577
|
+
* Logs bridge connection and scene readiness to the terminal.
|
|
154
578
|
*/
|
|
155
579
|
waitForSceneReady(options?: WaitForSceneReadyOptions): Promise<void>;
|
|
156
580
|
/**
|
|
@@ -164,42 +588,106 @@ declare class R3FFixture {
|
|
|
164
588
|
* animation frames. Useful after triggering interactions or animations.
|
|
165
589
|
*/
|
|
166
590
|
waitForIdle(options?: WaitForIdleOptions): Promise<void>;
|
|
591
|
+
/**
|
|
592
|
+
* Wait until one or more new objects appear in the scene that were not
|
|
593
|
+
* present when this call was made. Perfect for drawing apps where
|
|
594
|
+
* `drawPath()` creates new geometry asynchronously.
|
|
595
|
+
*
|
|
596
|
+
* @param options Filter by type, nameContains, timeout, pollInterval
|
|
597
|
+
* @returns Metadata of the newly added object(s)
|
|
598
|
+
*/
|
|
599
|
+
waitForNewObject(options?: WaitForNewObjectOptions): Promise<WaitForNewObjectResult>;
|
|
600
|
+
/**
|
|
601
|
+
* Wait until an object (by testId or uuid) is no longer in the scene.
|
|
602
|
+
* Use for delete flows: trigger removal, then wait until the object is gone.
|
|
603
|
+
*/
|
|
604
|
+
waitForObjectRemoved(idOrUuid: string, options?: WaitForObjectRemovedOptions): Promise<void>;
|
|
167
605
|
/** Select a 3D object by testId or uuid (highlights in scene). */
|
|
168
606
|
select(idOrUuid: string): Promise<void>;
|
|
169
607
|
/** Clear the current selection. */
|
|
170
608
|
clearSelection(): Promise<void>;
|
|
609
|
+
/**
|
|
610
|
+
* Fetch full bridge diagnostics (version, object counts, GPU info, etc.).
|
|
611
|
+
* Returns null if the bridge is not available.
|
|
612
|
+
*/
|
|
613
|
+
getDiagnostics(): Promise<BridgeDiagnostics | null>;
|
|
614
|
+
/**
|
|
615
|
+
* Print a full diagnostics report to the terminal.
|
|
616
|
+
* Useful at the start of a test suite or when debugging failures.
|
|
617
|
+
*/
|
|
618
|
+
logDiagnostics(): Promise<void>;
|
|
171
619
|
}
|
|
172
620
|
declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & {
|
|
173
621
|
r3f: R3FFixture;
|
|
174
622
|
}, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
|
|
623
|
+
/**
|
|
624
|
+
* Create a custom test.extend with debug enabled for all tests:
|
|
625
|
+
*
|
|
626
|
+
* ```typescript
|
|
627
|
+
* import { createR3FTest } from '@react-three-dom/playwright';
|
|
628
|
+
* export const test = createR3FTest({ debug: true });
|
|
629
|
+
* ```
|
|
630
|
+
*/
|
|
631
|
+
declare function createR3FTest(options?: R3FFixtureOptions): _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & {
|
|
632
|
+
r3f: R3FFixture;
|
|
633
|
+
}, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
|
|
175
634
|
|
|
176
635
|
/**
|
|
177
|
-
*
|
|
636
|
+
* @module assertions
|
|
178
637
|
*
|
|
179
|
-
*
|
|
180
|
-
* ```ts
|
|
181
|
-
* import { test, expect } from '@react-three-dom/playwright';
|
|
638
|
+
* Custom Playwright `expect` matchers for 3D scene testing via react-three-dom.
|
|
182
639
|
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
640
|
+
* Every matcher auto-retries until the assertion passes or the timeout
|
|
641
|
+
* expires, matching Playwright's built-in assertion behaviour.
|
|
642
|
+
*
|
|
643
|
+
* **Tier 1 — Metadata:** toExist, toBeVisible, toHavePosition,
|
|
644
|
+
* toHaveWorldPosition, toHaveRotation, toHaveScale, toHaveType, toHaveName,
|
|
645
|
+
* toHaveGeometryType, toHaveMaterialType, toHaveChildCount, toHaveParent,
|
|
646
|
+
* toHaveInstanceCount
|
|
647
|
+
*
|
|
648
|
+
* **Tier 2 — Inspection:** toBeInFrustum, toHaveBounds, toHaveColor,
|
|
649
|
+
* toHaveOpacity, toBeTransparent, toHaveVertexCount, toHaveTriangleCount,
|
|
650
|
+
* toHaveUserData, toHaveMapTexture
|
|
651
|
+
*
|
|
652
|
+
* **Scene-level:** toHaveObjectCount, toHaveObjectCountGreaterThan,
|
|
653
|
+
* toHaveCountByType, toHaveTotalTriangleCount,
|
|
654
|
+
* toHaveTotalTriangleCountLessThan
|
|
655
|
+
*
|
|
656
|
+
* **Camera:** toHaveCameraPosition, toHaveCameraFov, toHaveCameraNear,
|
|
657
|
+
* toHaveCameraFar, toHaveCameraZoom
|
|
658
|
+
*
|
|
659
|
+
* **Batch:** toAllExist, toAllBeVisible, toNoneExist
|
|
188
660
|
*/
|
|
189
|
-
|
|
190
|
-
|
|
661
|
+
|
|
662
|
+
interface R3FMatcherReceiver {
|
|
663
|
+
page: Page;
|
|
664
|
+
canvasId?: string;
|
|
665
|
+
getObject(idOrUuid: string): Promise<ObjectMetadata | null>;
|
|
666
|
+
inspect(idOrUuid: string): Promise<ObjectInspection | null>;
|
|
667
|
+
}
|
|
668
|
+
/** Context provided by Playwright when the matcher is invoked via expect().extend() */
|
|
669
|
+
interface ExpectMatcherContext {
|
|
670
|
+
isNot?: boolean;
|
|
671
|
+
}
|
|
672
|
+
interface MatcherOptions {
|
|
673
|
+
timeout?: number;
|
|
674
|
+
interval?: number;
|
|
675
|
+
}
|
|
676
|
+
type Vec3Opts = MatcherOptions & {
|
|
677
|
+
tolerance?: number;
|
|
678
|
+
};
|
|
679
|
+
declare const r3fMatchers: {
|
|
680
|
+
toExist(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, opts?: MatcherOptions): Promise<{
|
|
191
681
|
pass: boolean;
|
|
192
682
|
message: () => string;
|
|
193
683
|
name: string;
|
|
194
684
|
expected: string;
|
|
195
|
-
actual:
|
|
685
|
+
actual: null;
|
|
196
686
|
}>;
|
|
197
|
-
toBeVisible(this:
|
|
198
|
-
pass:
|
|
687
|
+
toBeVisible(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, opts?: MatcherOptions): Promise<{
|
|
688
|
+
pass: boolean;
|
|
199
689
|
message: () => string;
|
|
200
690
|
name: string;
|
|
201
|
-
expected?: undefined;
|
|
202
|
-
actual?: undefined;
|
|
203
691
|
} | {
|
|
204
692
|
pass: boolean;
|
|
205
693
|
message: () => string;
|
|
@@ -207,28 +695,43 @@ declare const expect: _playwright_test.Expect<{
|
|
|
207
695
|
expected: boolean;
|
|
208
696
|
actual: boolean;
|
|
209
697
|
}>;
|
|
210
|
-
|
|
211
|
-
pass:
|
|
698
|
+
toHavePosition(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expected: [number, number, number], tolOpts?: number | Vec3Opts): Promise<{
|
|
699
|
+
pass: boolean;
|
|
212
700
|
message: () => string;
|
|
213
701
|
name: string;
|
|
214
|
-
expected?: undefined;
|
|
215
|
-
actual?: undefined;
|
|
216
702
|
} | {
|
|
217
703
|
pass: boolean;
|
|
218
704
|
message: () => string;
|
|
219
705
|
name: string;
|
|
220
|
-
expected:
|
|
221
|
-
actual:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
706
|
+
expected: [number, number, number];
|
|
707
|
+
actual: [number, number, number];
|
|
708
|
+
}>;
|
|
709
|
+
toHaveWorldPosition(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expected: [number, number, number], tolOpts?: number | Vec3Opts): Promise<{
|
|
710
|
+
pass: boolean;
|
|
711
|
+
message: () => string;
|
|
712
|
+
name: string;
|
|
713
|
+
} | {
|
|
714
|
+
pass: boolean;
|
|
715
|
+
message: () => string;
|
|
716
|
+
name: string;
|
|
717
|
+
expected: [number, number, number];
|
|
718
|
+
actual: [number, number, number];
|
|
719
|
+
}>;
|
|
720
|
+
toHaveRotation(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expected: [number, number, number], tolOpts?: number | Vec3Opts): Promise<{
|
|
721
|
+
pass: boolean;
|
|
722
|
+
message: () => string;
|
|
723
|
+
name: string;
|
|
724
|
+
} | {
|
|
725
|
+
pass: boolean;
|
|
726
|
+
message: () => string;
|
|
727
|
+
name: string;
|
|
728
|
+
expected: [number, number, number];
|
|
729
|
+
actual: [number, number, number];
|
|
225
730
|
}>;
|
|
226
|
-
|
|
227
|
-
pass:
|
|
731
|
+
toHaveScale(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expected: [number, number, number], tolOpts?: number | Vec3Opts): Promise<{
|
|
732
|
+
pass: boolean;
|
|
228
733
|
message: () => string;
|
|
229
734
|
name: string;
|
|
230
|
-
expected?: undefined;
|
|
231
|
-
actual?: undefined;
|
|
232
735
|
} | {
|
|
233
736
|
pass: boolean;
|
|
234
737
|
message: () => string;
|
|
@@ -236,15 +739,104 @@ declare const expect: _playwright_test.Expect<{
|
|
|
236
739
|
expected: [number, number, number];
|
|
237
740
|
actual: [number, number, number];
|
|
238
741
|
}>;
|
|
239
|
-
|
|
742
|
+
toHaveType(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedType: string, opts?: MatcherOptions): Promise<{
|
|
743
|
+
pass: boolean;
|
|
744
|
+
message: () => string;
|
|
745
|
+
name: string;
|
|
746
|
+
} | {
|
|
747
|
+
pass: boolean;
|
|
748
|
+
message: () => string;
|
|
749
|
+
name: string;
|
|
750
|
+
expected: string;
|
|
751
|
+
actual: string;
|
|
752
|
+
}>;
|
|
753
|
+
toHaveName(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedName: string, opts?: MatcherOptions): Promise<{
|
|
754
|
+
pass: boolean;
|
|
755
|
+
message: () => string;
|
|
756
|
+
name: string;
|
|
757
|
+
} | {
|
|
758
|
+
pass: boolean;
|
|
759
|
+
message: () => string;
|
|
760
|
+
name: string;
|
|
761
|
+
expected: string;
|
|
762
|
+
actual: string;
|
|
763
|
+
}>;
|
|
764
|
+
toHaveGeometryType(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedGeo: string, opts?: MatcherOptions): Promise<{
|
|
765
|
+
pass: boolean;
|
|
766
|
+
message: () => string;
|
|
767
|
+
name: string;
|
|
768
|
+
} | {
|
|
769
|
+
pass: boolean;
|
|
770
|
+
message: () => string;
|
|
771
|
+
name: string;
|
|
772
|
+
expected: string;
|
|
773
|
+
actual: string | undefined;
|
|
774
|
+
}>;
|
|
775
|
+
toHaveMaterialType(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedMat: string, opts?: MatcherOptions): Promise<{
|
|
776
|
+
pass: boolean;
|
|
777
|
+
message: () => string;
|
|
778
|
+
name: string;
|
|
779
|
+
} | {
|
|
780
|
+
pass: boolean;
|
|
781
|
+
message: () => string;
|
|
782
|
+
name: string;
|
|
783
|
+
expected: string;
|
|
784
|
+
actual: string | undefined;
|
|
785
|
+
}>;
|
|
786
|
+
toHaveChildCount(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedCount: number, opts?: MatcherOptions): Promise<{
|
|
787
|
+
pass: boolean;
|
|
788
|
+
message: () => string;
|
|
789
|
+
name: string;
|
|
790
|
+
} | {
|
|
791
|
+
pass: boolean;
|
|
792
|
+
message: () => string;
|
|
793
|
+
name: string;
|
|
794
|
+
expected: number;
|
|
795
|
+
actual: number;
|
|
796
|
+
}>;
|
|
797
|
+
toHaveParent(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedParent: string, opts?: MatcherOptions): Promise<{
|
|
798
|
+
pass: boolean;
|
|
799
|
+
message: () => string;
|
|
800
|
+
name: string;
|
|
801
|
+
} | {
|
|
802
|
+
pass: boolean;
|
|
803
|
+
message: () => string;
|
|
804
|
+
name: string;
|
|
805
|
+
expected: string;
|
|
806
|
+
actual: string | null;
|
|
807
|
+
}>;
|
|
808
|
+
toHaveInstanceCount(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedCount: number, opts?: MatcherOptions): Promise<{
|
|
809
|
+
pass: boolean;
|
|
810
|
+
message: () => string;
|
|
811
|
+
name: string;
|
|
812
|
+
} | {
|
|
813
|
+
pass: boolean;
|
|
814
|
+
message: () => string;
|
|
815
|
+
name: string;
|
|
816
|
+
expected: number;
|
|
817
|
+
actual: number;
|
|
818
|
+
}>;
|
|
819
|
+
toBeInFrustum(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, opts?: MatcherOptions): Promise<{
|
|
820
|
+
pass: boolean;
|
|
821
|
+
message: () => string;
|
|
822
|
+
name: string;
|
|
823
|
+
} | {
|
|
824
|
+
pass: boolean;
|
|
825
|
+
message: () => string;
|
|
826
|
+
name: string;
|
|
827
|
+
expected: string;
|
|
828
|
+
actual: {
|
|
829
|
+
min: [number, number, number];
|
|
830
|
+
max: [number, number, number];
|
|
831
|
+
};
|
|
832
|
+
}>;
|
|
833
|
+
toHaveBounds(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expected: {
|
|
240
834
|
min: [number, number, number];
|
|
241
835
|
max: [number, number, number];
|
|
242
|
-
},
|
|
243
|
-
pass:
|
|
836
|
+
}, tolOpts?: number | Vec3Opts): Promise<{
|
|
837
|
+
pass: boolean;
|
|
244
838
|
message: () => string;
|
|
245
839
|
name: string;
|
|
246
|
-
expected?: undefined;
|
|
247
|
-
actual?: undefined;
|
|
248
840
|
} | {
|
|
249
841
|
pass: boolean;
|
|
250
842
|
message: () => string;
|
|
@@ -258,12 +850,43 @@ declare const expect: _playwright_test.Expect<{
|
|
|
258
850
|
max: [number, number, number];
|
|
259
851
|
};
|
|
260
852
|
}>;
|
|
261
|
-
|
|
262
|
-
pass:
|
|
853
|
+
toHaveColor(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedColor: string, opts?: MatcherOptions): Promise<{
|
|
854
|
+
pass: boolean;
|
|
855
|
+
message: () => string;
|
|
856
|
+
name: string;
|
|
857
|
+
} | {
|
|
858
|
+
pass: boolean;
|
|
859
|
+
message: () => string;
|
|
860
|
+
name: string;
|
|
861
|
+
expected: string;
|
|
862
|
+
actual: string | undefined;
|
|
863
|
+
}>;
|
|
864
|
+
toHaveOpacity(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedOpacity: number, tolOpts?: number | Vec3Opts): Promise<{
|
|
865
|
+
pass: boolean;
|
|
866
|
+
message: () => string;
|
|
867
|
+
name: string;
|
|
868
|
+
} | {
|
|
869
|
+
pass: boolean;
|
|
870
|
+
message: () => string;
|
|
871
|
+
name: string;
|
|
872
|
+
expected: number;
|
|
873
|
+
actual: number | undefined;
|
|
874
|
+
}>;
|
|
875
|
+
toBeTransparent(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, opts?: MatcherOptions): Promise<{
|
|
876
|
+
pass: boolean;
|
|
877
|
+
message: () => string;
|
|
878
|
+
name: string;
|
|
879
|
+
} | {
|
|
880
|
+
pass: boolean;
|
|
881
|
+
message: () => string;
|
|
882
|
+
name: string;
|
|
883
|
+
expected: boolean;
|
|
884
|
+
actual: boolean | undefined;
|
|
885
|
+
}>;
|
|
886
|
+
toHaveVertexCount(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedCount: number, opts?: MatcherOptions): Promise<{
|
|
887
|
+
pass: boolean;
|
|
263
888
|
message: () => string;
|
|
264
889
|
name: string;
|
|
265
|
-
expected?: undefined;
|
|
266
|
-
actual?: undefined;
|
|
267
890
|
} | {
|
|
268
891
|
pass: boolean;
|
|
269
892
|
message: () => string;
|
|
@@ -271,32 +894,349 @@ declare const expect: _playwright_test.Expect<{
|
|
|
271
894
|
expected: number;
|
|
272
895
|
actual: number;
|
|
273
896
|
}>;
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
897
|
+
toHaveTriangleCount(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedCount: number, opts?: MatcherOptions): Promise<{
|
|
898
|
+
pass: boolean;
|
|
899
|
+
message: () => string;
|
|
900
|
+
name: string;
|
|
901
|
+
} | {
|
|
902
|
+
pass: boolean;
|
|
903
|
+
message: () => string;
|
|
904
|
+
name: string;
|
|
905
|
+
expected: number;
|
|
906
|
+
actual: number;
|
|
907
|
+
}>;
|
|
908
|
+
toHaveUserData(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, key: string, expectedValue?: unknown, opts?: MatcherOptions): Promise<{
|
|
909
|
+
pass: boolean;
|
|
910
|
+
message: () => string;
|
|
911
|
+
name: string;
|
|
912
|
+
} | {
|
|
913
|
+
pass: boolean;
|
|
914
|
+
message: () => string;
|
|
915
|
+
name: string;
|
|
916
|
+
expected: {};
|
|
917
|
+
actual: unknown;
|
|
918
|
+
}>;
|
|
919
|
+
toHaveMapTexture(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, id: string, expectedName?: string, opts?: MatcherOptions): Promise<{
|
|
920
|
+
pass: boolean;
|
|
921
|
+
message: () => string;
|
|
922
|
+
name: string;
|
|
923
|
+
} | {
|
|
924
|
+
pass: boolean;
|
|
925
|
+
message: () => string;
|
|
926
|
+
name: string;
|
|
927
|
+
expected: string;
|
|
928
|
+
actual: string | undefined;
|
|
929
|
+
}>;
|
|
930
|
+
/**
|
|
931
|
+
* Assert the total number of objects in the scene.
|
|
932
|
+
* Auto-retries until the count matches or timeout.
|
|
933
|
+
*
|
|
934
|
+
* @example expect(r3f).toHaveObjectCount(42);
|
|
935
|
+
* @example expect(r3f).toHaveObjectCount(42, { timeout: 10_000 });
|
|
936
|
+
*/
|
|
937
|
+
toHaveObjectCount(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, expected: number, options?: MatcherOptions): Promise<{
|
|
938
|
+
pass: boolean;
|
|
939
|
+
message: () => string;
|
|
940
|
+
name: string;
|
|
941
|
+
expected: number;
|
|
942
|
+
actual: number;
|
|
943
|
+
}>;
|
|
944
|
+
/**
|
|
945
|
+
* Assert the total number of objects is at least `min`.
|
|
946
|
+
* Useful for BIM scenes where the exact count may vary slightly.
|
|
947
|
+
*
|
|
948
|
+
* @example expect(r3f).toHaveObjectCountGreaterThan(10);
|
|
949
|
+
*/
|
|
950
|
+
toHaveObjectCountGreaterThan(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, min: number, options?: MatcherOptions): Promise<{
|
|
951
|
+
pass: boolean;
|
|
952
|
+
message: () => string;
|
|
953
|
+
name: string;
|
|
954
|
+
expected: string;
|
|
955
|
+
actual: number;
|
|
956
|
+
}>;
|
|
957
|
+
/**
|
|
958
|
+
* Assert the count of objects of a specific Three.js type.
|
|
959
|
+
* Auto-retries until the count matches or timeout.
|
|
960
|
+
*
|
|
961
|
+
* @example expect(r3f).toHaveCountByType('Mesh', 5);
|
|
962
|
+
* @example expect(r3f).toHaveCountByType('Line', 10, { timeout: 10_000 });
|
|
963
|
+
*/
|
|
964
|
+
toHaveCountByType(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, type: string, expected: number, options?: MatcherOptions): Promise<{
|
|
965
|
+
pass: boolean;
|
|
966
|
+
message: () => string;
|
|
967
|
+
name: string;
|
|
968
|
+
expected: number;
|
|
969
|
+
actual: number;
|
|
970
|
+
}>;
|
|
971
|
+
/**
|
|
972
|
+
* Assert the total triangle count across all meshes in the scene.
|
|
973
|
+
* Use as a performance budget guard — fail if the scene exceeds a threshold.
|
|
974
|
+
*
|
|
975
|
+
* @example expect(r3f).toHaveTotalTriangleCount(50000);
|
|
976
|
+
* @example expect(r3f).not.toHaveTotalTriangleCountGreaterThan(100000); // budget guard
|
|
977
|
+
*/
|
|
978
|
+
toHaveTotalTriangleCount(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, expected: number, options?: MatcherOptions): Promise<{
|
|
979
|
+
pass: boolean;
|
|
980
|
+
message: () => string;
|
|
981
|
+
name: string;
|
|
982
|
+
expected: number;
|
|
983
|
+
actual: number;
|
|
984
|
+
}>;
|
|
985
|
+
/**
|
|
986
|
+
* Assert the total triangle count is at most `max`.
|
|
987
|
+
* Perfect as a performance budget guard to prevent scene bloat.
|
|
988
|
+
*
|
|
989
|
+
* @example expect(r3f).toHaveTotalTriangleCountLessThan(100_000);
|
|
990
|
+
*/
|
|
991
|
+
toHaveTotalTriangleCountLessThan(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, max: number, options?: MatcherOptions): Promise<{
|
|
992
|
+
pass: boolean;
|
|
993
|
+
message: () => string;
|
|
994
|
+
name: string;
|
|
995
|
+
expected: string;
|
|
996
|
+
actual: number;
|
|
997
|
+
}>;
|
|
998
|
+
/**
|
|
999
|
+
* Assert the camera position is close to the expected [x, y, z].
|
|
1000
|
+
*
|
|
1001
|
+
* @example expect(r3f).toHaveCameraPosition([0, 5, 10], 0.1);
|
|
1002
|
+
*/
|
|
1003
|
+
toHaveCameraPosition(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, expected: [number, number, number], tolOpts?: number | Vec3Opts): Promise<{
|
|
1004
|
+
pass: boolean;
|
|
1005
|
+
message: () => string;
|
|
1006
|
+
name: string;
|
|
1007
|
+
expected: [number, number, number];
|
|
1008
|
+
actual: [number, number, number];
|
|
1009
|
+
}>;
|
|
1010
|
+
/**
|
|
1011
|
+
* Assert the camera field of view (PerspectiveCamera only).
|
|
1012
|
+
*
|
|
1013
|
+
* @example expect(r3f).toHaveCameraFov(75);
|
|
1014
|
+
*/
|
|
1015
|
+
toHaveCameraFov(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, expected: number, tolOpts?: number | Vec3Opts): Promise<{
|
|
1016
|
+
pass: boolean;
|
|
1017
|
+
message: () => string;
|
|
1018
|
+
name: string;
|
|
1019
|
+
expected: number;
|
|
1020
|
+
actual: number | undefined;
|
|
1021
|
+
}>;
|
|
1022
|
+
/**
|
|
1023
|
+
* Assert the camera near clipping plane.
|
|
1024
|
+
*
|
|
1025
|
+
* @example expect(r3f).toHaveCameraNear(0.1);
|
|
1026
|
+
*/
|
|
1027
|
+
toHaveCameraNear(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, expected: number, tolOpts?: number | Vec3Opts): Promise<{
|
|
1028
|
+
pass: boolean;
|
|
1029
|
+
message: () => string;
|
|
1030
|
+
name: string;
|
|
1031
|
+
expected: number;
|
|
1032
|
+
actual: number;
|
|
1033
|
+
}>;
|
|
1034
|
+
/**
|
|
1035
|
+
* Assert the camera far clipping plane.
|
|
1036
|
+
*
|
|
1037
|
+
* @example expect(r3f).toHaveCameraFar(1000);
|
|
1038
|
+
*/
|
|
1039
|
+
toHaveCameraFar(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, expected: number, tolOpts?: number | Vec3Opts): Promise<{
|
|
1040
|
+
pass: boolean;
|
|
1041
|
+
message: () => string;
|
|
1042
|
+
name: string;
|
|
1043
|
+
expected: number;
|
|
1044
|
+
actual: number;
|
|
1045
|
+
}>;
|
|
1046
|
+
/**
|
|
1047
|
+
* Assert the camera zoom level.
|
|
1048
|
+
*
|
|
1049
|
+
* @example expect(r3f).toHaveCameraZoom(1);
|
|
1050
|
+
*/
|
|
1051
|
+
toHaveCameraZoom(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, expected: number, tolOpts?: number | Vec3Opts): Promise<{
|
|
1052
|
+
pass: boolean;
|
|
1053
|
+
message: () => string;
|
|
1054
|
+
name: string;
|
|
1055
|
+
expected: number;
|
|
1056
|
+
actual: number;
|
|
1057
|
+
}>;
|
|
1058
|
+
/**
|
|
1059
|
+
* Assert that ALL given objects exist in the scene.
|
|
1060
|
+
* Accepts an array of testIds/uuids or a glob pattern (e.g. "wall-*").
|
|
1061
|
+
*
|
|
1062
|
+
* @example expect(r3f).toAllExist(['wall-1', 'wall-2', 'floor']);
|
|
1063
|
+
* @example expect(r3f).toAllExist('wall-*');
|
|
1064
|
+
*/
|
|
1065
|
+
toAllExist(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, idsOrPattern: string[] | string, opts?: MatcherOptions): Promise<{
|
|
1066
|
+
pass: boolean;
|
|
1067
|
+
message: () => string;
|
|
1068
|
+
name: string;
|
|
1069
|
+
expected: string | string[];
|
|
1070
|
+
actual: {
|
|
1071
|
+
missing: string[];
|
|
1072
|
+
};
|
|
1073
|
+
}>;
|
|
1074
|
+
/**
|
|
1075
|
+
* Assert that ALL given objects are visible.
|
|
1076
|
+
*
|
|
1077
|
+
* @example expect(r3f).toAllBeVisible(['wall-1', 'wall-2', 'floor']);
|
|
1078
|
+
* @example expect(r3f).toAllBeVisible('wall-*');
|
|
1079
|
+
*/
|
|
1080
|
+
toAllBeVisible(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, idsOrPattern: string[] | string, opts?: MatcherOptions): Promise<{
|
|
1081
|
+
pass: boolean;
|
|
1082
|
+
message: () => string;
|
|
1083
|
+
name: string;
|
|
1084
|
+
expected: string | string[];
|
|
1085
|
+
actual: {
|
|
1086
|
+
hidden: string[];
|
|
1087
|
+
};
|
|
1088
|
+
}>;
|
|
1089
|
+
/**
|
|
1090
|
+
* Assert that NONE of the given objects exist in the scene.
|
|
1091
|
+
*
|
|
1092
|
+
* @example expect(r3f).toNoneExist(['deleted-wall', 'old-floor']);
|
|
1093
|
+
* @example expect(r3f).toNoneExist('temp-*');
|
|
1094
|
+
*/
|
|
1095
|
+
toNoneExist(this: ExpectMatcherContext, r3f: R3FMatcherReceiver, idsOrPattern: string[] | string, opts?: MatcherOptions): Promise<{
|
|
1096
|
+
pass: boolean;
|
|
1097
|
+
message: () => string;
|
|
1098
|
+
name: string;
|
|
1099
|
+
expected: string | string[];
|
|
1100
|
+
actual: {
|
|
1101
|
+
found: string[];
|
|
1102
|
+
};
|
|
1103
|
+
}>;
|
|
1104
|
+
};
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* @module interactions
|
|
1108
|
+
*
|
|
1109
|
+
* Playwright interaction helpers — thin wrappers around `page.evaluate` calls
|
|
1110
|
+
* to the `window.__R3F_DOM__` bridge interaction methods.
|
|
1111
|
+
*
|
|
1112
|
+
* All object-targeted interactions auto-wait for:
|
|
1113
|
+
* 1. The bridge to be ready (`_ready === true`)
|
|
1114
|
+
* 2. The target object to exist (by testId or uuid)
|
|
1115
|
+
*
|
|
1116
|
+
* This mirrors Playwright's built-in auto-waiting on locators.
|
|
1117
|
+
*
|
|
1118
|
+
* Multi-canvas: pass `canvasId` to target a specific canvas instance.
|
|
1119
|
+
* When undefined, uses the default `window.__R3F_DOM__`.
|
|
1120
|
+
*/
|
|
279
1121
|
|
|
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
|
-
/**
|
|
1122
|
+
/** Click a 3D object by its testId or uuid. Auto-waits for the object. */
|
|
1123
|
+
declare function click(page: Page, idOrUuid: string, timeout?: number, canvasId?: string): Promise<void>;
|
|
1124
|
+
/** Double-click a 3D object by its testId or uuid. Auto-waits for the object. */
|
|
1125
|
+
declare function doubleClick(page: Page, idOrUuid: string, timeout?: number, canvasId?: string): Promise<void>;
|
|
1126
|
+
/** Right-click / context-menu a 3D object. Auto-waits for the object. */
|
|
1127
|
+
declare function contextMenu(page: Page, idOrUuid: string, timeout?: number, canvasId?: string): Promise<void>;
|
|
1128
|
+
/** Hover over a 3D object. Auto-waits for the object. */
|
|
1129
|
+
declare function hover(page: Page, idOrUuid: string, timeout?: number, canvasId?: string): Promise<void>;
|
|
1130
|
+
/** Unhover / pointer-leave — resets hover state by moving pointer off-canvas. Auto-waits for bridge. */
|
|
1131
|
+
declare function unhover(page: Page, timeout?: number, canvasId?: string): Promise<void>;
|
|
1132
|
+
/** Drag a 3D object with a world-space delta. Auto-waits for the object. */
|
|
289
1133
|
declare function drag(page: Page, idOrUuid: string, delta: {
|
|
290
1134
|
x: number;
|
|
291
1135
|
y: number;
|
|
292
1136
|
z: number;
|
|
293
|
-
}): Promise<void>;
|
|
294
|
-
/** Dispatch a wheel/scroll event on a 3D object. */
|
|
1137
|
+
}, timeout?: number, canvasId?: string): Promise<void>;
|
|
1138
|
+
/** Dispatch a wheel/scroll event on a 3D object. Auto-waits for the object. */
|
|
295
1139
|
declare function wheel(page: Page, idOrUuid: string, options?: {
|
|
296
1140
|
deltaY?: number;
|
|
297
1141
|
deltaX?: number;
|
|
298
|
-
}): Promise<void>;
|
|
299
|
-
/** Click empty space to trigger onPointerMissed handlers. */
|
|
300
|
-
declare function pointerMiss(page: Page): Promise<void>;
|
|
1142
|
+
}, timeout?: number, canvasId?: string): Promise<void>;
|
|
1143
|
+
/** Click empty space to trigger onPointerMissed handlers. Auto-waits for bridge. */
|
|
1144
|
+
declare function pointerMiss(page: Page, timeout?: number, canvasId?: string): Promise<void>;
|
|
1145
|
+
/** Draw a freeform path on the canvas. Auto-waits for bridge. */
|
|
1146
|
+
declare function drawPathOnCanvas(page: Page, points: Array<{
|
|
1147
|
+
x: number;
|
|
1148
|
+
y: number;
|
|
1149
|
+
pressure?: number;
|
|
1150
|
+
}>, options?: {
|
|
1151
|
+
stepDelayMs?: number;
|
|
1152
|
+
pointerType?: 'mouse' | 'pen' | 'touch';
|
|
1153
|
+
clickAtEnd?: boolean;
|
|
1154
|
+
}, timeout?: number, canvasId?: string): Promise<{
|
|
1155
|
+
eventCount: number;
|
|
1156
|
+
pointCount: number;
|
|
1157
|
+
}>;
|
|
1158
|
+
/** Get the current camera state (position, rotation, fov, near, far, zoom). Auto-waits for bridge. */
|
|
1159
|
+
declare function getCameraState(page: Page, timeout?: number, canvasId?: string): Promise<CameraState>;
|
|
1160
|
+
|
|
1161
|
+
/**
|
|
1162
|
+
* @module pathGenerators
|
|
1163
|
+
*
|
|
1164
|
+
* Pure geometry utilities that generate arrays of screen-space points for
|
|
1165
|
+
* use with `r3f.drawPath()`. Provides line, quadratic bezier, rectangle,
|
|
1166
|
+
* and circle/ellipse path generators.
|
|
1167
|
+
*
|
|
1168
|
+
* Duplicated from `@react-three-dom/core` to avoid a runtime dependency.
|
|
1169
|
+
*/
|
|
1170
|
+
/** A 2D screen-space point in CSS pixels, relative to the canvas top-left. */
|
|
1171
|
+
interface DrawPoint {
|
|
1172
|
+
/** X coordinate in CSS pixels from canvas left edge. */
|
|
1173
|
+
x: number;
|
|
1174
|
+
/** Y coordinate in CSS pixels from canvas top edge. */
|
|
1175
|
+
y: number;
|
|
1176
|
+
/** Optional pressure (0–1). Default: 0.5 */
|
|
1177
|
+
pressure?: number;
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Generate points along a straight line.
|
|
1181
|
+
*
|
|
1182
|
+
* @param start Start point
|
|
1183
|
+
* @param end End point
|
|
1184
|
+
* @param steps Intermediate points (excluding start/end). Default: 10
|
|
1185
|
+
* @param pressure Uniform pressure. Default: 0.5
|
|
1186
|
+
*/
|
|
1187
|
+
declare function linePath(start: {
|
|
1188
|
+
x: number;
|
|
1189
|
+
y: number;
|
|
1190
|
+
}, end: {
|
|
1191
|
+
x: number;
|
|
1192
|
+
y: number;
|
|
1193
|
+
}, steps?: number, pressure?: number): DrawPoint[];
|
|
1194
|
+
/**
|
|
1195
|
+
* Generate points along a quadratic bezier curve.
|
|
1196
|
+
*
|
|
1197
|
+
* @param start Start point
|
|
1198
|
+
* @param control Control point
|
|
1199
|
+
* @param end End point
|
|
1200
|
+
* @param steps Number of steps. Default: 20
|
|
1201
|
+
* @param pressure Uniform pressure. Default: 0.5
|
|
1202
|
+
*/
|
|
1203
|
+
declare function curvePath(start: {
|
|
1204
|
+
x: number;
|
|
1205
|
+
y: number;
|
|
1206
|
+
}, control: {
|
|
1207
|
+
x: number;
|
|
1208
|
+
y: number;
|
|
1209
|
+
}, end: {
|
|
1210
|
+
x: number;
|
|
1211
|
+
y: number;
|
|
1212
|
+
}, steps?: number, pressure?: number): DrawPoint[];
|
|
1213
|
+
/**
|
|
1214
|
+
* Generate points forming a rectangle.
|
|
1215
|
+
*
|
|
1216
|
+
* @param topLeft Top-left corner
|
|
1217
|
+
* @param bottomRight Bottom-right corner
|
|
1218
|
+
* @param pointsPerSide Points per side. Default: 5
|
|
1219
|
+
* @param pressure Uniform pressure. Default: 0.5
|
|
1220
|
+
*/
|
|
1221
|
+
declare function rectPath(topLeft: {
|
|
1222
|
+
x: number;
|
|
1223
|
+
y: number;
|
|
1224
|
+
}, bottomRight: {
|
|
1225
|
+
x: number;
|
|
1226
|
+
y: number;
|
|
1227
|
+
}, pointsPerSide?: number, pressure?: number): DrawPoint[];
|
|
1228
|
+
/**
|
|
1229
|
+
* Generate points forming a circle/ellipse.
|
|
1230
|
+
*
|
|
1231
|
+
* @param center Center point
|
|
1232
|
+
* @param radiusX Horizontal radius in CSS pixels
|
|
1233
|
+
* @param radiusY Vertical radius. Default: same as radiusX
|
|
1234
|
+
* @param steps Number of points. Default: 36
|
|
1235
|
+
* @param pressure Uniform pressure. Default: 0.5
|
|
1236
|
+
*/
|
|
1237
|
+
declare function circlePath(center: {
|
|
1238
|
+
x: number;
|
|
1239
|
+
y: number;
|
|
1240
|
+
}, radiusX: number, radiusY?: number, steps?: number, pressure?: number): DrawPoint[];
|
|
301
1241
|
|
|
302
|
-
export { type ObjectInspection, type ObjectMetadata, R3FFixture, type SceneSnapshot, type SnapshotNode, type WaitForIdleOptions, type WaitForObjectOptions, type WaitForSceneReadyOptions, click, contextMenu, doubleClick, drag,
|
|
1242
|
+
export { type BridgeDiagnostics, type CameraState, type DrawPoint, type InspectOptions, type ObjectInspection, type ObjectMetadata, R3FFixture, type R3FFixtureOptions, R3FReporter, type SceneDiff, type SceneDiffChange, type SceneSnapshot, type SnapshotNode, type WaitForIdleOptions, type WaitForNewObjectOptions, type WaitForNewObjectResult, type WaitForObjectOptions, type WaitForObjectRemovedOptions, type WaitForSceneReadyOptions, circlePath, click, contextMenu, createR3FTest, curvePath, diffSnapshots, doubleClick, drag, drawPathOnCanvas, getCameraState, hover, linePath, pointerMiss, r3fMatchers, rectPath, test, unhover, waitForIdle, waitForNewObject, waitForObject, waitForObjectRemoved, waitForSceneReady, wheel };
|