@react-three-dom/cypress 0.2.0 → 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.d.cts CHANGED
@@ -9,6 +9,10 @@ interface ObjectMetadata {
9
9
  vertexCount?: number;
10
10
  triangleCount?: number;
11
11
  instanceCount?: number;
12
+ fov?: number;
13
+ near?: number;
14
+ far?: number;
15
+ zoom?: number;
12
16
  position: [number, number, number];
13
17
  rotation: [number, number, number];
14
18
  scale: [number, number, number];
@@ -36,6 +40,8 @@ interface ObjectInspection {
36
40
  center: [number, number, number];
37
41
  radius: number;
38
42
  };
43
+ positionData?: number[];
44
+ indexData?: number[];
39
45
  };
40
46
  material?: {
41
47
  type: string;
@@ -57,6 +63,11 @@ interface SnapshotNode {
57
63
  position: [number, number, number];
58
64
  rotation: [number, number, number];
59
65
  scale: [number, number, number];
66
+ geometryType?: string;
67
+ materialType?: string;
68
+ vertexCount?: number;
69
+ triangleCount?: number;
70
+ instanceCount?: number;
60
71
  children: SnapshotNode[];
61
72
  }
62
73
  interface SceneSnapshot {
@@ -64,6 +75,49 @@ interface SceneSnapshot {
64
75
  objectCount: number;
65
76
  tree: SnapshotNode;
66
77
  }
78
+ interface BridgeDiagnostics {
79
+ version: string;
80
+ ready: boolean;
81
+ error?: string;
82
+ objectCount: number;
83
+ meshCount: number;
84
+ groupCount: number;
85
+ lightCount: number;
86
+ cameraCount: number;
87
+ materializedDomNodes: number;
88
+ maxDomNodes: number;
89
+ canvasWidth: number;
90
+ canvasHeight: number;
91
+ webglRenderer: string;
92
+ dirtyQueueSize: number;
93
+ }
94
+ interface CameraState {
95
+ type: string;
96
+ position: [number, number, number];
97
+ rotation: [number, number, number];
98
+ target: [number, number, number];
99
+ fov?: number;
100
+ near: number;
101
+ far: number;
102
+ zoom: number;
103
+ aspect?: number;
104
+ left?: number;
105
+ right?: number;
106
+ top?: number;
107
+ bottom?: number;
108
+ }
109
+
110
+ interface SceneDiffChange {
111
+ uuid: string;
112
+ field: string;
113
+ from: unknown;
114
+ to: unknown;
115
+ }
116
+ interface SceneDiff {
117
+ added: SnapshotNode[];
118
+ removed: SnapshotNode[];
119
+ changed: SceneDiffChange[];
120
+ }
67
121
 
68
122
  // ---------------------------------------------------------------------------
69
123
  // TypeScript declarations for @react-three-dom/cypress
@@ -78,42 +132,85 @@ interface SceneSnapshot {
78
132
  declare global {
79
133
  namespace Cypress {
80
134
  interface Chainable {
81
- // ---- Debug ----
135
+ // ---- Multi-canvas ----
136
+ /**
137
+ * Switch all subsequent r3f commands to target a specific canvas instance.
138
+ * Pass `null` to switch back to the default canvas.
139
+ * @example cy.r3fUseCanvas('minimap'); cy.r3fClick('marker');
140
+ */
141
+ r3fUseCanvas(canvasId: string | null): Chainable<void>;
142
+ /** List all active canvas IDs registered on the page. */
143
+ r3fGetCanvasIds(): Chainable<string[]>;
144
+
145
+ // ---- Debug / Reporter ----
82
146
  /** Enable debug logging. Mirrors [r3f-dom:*] browser logs to Cypress command log. */
83
147
  r3fEnableDebug(): Chainable<void>;
148
+ /**
149
+ * Enable the R3F reporter for rich terminal output (bridge status, object lookup,
150
+ * interaction timing, diagnostics). Requires `registerR3FTasks(on)` in cypress.config.ts.
151
+ */
152
+ r3fEnableReporter(enabled?: boolean): Chainable<void>;
84
153
  /** Log the full scene tree to the Cypress command log and browser console. */
85
154
  r3fLogScene(): Chainable<void>;
86
155
 
156
+ // ---- Diagnostics ----
157
+ /** Get bridge diagnostics (object counts, DOM state, GPU info). */
158
+ r3fGetDiagnostics(): Chainable<BridgeDiagnostics | null>;
159
+ /** Log bridge diagnostics to the Cypress command log and browser console. */
160
+ r3fLogDiagnostics(): Chainable<void>;
161
+ /** Fuzzy search for objects by partial testId, name, or uuid. */
162
+ r3fFuzzyFind(query: string, limit?: number): Chainable<ObjectMetadata[]>;
163
+
87
164
  // ---- Interactions ----
88
- /** Click a 3D object by testId or uuid. */
165
+ /** Click a 3D object by testId or uuid. Auto-waits for bridge + object. */
89
166
  r3fClick(idOrUuid: string): Chainable<void>;
90
- /** Double-click a 3D object by testId or uuid. */
167
+ /** Double-click a 3D object by testId or uuid. Auto-waits for bridge + object. */
91
168
  r3fDoubleClick(idOrUuid: string): Chainable<void>;
92
- /** Right-click / context-menu a 3D object by testId or uuid. */
169
+ /** Right-click / context-menu a 3D object by testId or uuid. Auto-waits for bridge + object. */
93
170
  r3fContextMenu(idOrUuid: string): Chainable<void>;
94
- /** Hover over a 3D object by testId or uuid. */
171
+ /** Hover over a 3D object by testId or uuid. Auto-waits for bridge + object. */
95
172
  r3fHover(idOrUuid: string): Chainable<void>;
96
- /** Drag a 3D object with a world-space delta vector. */
173
+ /** Unhover / pointer-leave resets hover state. Auto-waits for bridge. */
174
+ r3fUnhover(): Chainable<void>;
175
+ /** Drag a 3D object with a world-space delta vector. Auto-waits for bridge + object. */
97
176
  r3fDrag(idOrUuid: string, delta: { x: number; y: number; z: number }): Chainable<void>;
98
- /** Dispatch a wheel/scroll event on a 3D object. */
177
+ /** Dispatch a wheel/scroll event on a 3D object. Auto-waits for bridge + object. */
99
178
  r3fWheel(idOrUuid: string, options?: { deltaY?: number; deltaX?: number }): Chainable<void>;
100
- /** Click empty space to trigger onPointerMissed handlers. */
179
+ /** Click empty space to trigger onPointerMissed handlers. Auto-waits for bridge. */
101
180
  r3fPointerMiss(): Chainable<void>;
102
- /** Draw a freeform path on the canvas (for drawing/annotation apps). */
181
+ /** Draw a freeform path on the canvas (for drawing/annotation apps). Auto-waits for bridge. */
103
182
  r3fDrawPath(
104
183
  points: Array<{ x: number; y: number; pressure?: number }>,
105
184
  options?: { stepDelayMs?: number; pointerType?: 'mouse' | 'pen' | 'touch'; clickAtEnd?: boolean },
106
185
  ): Chainable<{ eventCount: number; pointCount: number }>;
107
186
 
108
187
  // ---- Selection ----
109
- /** Select a 3D object (highlights in scene). */
188
+ /** Select a 3D object (highlights in scene). Auto-waits for bridge + object. */
110
189
  r3fSelect(idOrUuid: string): Chainable<void>;
111
- /** Clear the current selection. */
190
+ /** Clear the current selection. Auto-waits for bridge. */
112
191
  r3fClearSelection(): Chainable<void>;
113
192
 
114
193
  // ---- Queries ----
115
194
  /** Get object metadata by testId or uuid. */
116
195
  r3fGetObject(idOrUuid: string): Chainable<ObjectMetadata | null>;
196
+ /** Get object metadata by testId. */
197
+ r3fGetByTestId(testId: string): Chainable<ObjectMetadata | null>;
198
+ /** Get all objects with the given name (object.name). */
199
+ r3fGetByName(name: string): Chainable<ObjectMetadata[]>;
200
+ /** Get object metadata by uuid only. */
201
+ r3fGetByUuid(uuid: string): Chainable<ObjectMetadata | null>;
202
+ /** Get direct children of an object by testId or uuid. */
203
+ r3fGetChildren(idOrUuid: string): Chainable<ObjectMetadata[]>;
204
+ /** Get parent of an object by testId or uuid. */
205
+ r3fGetParent(idOrUuid: string): Chainable<ObjectMetadata | null>;
206
+ /** Get the R3F canvas element (data-r3f-canvas). */
207
+ r3fGetCanvas(): Chainable<JQuery<HTMLCanvasElement>>;
208
+ /** Get world-space position [x, y, z] of an object. */
209
+ r3fGetWorldPosition(idOrUuid: string): Chainable<[number, number, number] | null>;
210
+ /** Compare two scene snapshots (added, removed, changed). */
211
+ r3fDiffSnapshots(before: SceneSnapshot, after: SceneSnapshot): Chainable<SceneDiff>;
212
+ /** Run an action and return { added, removed } object count change. */
213
+ r3fTrackObjectCount(action: () => Cypress.Chainable<unknown>): Chainable<{ added: number; removed: number }>;
117
214
  /** Get heavy inspection data (Tier 2) by testId or uuid. */
118
215
  r3fInspect(idOrUuid: string): Chainable<ObjectInspection | null>;
119
216
  /** Take a full scene snapshot. */
@@ -124,6 +221,10 @@ declare global {
124
221
  // ---- BIM/CAD queries ----
125
222
  /** Get all objects of a given Three.js type (e.g. "Mesh", "Group", "Line"). */
126
223
  r3fGetByType(type: string): Chainable<ObjectMetadata[]>;
224
+ /** Get all objects with a given geometry type (e.g. "BoxGeometry"). */
225
+ r3fGetByGeometryType(type: string): Chainable<ObjectMetadata[]>;
226
+ /** Get all objects with a given material type (e.g. "MeshStandardMaterial"). */
227
+ r3fGetByMaterialType(type: string): Chainable<ObjectMetadata[]>;
127
228
  /** Get objects that have a specific userData key (and optionally matching value). */
128
229
  r3fGetByUserData(key: string, value?: unknown): Chainable<ObjectMetadata[]>;
129
230
  /** Count objects of a given Three.js type. */
@@ -131,6 +232,10 @@ declare global {
131
232
  /** Batch lookup: get metadata for multiple objects by testId or uuid. */
132
233
  r3fGetObjects(ids: string[]): Chainable<Record<string, ObjectMetadata | null>>;
133
234
 
235
+ // ---- Camera ----
236
+ /** Get current camera state (position, rotation, fov, near, far, zoom, target). */
237
+ r3fGetCameraState(): Chainable<CameraState>;
238
+
134
239
  // ---- Waiters ----
135
240
  /** Wait until the scene is ready (bridge available, object count stable). */
136
241
  r3fWaitForSceneReady(options?: {
@@ -160,6 +265,11 @@ declare global {
160
265
  pollIntervalMs?: number;
161
266
  timeout?: number;
162
267
  }): Chainable<{ newObjects: ObjectMetadata[]; newUuids: string[]; count: number }>;
268
+ /** Wait until an object (by testId or uuid) is no longer in the scene. */
269
+ r3fWaitForObjectRemoved(
270
+ idOrUuid: string,
271
+ options?: { bridgeTimeout?: number; pollIntervalMs?: number; timeout?: number },
272
+ ): Chainable<void>;
163
273
  }
164
274
 
165
275
  interface Assertion {
@@ -168,8 +278,10 @@ declare global {
168
278
  r3fExist(idOrUuid: string): Assertion;
169
279
  /** Assert that a 3D object is visible. */
170
280
  r3fVisible(idOrUuid: string): Assertion;
171
- /** Assert object position within tolerance. */
281
+ /** Assert object local position within tolerance. */
172
282
  r3fPosition(idOrUuid: string, expected: [number, number, number], tolerance?: number): Assertion;
283
+ /** Assert object world position within tolerance. */
284
+ r3fWorldPosition(idOrUuid: string, expected: [number, number, number], tolerance?: number): Assertion;
173
285
  /** Assert object rotation (Euler radians) within tolerance. */
174
286
  r3fRotation(idOrUuid: string, expected: [number, number, number], tolerance?: number): Assertion;
175
287
  /** Assert object scale within tolerance. */
@@ -224,6 +336,26 @@ declare global {
224
336
  r3fTotalTriangleCount(expected: number): Assertion;
225
337
  /** Assert total triangle count is less than a maximum (performance budget). */
226
338
  r3fTotalTriangleCountLessThan(max: number): Assertion;
339
+
340
+ // ---- Camera assertions ----
341
+ /** Assert camera position within tolerance. */
342
+ r3fCameraPosition(expected: [number, number, number], tolerance?: number): Assertion;
343
+ /** Assert camera field of view (PerspectiveCamera). */
344
+ r3fCameraFov(expected: number, tolerance?: number): Assertion;
345
+ /** Assert camera near clipping plane. */
346
+ r3fCameraNear(expected: number, tolerance?: number): Assertion;
347
+ /** Assert camera far clipping plane. */
348
+ r3fCameraFar(expected: number, tolerance?: number): Assertion;
349
+ /** Assert camera zoom level. */
350
+ r3fCameraZoom(expected: number, tolerance?: number): Assertion;
351
+
352
+ // ---- Batch assertions ----
353
+ /** Assert ALL given objects exist. Accepts array of ids or glob pattern (e.g. "wall-*"). */
354
+ r3fAllExist(idsOrPattern: string[] | string): Assertion;
355
+ /** Assert ALL given objects are visible. Accepts array of ids or glob pattern. */
356
+ r3fAllVisible(idsOrPattern: string[] | string): Assertion;
357
+ /** Assert NONE of the given objects exist. Accepts array of ids or glob pattern. */
358
+ r3fNoneExist(idsOrPattern: string[] | string): Assertion;
227
359
  }
228
360
  }
229
361
  }
package/dist/index.d.ts CHANGED
@@ -9,6 +9,10 @@ interface ObjectMetadata {
9
9
  vertexCount?: number;
10
10
  triangleCount?: number;
11
11
  instanceCount?: number;
12
+ fov?: number;
13
+ near?: number;
14
+ far?: number;
15
+ zoom?: number;
12
16
  position: [number, number, number];
13
17
  rotation: [number, number, number];
14
18
  scale: [number, number, number];
@@ -36,6 +40,8 @@ interface ObjectInspection {
36
40
  center: [number, number, number];
37
41
  radius: number;
38
42
  };
43
+ positionData?: number[];
44
+ indexData?: number[];
39
45
  };
40
46
  material?: {
41
47
  type: string;
@@ -57,6 +63,11 @@ interface SnapshotNode {
57
63
  position: [number, number, number];
58
64
  rotation: [number, number, number];
59
65
  scale: [number, number, number];
66
+ geometryType?: string;
67
+ materialType?: string;
68
+ vertexCount?: number;
69
+ triangleCount?: number;
70
+ instanceCount?: number;
60
71
  children: SnapshotNode[];
61
72
  }
62
73
  interface SceneSnapshot {
@@ -64,6 +75,49 @@ interface SceneSnapshot {
64
75
  objectCount: number;
65
76
  tree: SnapshotNode;
66
77
  }
78
+ interface BridgeDiagnostics {
79
+ version: string;
80
+ ready: boolean;
81
+ error?: string;
82
+ objectCount: number;
83
+ meshCount: number;
84
+ groupCount: number;
85
+ lightCount: number;
86
+ cameraCount: number;
87
+ materializedDomNodes: number;
88
+ maxDomNodes: number;
89
+ canvasWidth: number;
90
+ canvasHeight: number;
91
+ webglRenderer: string;
92
+ dirtyQueueSize: number;
93
+ }
94
+ interface CameraState {
95
+ type: string;
96
+ position: [number, number, number];
97
+ rotation: [number, number, number];
98
+ target: [number, number, number];
99
+ fov?: number;
100
+ near: number;
101
+ far: number;
102
+ zoom: number;
103
+ aspect?: number;
104
+ left?: number;
105
+ right?: number;
106
+ top?: number;
107
+ bottom?: number;
108
+ }
109
+
110
+ interface SceneDiffChange {
111
+ uuid: string;
112
+ field: string;
113
+ from: unknown;
114
+ to: unknown;
115
+ }
116
+ interface SceneDiff {
117
+ added: SnapshotNode[];
118
+ removed: SnapshotNode[];
119
+ changed: SceneDiffChange[];
120
+ }
67
121
 
68
122
  // ---------------------------------------------------------------------------
69
123
  // TypeScript declarations for @react-three-dom/cypress
@@ -78,42 +132,85 @@ interface SceneSnapshot {
78
132
  declare global {
79
133
  namespace Cypress {
80
134
  interface Chainable {
81
- // ---- Debug ----
135
+ // ---- Multi-canvas ----
136
+ /**
137
+ * Switch all subsequent r3f commands to target a specific canvas instance.
138
+ * Pass `null` to switch back to the default canvas.
139
+ * @example cy.r3fUseCanvas('minimap'); cy.r3fClick('marker');
140
+ */
141
+ r3fUseCanvas(canvasId: string | null): Chainable<void>;
142
+ /** List all active canvas IDs registered on the page. */
143
+ r3fGetCanvasIds(): Chainable<string[]>;
144
+
145
+ // ---- Debug / Reporter ----
82
146
  /** Enable debug logging. Mirrors [r3f-dom:*] browser logs to Cypress command log. */
83
147
  r3fEnableDebug(): Chainable<void>;
148
+ /**
149
+ * Enable the R3F reporter for rich terminal output (bridge status, object lookup,
150
+ * interaction timing, diagnostics). Requires `registerR3FTasks(on)` in cypress.config.ts.
151
+ */
152
+ r3fEnableReporter(enabled?: boolean): Chainable<void>;
84
153
  /** Log the full scene tree to the Cypress command log and browser console. */
85
154
  r3fLogScene(): Chainable<void>;
86
155
 
156
+ // ---- Diagnostics ----
157
+ /** Get bridge diagnostics (object counts, DOM state, GPU info). */
158
+ r3fGetDiagnostics(): Chainable<BridgeDiagnostics | null>;
159
+ /** Log bridge diagnostics to the Cypress command log and browser console. */
160
+ r3fLogDiagnostics(): Chainable<void>;
161
+ /** Fuzzy search for objects by partial testId, name, or uuid. */
162
+ r3fFuzzyFind(query: string, limit?: number): Chainable<ObjectMetadata[]>;
163
+
87
164
  // ---- Interactions ----
88
- /** Click a 3D object by testId or uuid. */
165
+ /** Click a 3D object by testId or uuid. Auto-waits for bridge + object. */
89
166
  r3fClick(idOrUuid: string): Chainable<void>;
90
- /** Double-click a 3D object by testId or uuid. */
167
+ /** Double-click a 3D object by testId or uuid. Auto-waits for bridge + object. */
91
168
  r3fDoubleClick(idOrUuid: string): Chainable<void>;
92
- /** Right-click / context-menu a 3D object by testId or uuid. */
169
+ /** Right-click / context-menu a 3D object by testId or uuid. Auto-waits for bridge + object. */
93
170
  r3fContextMenu(idOrUuid: string): Chainable<void>;
94
- /** Hover over a 3D object by testId or uuid. */
171
+ /** Hover over a 3D object by testId or uuid. Auto-waits for bridge + object. */
95
172
  r3fHover(idOrUuid: string): Chainable<void>;
96
- /** Drag a 3D object with a world-space delta vector. */
173
+ /** Unhover / pointer-leave resets hover state. Auto-waits for bridge. */
174
+ r3fUnhover(): Chainable<void>;
175
+ /** Drag a 3D object with a world-space delta vector. Auto-waits for bridge + object. */
97
176
  r3fDrag(idOrUuid: string, delta: { x: number; y: number; z: number }): Chainable<void>;
98
- /** Dispatch a wheel/scroll event on a 3D object. */
177
+ /** Dispatch a wheel/scroll event on a 3D object. Auto-waits for bridge + object. */
99
178
  r3fWheel(idOrUuid: string, options?: { deltaY?: number; deltaX?: number }): Chainable<void>;
100
- /** Click empty space to trigger onPointerMissed handlers. */
179
+ /** Click empty space to trigger onPointerMissed handlers. Auto-waits for bridge. */
101
180
  r3fPointerMiss(): Chainable<void>;
102
- /** Draw a freeform path on the canvas (for drawing/annotation apps). */
181
+ /** Draw a freeform path on the canvas (for drawing/annotation apps). Auto-waits for bridge. */
103
182
  r3fDrawPath(
104
183
  points: Array<{ x: number; y: number; pressure?: number }>,
105
184
  options?: { stepDelayMs?: number; pointerType?: 'mouse' | 'pen' | 'touch'; clickAtEnd?: boolean },
106
185
  ): Chainable<{ eventCount: number; pointCount: number }>;
107
186
 
108
187
  // ---- Selection ----
109
- /** Select a 3D object (highlights in scene). */
188
+ /** Select a 3D object (highlights in scene). Auto-waits for bridge + object. */
110
189
  r3fSelect(idOrUuid: string): Chainable<void>;
111
- /** Clear the current selection. */
190
+ /** Clear the current selection. Auto-waits for bridge. */
112
191
  r3fClearSelection(): Chainable<void>;
113
192
 
114
193
  // ---- Queries ----
115
194
  /** Get object metadata by testId or uuid. */
116
195
  r3fGetObject(idOrUuid: string): Chainable<ObjectMetadata | null>;
196
+ /** Get object metadata by testId. */
197
+ r3fGetByTestId(testId: string): Chainable<ObjectMetadata | null>;
198
+ /** Get all objects with the given name (object.name). */
199
+ r3fGetByName(name: string): Chainable<ObjectMetadata[]>;
200
+ /** Get object metadata by uuid only. */
201
+ r3fGetByUuid(uuid: string): Chainable<ObjectMetadata | null>;
202
+ /** Get direct children of an object by testId or uuid. */
203
+ r3fGetChildren(idOrUuid: string): Chainable<ObjectMetadata[]>;
204
+ /** Get parent of an object by testId or uuid. */
205
+ r3fGetParent(idOrUuid: string): Chainable<ObjectMetadata | null>;
206
+ /** Get the R3F canvas element (data-r3f-canvas). */
207
+ r3fGetCanvas(): Chainable<JQuery<HTMLCanvasElement>>;
208
+ /** Get world-space position [x, y, z] of an object. */
209
+ r3fGetWorldPosition(idOrUuid: string): Chainable<[number, number, number] | null>;
210
+ /** Compare two scene snapshots (added, removed, changed). */
211
+ r3fDiffSnapshots(before: SceneSnapshot, after: SceneSnapshot): Chainable<SceneDiff>;
212
+ /** Run an action and return { added, removed } object count change. */
213
+ r3fTrackObjectCount(action: () => Cypress.Chainable<unknown>): Chainable<{ added: number; removed: number }>;
117
214
  /** Get heavy inspection data (Tier 2) by testId or uuid. */
118
215
  r3fInspect(idOrUuid: string): Chainable<ObjectInspection | null>;
119
216
  /** Take a full scene snapshot. */
@@ -124,6 +221,10 @@ declare global {
124
221
  // ---- BIM/CAD queries ----
125
222
  /** Get all objects of a given Three.js type (e.g. "Mesh", "Group", "Line"). */
126
223
  r3fGetByType(type: string): Chainable<ObjectMetadata[]>;
224
+ /** Get all objects with a given geometry type (e.g. "BoxGeometry"). */
225
+ r3fGetByGeometryType(type: string): Chainable<ObjectMetadata[]>;
226
+ /** Get all objects with a given material type (e.g. "MeshStandardMaterial"). */
227
+ r3fGetByMaterialType(type: string): Chainable<ObjectMetadata[]>;
127
228
  /** Get objects that have a specific userData key (and optionally matching value). */
128
229
  r3fGetByUserData(key: string, value?: unknown): Chainable<ObjectMetadata[]>;
129
230
  /** Count objects of a given Three.js type. */
@@ -131,6 +232,10 @@ declare global {
131
232
  /** Batch lookup: get metadata for multiple objects by testId or uuid. */
132
233
  r3fGetObjects(ids: string[]): Chainable<Record<string, ObjectMetadata | null>>;
133
234
 
235
+ // ---- Camera ----
236
+ /** Get current camera state (position, rotation, fov, near, far, zoom, target). */
237
+ r3fGetCameraState(): Chainable<CameraState>;
238
+
134
239
  // ---- Waiters ----
135
240
  /** Wait until the scene is ready (bridge available, object count stable). */
136
241
  r3fWaitForSceneReady(options?: {
@@ -160,6 +265,11 @@ declare global {
160
265
  pollIntervalMs?: number;
161
266
  timeout?: number;
162
267
  }): Chainable<{ newObjects: ObjectMetadata[]; newUuids: string[]; count: number }>;
268
+ /** Wait until an object (by testId or uuid) is no longer in the scene. */
269
+ r3fWaitForObjectRemoved(
270
+ idOrUuid: string,
271
+ options?: { bridgeTimeout?: number; pollIntervalMs?: number; timeout?: number },
272
+ ): Chainable<void>;
163
273
  }
164
274
 
165
275
  interface Assertion {
@@ -168,8 +278,10 @@ declare global {
168
278
  r3fExist(idOrUuid: string): Assertion;
169
279
  /** Assert that a 3D object is visible. */
170
280
  r3fVisible(idOrUuid: string): Assertion;
171
- /** Assert object position within tolerance. */
281
+ /** Assert object local position within tolerance. */
172
282
  r3fPosition(idOrUuid: string, expected: [number, number, number], tolerance?: number): Assertion;
283
+ /** Assert object world position within tolerance. */
284
+ r3fWorldPosition(idOrUuid: string, expected: [number, number, number], tolerance?: number): Assertion;
173
285
  /** Assert object rotation (Euler radians) within tolerance. */
174
286
  r3fRotation(idOrUuid: string, expected: [number, number, number], tolerance?: number): Assertion;
175
287
  /** Assert object scale within tolerance. */
@@ -224,6 +336,26 @@ declare global {
224
336
  r3fTotalTriangleCount(expected: number): Assertion;
225
337
  /** Assert total triangle count is less than a maximum (performance budget). */
226
338
  r3fTotalTriangleCountLessThan(max: number): Assertion;
339
+
340
+ // ---- Camera assertions ----
341
+ /** Assert camera position within tolerance. */
342
+ r3fCameraPosition(expected: [number, number, number], tolerance?: number): Assertion;
343
+ /** Assert camera field of view (PerspectiveCamera). */
344
+ r3fCameraFov(expected: number, tolerance?: number): Assertion;
345
+ /** Assert camera near clipping plane. */
346
+ r3fCameraNear(expected: number, tolerance?: number): Assertion;
347
+ /** Assert camera far clipping plane. */
348
+ r3fCameraFar(expected: number, tolerance?: number): Assertion;
349
+ /** Assert camera zoom level. */
350
+ r3fCameraZoom(expected: number, tolerance?: number): Assertion;
351
+
352
+ // ---- Batch assertions ----
353
+ /** Assert ALL given objects exist. Accepts array of ids or glob pattern (e.g. "wall-*"). */
354
+ r3fAllExist(idsOrPattern: string[] | string): Assertion;
355
+ /** Assert ALL given objects are visible. Accepts array of ids or glob pattern. */
356
+ r3fAllVisible(idsOrPattern: string[] | string): Assertion;
357
+ /** Assert NONE of the given objects exist. Accepts array of ids or glob pattern. */
358
+ r3fNoneExist(idsOrPattern: string[] | string): Assertion;
227
359
  }
228
360
  }
229
361
  }