@webspatial/core-sdk 1.4.0 → 1.6.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/CHANGELOG.md +34 -1
- package/dist/iife/index.d.ts +171 -12
- package/dist/iife/index.global.js +11 -11
- package/dist/iife/index.global.js.map +1 -1
- package/dist/index.d.ts +171 -12
- package/dist/index.js +460 -114
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/JSBCommand.ts +40 -2
- package/src/Spatial.ts +1 -1
- package/src/SpatialSession.ts +4 -2
- package/src/SpatializedElement.ts +10 -10
- package/src/SpatializedElementCreator.ts +5 -2
- package/src/SpatializedStatic3DElement.test.ts +15 -1
- package/src/SpatializedStatic3DElement.ts +167 -8
- package/src/WebMsgCommand.ts +22 -0
- package/src/platform-adapter/index.ts +2 -2
- package/src/platform-adapter/{xr/XRPlatform.ts → pico-os/PicoOSPlatform.ts} +5 -7
- package/src/reality/entity/SpatialEntity.ts +4 -0
- package/src/reality/entity/SpatialModelEntity.ts +6 -0
- package/src/scene-polyfill.manifest.test.ts +402 -0
- package/src/scene-polyfill.test.ts +108 -18
- package/src/scene-polyfill.ts +284 -26
- package/src/types/global.d.ts +8 -0
- package/src/types/types.ts +71 -0
- package/src/utils.ts +21 -0
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
vi.mock('./JSBCommand', () => {
|
|
4
|
+
return {
|
|
5
|
+
createSpatialSceneCommand: vi.fn().mockImplementation(() => ({
|
|
6
|
+
executeSync: vi.fn().mockReturnValue({
|
|
7
|
+
data: { id: 'scene-1', windowProxy: {} },
|
|
8
|
+
}),
|
|
9
|
+
})),
|
|
10
|
+
FocusScene: vi.fn().mockImplementation(() => ({
|
|
11
|
+
execute: vi.fn().mockResolvedValue(undefined),
|
|
12
|
+
})),
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
function addDataManifest(manifest: any) {
|
|
17
|
+
const link = document.createElement('link')
|
|
18
|
+
link.rel = 'manifest'
|
|
19
|
+
const json = JSON.stringify(manifest)
|
|
20
|
+
link.href = 'data:application/manifest+json,' + encodeURIComponent(json)
|
|
21
|
+
document.head.appendChild(link)
|
|
22
|
+
return () => {
|
|
23
|
+
document.head.removeChild(link)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function waitTick() {
|
|
28
|
+
await Promise.resolve()
|
|
29
|
+
await new Promise(r => setTimeout(r, 0))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('setupManifest applies overrides to xr_window_defaults / xr_volume_defaults', () => {
|
|
33
|
+
it('applies window overrides without affecting volume defaults', async () => {
|
|
34
|
+
vi.resetModules()
|
|
35
|
+
const cleanup = addDataManifest({
|
|
36
|
+
xr_spatial_scene: {
|
|
37
|
+
defaultSize: { width: '200px', height: '300px' },
|
|
38
|
+
resizability: { minWidth: '300px', minHeight: '400px' },
|
|
39
|
+
worldScaling: 'dynamic',
|
|
40
|
+
worldAlignment: 'gravityAligned',
|
|
41
|
+
baseplateVisibility: 'visible',
|
|
42
|
+
overrides: {
|
|
43
|
+
window_scene: {
|
|
44
|
+
defaultSize: { width: '1000px' },
|
|
45
|
+
resizability: { minWidth: '500px', maxWidth: '1200px' },
|
|
46
|
+
worldAlignment: 'automatic',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
|
|
52
|
+
hijackWindowOpen(window)
|
|
53
|
+
await waitTick()
|
|
54
|
+
|
|
55
|
+
let winDefaults: any
|
|
56
|
+
initScene(
|
|
57
|
+
'w',
|
|
58
|
+
pre => {
|
|
59
|
+
winDefaults = pre
|
|
60
|
+
return pre
|
|
61
|
+
},
|
|
62
|
+
{ type: 'window' },
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
let volDefaults: any
|
|
66
|
+
initScene(
|
|
67
|
+
'v',
|
|
68
|
+
pre => {
|
|
69
|
+
volDefaults = pre
|
|
70
|
+
return pre
|
|
71
|
+
},
|
|
72
|
+
{ type: 'volume' },
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
// window uses overrides + formatted to px
|
|
76
|
+
expect(winDefaults).toEqual(
|
|
77
|
+
expect.objectContaining({
|
|
78
|
+
defaultSize: { width: '1000px', height: '300px' },
|
|
79
|
+
resizability: expect.objectContaining({
|
|
80
|
+
minWidth: '500px',
|
|
81
|
+
minHeight: '400px',
|
|
82
|
+
maxWidth: '1200px',
|
|
83
|
+
}),
|
|
84
|
+
worldAlignment: 'automatic',
|
|
85
|
+
worldScaling: 'dynamic',
|
|
86
|
+
baseplateVisibility: 'visible',
|
|
87
|
+
}),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
// volume remains from top-level only (no volume override) and formats:
|
|
91
|
+
// - pre passed to initScene is the raw manifest values (unformatted)
|
|
92
|
+
expect(volDefaults).toEqual(
|
|
93
|
+
expect.objectContaining({
|
|
94
|
+
defaultSize: {
|
|
95
|
+
width: '200px',
|
|
96
|
+
height: '300px',
|
|
97
|
+
// depth may be omitted in manifest; defaults keep only provided keys
|
|
98
|
+
},
|
|
99
|
+
resizability: expect.objectContaining({
|
|
100
|
+
minWidth: '300px',
|
|
101
|
+
minHeight: '400px',
|
|
102
|
+
}),
|
|
103
|
+
worldAlignment: 'gravityAligned',
|
|
104
|
+
worldScaling: 'dynamic',
|
|
105
|
+
baseplateVisibility: 'visible',
|
|
106
|
+
}),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
cleanup()
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('applies volume overrides without affecting window defaults', async () => {
|
|
113
|
+
vi.resetModules()
|
|
114
|
+
const cleanup = addDataManifest({
|
|
115
|
+
xr_spatial_scene: {
|
|
116
|
+
defaultSize: { width: '120px', height: '240px' },
|
|
117
|
+
resizability: { minWidth: '200px', minHeight: '300px' },
|
|
118
|
+
overrides: {
|
|
119
|
+
volume_scene: {
|
|
120
|
+
defaultSize: { width: '2m', height: '2m', depth: '2m' },
|
|
121
|
+
resizability: { minWidth: '1m' },
|
|
122
|
+
baseplateVisibility: 'automatic',
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
})
|
|
127
|
+
const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
|
|
128
|
+
hijackWindowOpen(window)
|
|
129
|
+
await waitTick()
|
|
130
|
+
|
|
131
|
+
let volDefaults: any
|
|
132
|
+
initScene(
|
|
133
|
+
'v',
|
|
134
|
+
pre => {
|
|
135
|
+
volDefaults = pre
|
|
136
|
+
return pre
|
|
137
|
+
},
|
|
138
|
+
{ type: 'volume' },
|
|
139
|
+
)
|
|
140
|
+
let winDefaults: any
|
|
141
|
+
initScene(
|
|
142
|
+
'w',
|
|
143
|
+
pre => {
|
|
144
|
+
winDefaults = pre
|
|
145
|
+
return pre
|
|
146
|
+
},
|
|
147
|
+
{ type: 'window' },
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
// volume uses overrides + formatting (m for defaultSize, px for resizability)
|
|
151
|
+
expect(volDefaults).toEqual(
|
|
152
|
+
expect.objectContaining({
|
|
153
|
+
defaultSize: { width: '2m', height: '2m', depth: '2m' },
|
|
154
|
+
resizability: expect.objectContaining({
|
|
155
|
+
minWidth: '1m',
|
|
156
|
+
}),
|
|
157
|
+
baseplateVisibility: 'automatic',
|
|
158
|
+
}),
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
// window remains from top-level only (no window override)
|
|
162
|
+
expect(winDefaults).toEqual(
|
|
163
|
+
expect.objectContaining({
|
|
164
|
+
defaultSize: { width: '120px', height: '240px' },
|
|
165
|
+
resizability: expect.objectContaining({
|
|
166
|
+
minWidth: '200px',
|
|
167
|
+
minHeight: '300px',
|
|
168
|
+
}),
|
|
169
|
+
}),
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
cleanup()
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
it('applies provided mixed-case defaults and empty volume override; volume pre is formatted as expected', async () => {
|
|
176
|
+
vi.resetModules()
|
|
177
|
+
const cleanup = addDataManifest({
|
|
178
|
+
xr_spatial_scene: {
|
|
179
|
+
default_size: {
|
|
180
|
+
width: '1024px',
|
|
181
|
+
height: '1024px',
|
|
182
|
+
depth: '55px',
|
|
183
|
+
},
|
|
184
|
+
resizability: {
|
|
185
|
+
minWidth: '1024px',
|
|
186
|
+
minHeight: '1024px',
|
|
187
|
+
maxWidth: '2000px',
|
|
188
|
+
maxHeight: '2000px',
|
|
189
|
+
},
|
|
190
|
+
worldScaling: 'automatic',
|
|
191
|
+
worldAlignment: 'automatic',
|
|
192
|
+
baseplateVisibility: 'visible',
|
|
193
|
+
overrides: {
|
|
194
|
+
window_scene: {
|
|
195
|
+
default_size: {
|
|
196
|
+
width: '500px',
|
|
197
|
+
height: '500px',
|
|
198
|
+
depth: '55px',
|
|
199
|
+
},
|
|
200
|
+
resizability: {
|
|
201
|
+
minWidth: '500px',
|
|
202
|
+
minHeight: '500px',
|
|
203
|
+
maxWidth: '1000px',
|
|
204
|
+
maxHeight: '1000px',
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
volume_scene: {},
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
})
|
|
211
|
+
const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
|
|
212
|
+
hijackWindowOpen(window)
|
|
213
|
+
await waitTick()
|
|
214
|
+
|
|
215
|
+
const pxToM = (px: number) => px / 1360
|
|
216
|
+
|
|
217
|
+
let volDefaults: any
|
|
218
|
+
initScene(
|
|
219
|
+
'sa',
|
|
220
|
+
pre => {
|
|
221
|
+
volDefaults = pre
|
|
222
|
+
return { ...pre }
|
|
223
|
+
},
|
|
224
|
+
{ type: 'volume' },
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
expect(volDefaults).toEqual(
|
|
228
|
+
expect.objectContaining({
|
|
229
|
+
defaultSize: {
|
|
230
|
+
width: '1024px',
|
|
231
|
+
height: '1024px',
|
|
232
|
+
depth: '55px',
|
|
233
|
+
},
|
|
234
|
+
resizability: expect.objectContaining({
|
|
235
|
+
minWidth: '1024px',
|
|
236
|
+
minHeight: '1024px',
|
|
237
|
+
maxWidth: '2000px',
|
|
238
|
+
maxHeight: '2000px',
|
|
239
|
+
}),
|
|
240
|
+
worldScaling: 'automatic',
|
|
241
|
+
worldAlignment: 'automatic',
|
|
242
|
+
baseplateVisibility: 'visible',
|
|
243
|
+
}),
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
// Snapshot current 'sa' internal config before cleanup
|
|
247
|
+
const { __getSceneConfigSnapshotForTest } = await import('./scene-polyfill')
|
|
248
|
+
const snap = __getSceneConfigSnapshotForTest('sa')
|
|
249
|
+
expect(snap).toEqual(
|
|
250
|
+
expect.objectContaining({
|
|
251
|
+
type: 'volume',
|
|
252
|
+
defaultSize: {
|
|
253
|
+
width: pxToM(1024),
|
|
254
|
+
height: pxToM(1024),
|
|
255
|
+
depth: pxToM(55),
|
|
256
|
+
},
|
|
257
|
+
resizability: expect.objectContaining({
|
|
258
|
+
minWidth: 1024,
|
|
259
|
+
minHeight: 1024,
|
|
260
|
+
maxWidth: 2000,
|
|
261
|
+
maxHeight: 2000,
|
|
262
|
+
}),
|
|
263
|
+
}),
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
cleanup()
|
|
267
|
+
})
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
describe('manifest error paths and empty configs', () => {
|
|
271
|
+
function addInvalidDataManifest() {
|
|
272
|
+
const link = document.createElement('link')
|
|
273
|
+
link.rel = 'manifest'
|
|
274
|
+
// Invalid JSON payload to force parse failure in getPWAManifest
|
|
275
|
+
link.href = 'data:application/manifest+json,INVALID_JSON'
|
|
276
|
+
document.head.appendChild(link)
|
|
277
|
+
return () => {
|
|
278
|
+
document.head.removeChild(link)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
it('falls back to built-in defaults when no manifest link is present', async () => {
|
|
283
|
+
vi.resetModules()
|
|
284
|
+
const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
|
|
285
|
+
hijackWindowOpen(window)
|
|
286
|
+
await waitTick()
|
|
287
|
+
|
|
288
|
+
let winPre: any
|
|
289
|
+
initScene(
|
|
290
|
+
'no-manifest-win',
|
|
291
|
+
pre => {
|
|
292
|
+
winPre = pre
|
|
293
|
+
return pre
|
|
294
|
+
},
|
|
295
|
+
{ type: 'window' },
|
|
296
|
+
)
|
|
297
|
+
let volPre: any
|
|
298
|
+
initScene(
|
|
299
|
+
'no-manifest-vol',
|
|
300
|
+
pre => {
|
|
301
|
+
volPre = pre
|
|
302
|
+
return pre
|
|
303
|
+
},
|
|
304
|
+
{ type: 'volume' },
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
// Window defaults: numbers in px domain for width/height
|
|
308
|
+
expect(winPre).toEqual(
|
|
309
|
+
expect.objectContaining({
|
|
310
|
+
defaultSize: { width: 1280, height: 720 },
|
|
311
|
+
}),
|
|
312
|
+
)
|
|
313
|
+
// Volume defaults: strings in meters for width/height/depth
|
|
314
|
+
expect(volPre).toEqual(
|
|
315
|
+
expect.objectContaining({
|
|
316
|
+
defaultSize: { width: '0.94m', height: '0.94m', depth: '0.94m' },
|
|
317
|
+
}),
|
|
318
|
+
)
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
it('falls back to built-in defaults when manifest parsing fails', async () => {
|
|
322
|
+
vi.resetModules()
|
|
323
|
+
const cleanup = addInvalidDataManifest()
|
|
324
|
+
const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
|
|
325
|
+
hijackWindowOpen(window)
|
|
326
|
+
await waitTick()
|
|
327
|
+
|
|
328
|
+
let winPre: any
|
|
329
|
+
initScene(
|
|
330
|
+
'bad-manifest-win',
|
|
331
|
+
pre => {
|
|
332
|
+
winPre = pre
|
|
333
|
+
return pre
|
|
334
|
+
},
|
|
335
|
+
{ type: 'window' },
|
|
336
|
+
)
|
|
337
|
+
let volPre: any
|
|
338
|
+
initScene(
|
|
339
|
+
'bad-manifest-vol',
|
|
340
|
+
pre => {
|
|
341
|
+
volPre = pre
|
|
342
|
+
return pre
|
|
343
|
+
},
|
|
344
|
+
{ type: 'volume' },
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
expect(winPre).toEqual(
|
|
348
|
+
expect.objectContaining({
|
|
349
|
+
defaultSize: { width: 1280, height: 720 },
|
|
350
|
+
}),
|
|
351
|
+
)
|
|
352
|
+
expect(volPre).toEqual(
|
|
353
|
+
expect.objectContaining({
|
|
354
|
+
defaultSize: { width: '0.94m', height: '0.94m', depth: '0.94m' },
|
|
355
|
+
}),
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
cleanup()
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
it('ignores empty xr_spatial_scene object and preserves built-in defaults', async () => {
|
|
362
|
+
vi.resetModules()
|
|
363
|
+
const cleanup = addDataManifest({
|
|
364
|
+
xr_spatial_scene: {},
|
|
365
|
+
})
|
|
366
|
+
const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
|
|
367
|
+
hijackWindowOpen(window)
|
|
368
|
+
await waitTick()
|
|
369
|
+
|
|
370
|
+
let winPre: any
|
|
371
|
+
initScene(
|
|
372
|
+
'empty-xr-win',
|
|
373
|
+
pre => {
|
|
374
|
+
winPre = pre
|
|
375
|
+
return pre
|
|
376
|
+
},
|
|
377
|
+
{ type: 'window' },
|
|
378
|
+
)
|
|
379
|
+
let volPre: any
|
|
380
|
+
initScene(
|
|
381
|
+
'empty-xr-vol',
|
|
382
|
+
pre => {
|
|
383
|
+
volPre = pre
|
|
384
|
+
return pre
|
|
385
|
+
},
|
|
386
|
+
{ type: 'volume' },
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
expect(winPre).toEqual(
|
|
390
|
+
expect.objectContaining({
|
|
391
|
+
defaultSize: { width: 1280, height: 720 },
|
|
392
|
+
}),
|
|
393
|
+
)
|
|
394
|
+
expect(volPre).toEqual(
|
|
395
|
+
expect.objectContaining({
|
|
396
|
+
defaultSize: { width: '0.94m', height: '0.94m', depth: '0.94m' },
|
|
397
|
+
}),
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
cleanup()
|
|
401
|
+
})
|
|
402
|
+
})
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { describe, expect, test, vi, beforeEach, afterEach, it } from 'vitest'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
formatSceneConfig,
|
|
4
|
+
initScene,
|
|
5
|
+
injectSceneHook,
|
|
6
|
+
__getSceneConfigSnapshotForTest,
|
|
7
|
+
} from './scene-polyfill'
|
|
3
8
|
import { SpatialSceneCreationOptions } from './types/types'
|
|
9
|
+
import { pointToPhysical } from './physicalMetrics'
|
|
4
10
|
|
|
5
11
|
describe('test formatSceneConfig in window', () => {
|
|
6
12
|
test('should format window with no unit', () => {
|
|
@@ -79,6 +85,23 @@ describe('test formatSceneConfig in window', () => {
|
|
|
79
85
|
])
|
|
80
86
|
})
|
|
81
87
|
|
|
88
|
+
test('window mixed units: cm invalid and numbers treated as px', () => {
|
|
89
|
+
const config = {
|
|
90
|
+
defaultSize: {
|
|
91
|
+
width: '10cm',
|
|
92
|
+
height: 800,
|
|
93
|
+
},
|
|
94
|
+
} satisfies SpatialSceneCreationOptions
|
|
95
|
+
const [formatted, errors] = formatSceneConfig(config, 'window')
|
|
96
|
+
expect(errors).toEqual(['defaultSize.width'])
|
|
97
|
+
expect(formatted.defaultSize).toEqual(
|
|
98
|
+
expect.objectContaining({
|
|
99
|
+
height: 800,
|
|
100
|
+
}),
|
|
101
|
+
)
|
|
102
|
+
expect((formatted.defaultSize as any).width).toBeUndefined()
|
|
103
|
+
})
|
|
104
|
+
|
|
82
105
|
test('should format window with meter', () => {
|
|
83
106
|
const config = {
|
|
84
107
|
defaultSize: {
|
|
@@ -106,6 +129,27 @@ describe('test formatSceneConfig in window', () => {
|
|
|
106
129
|
})
|
|
107
130
|
})
|
|
108
131
|
|
|
132
|
+
describe('formatSceneConfig invalid unit (mixed)', () => {
|
|
133
|
+
test('volume defaultSize width cm invalid while numbers convert', () => {
|
|
134
|
+
const config = {
|
|
135
|
+
defaultSize: {
|
|
136
|
+
width: '10cm',
|
|
137
|
+
height: 1000,
|
|
138
|
+
depth: 100,
|
|
139
|
+
},
|
|
140
|
+
} satisfies SpatialSceneCreationOptions
|
|
141
|
+
const [formattedConfig, errors] = formatSceneConfig(config, 'volume')
|
|
142
|
+
expect(errors).toEqual(['defaultSize.width'])
|
|
143
|
+
expect(formattedConfig.defaultSize).toEqual(
|
|
144
|
+
expect.objectContaining({
|
|
145
|
+
height: pointToPhysical(1000),
|
|
146
|
+
depth: pointToPhysical(100),
|
|
147
|
+
}),
|
|
148
|
+
)
|
|
149
|
+
expect((formattedConfig.defaultSize as any).width).toBeUndefined()
|
|
150
|
+
})
|
|
151
|
+
})
|
|
152
|
+
|
|
109
153
|
describe('test formatSceneConfig in volume', () => {
|
|
110
154
|
test('should format volume with no unit', () => {
|
|
111
155
|
const config = {
|
|
@@ -123,15 +167,15 @@ describe('test formatSceneConfig in volume', () => {
|
|
|
123
167
|
} satisfies SpatialSceneCreationOptions
|
|
124
168
|
const [formattedConfig] = formatSceneConfig(config, 'volume')
|
|
125
169
|
expect(formattedConfig.defaultSize).toEqual({
|
|
126
|
-
width: 1,
|
|
127
|
-
height: 1,
|
|
128
|
-
depth: 1,
|
|
170
|
+
width: pointToPhysical(1),
|
|
171
|
+
height: pointToPhysical(1),
|
|
172
|
+
depth: pointToPhysical(1),
|
|
129
173
|
})
|
|
130
174
|
expect(formattedConfig.resizability).toEqual({
|
|
131
|
-
minWidth:
|
|
132
|
-
minHeight:
|
|
133
|
-
maxWidth:
|
|
134
|
-
maxHeight:
|
|
175
|
+
minWidth: 1,
|
|
176
|
+
minHeight: 1,
|
|
177
|
+
maxWidth: 1,
|
|
178
|
+
maxHeight: 1,
|
|
135
179
|
})
|
|
136
180
|
})
|
|
137
181
|
|
|
@@ -316,7 +360,7 @@ describe('injectScenePolyfill should call xrCurrentSceneDefaults and update scen
|
|
|
316
360
|
|
|
317
361
|
expect(mockFn).toHaveBeenCalledWith(
|
|
318
362
|
expect.objectContaining({
|
|
319
|
-
defaultSize: { width: 0.
|
|
363
|
+
defaultSize: { width: '0.94m', height: '0.94m', depth: '0.94m' },
|
|
320
364
|
}),
|
|
321
365
|
)
|
|
322
366
|
|
|
@@ -324,12 +368,16 @@ describe('injectScenePolyfill should call xrCurrentSceneDefaults and update scen
|
|
|
324
368
|
const { UpdateSceneConfig } = await import('./JSBCommand')
|
|
325
369
|
expect(UpdateSceneConfig).toHaveBeenCalledWith({
|
|
326
370
|
type: 'volume',
|
|
327
|
-
defaultSize: {
|
|
371
|
+
defaultSize: {
|
|
372
|
+
width: pointToPhysical(1),
|
|
373
|
+
height: pointToPhysical(1),
|
|
374
|
+
depth: pointToPhysical(1),
|
|
375
|
+
},
|
|
328
376
|
resizability: {
|
|
329
|
-
minWidth: 0.5
|
|
330
|
-
minHeight: 1
|
|
331
|
-
maxWidth: 0.5
|
|
332
|
-
maxHeight: 1
|
|
377
|
+
minWidth: 0.5,
|
|
378
|
+
minHeight: 1,
|
|
379
|
+
maxWidth: 0.5,
|
|
380
|
+
maxHeight: 1,
|
|
333
381
|
},
|
|
334
382
|
})
|
|
335
383
|
})
|
|
@@ -341,7 +389,7 @@ describe('initScene should receive defaultScene config by type', () => {
|
|
|
341
389
|
.fn()
|
|
342
390
|
.mockResolvedValue({ defaultSize: { width: 800, height: 600 } })
|
|
343
391
|
|
|
344
|
-
initScene('sa', mockFn)
|
|
392
|
+
initScene('sa-no-type', mockFn)
|
|
345
393
|
|
|
346
394
|
expect(mockFn).toHaveBeenCalledWith(
|
|
347
395
|
expect.objectContaining({ defaultSize: { width: 1280, height: 720 } }),
|
|
@@ -353,7 +401,7 @@ describe('initScene should receive defaultScene config by type', () => {
|
|
|
353
401
|
.fn()
|
|
354
402
|
.mockResolvedValue({ defaultSize: { width: 800, height: 600 } })
|
|
355
403
|
|
|
356
|
-
initScene('sa', mockFn, { type: 'window' })
|
|
404
|
+
initScene('sa-window', mockFn, { type: 'window' })
|
|
357
405
|
|
|
358
406
|
expect(mockFn).toHaveBeenCalledWith(
|
|
359
407
|
expect.objectContaining({ defaultSize: { width: 1280, height: 720 } }),
|
|
@@ -365,12 +413,54 @@ describe('initScene should receive defaultScene config by type', () => {
|
|
|
365
413
|
.fn()
|
|
366
414
|
.mockResolvedValue({ defaultSize: { width: 800, height: 600 } })
|
|
367
415
|
|
|
368
|
-
initScene('sa', mockFn, { type: 'volume' })
|
|
416
|
+
initScene('sa-volume', mockFn, { type: 'volume' })
|
|
369
417
|
|
|
370
418
|
expect(mockFn).toHaveBeenCalledWith(
|
|
371
419
|
expect.objectContaining({
|
|
372
|
-
defaultSize: { width: 0.
|
|
420
|
+
defaultSize: { width: '0.94m', height: '0.94m', depth: '0.94m' },
|
|
373
421
|
}),
|
|
374
422
|
)
|
|
375
423
|
})
|
|
424
|
+
|
|
425
|
+
it('with volume type and merge pre', () => {
|
|
426
|
+
const cb = vi.fn().mockImplementation(pre => ({
|
|
427
|
+
...pre,
|
|
428
|
+
defaultSize: { ...(pre.defaultSize as any), depth: '0.1m' },
|
|
429
|
+
}))
|
|
430
|
+
|
|
431
|
+
// pre-snapshot should be empty before initScene writes configMap
|
|
432
|
+
const preSnap = __getSceneConfigSnapshotForTest('sa')
|
|
433
|
+
expect(preSnap).toBeUndefined()
|
|
434
|
+
|
|
435
|
+
initScene('sa', cb, { type: 'volume' })
|
|
436
|
+
|
|
437
|
+
expect(cb).toHaveBeenCalledWith(
|
|
438
|
+
expect.objectContaining({
|
|
439
|
+
defaultSize: { width: '0.94m', height: '0.94m', depth: '0.94m' },
|
|
440
|
+
}),
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
const snap = __getSceneConfigSnapshotForTest('sa')
|
|
444
|
+
expect(snap).toEqual(
|
|
445
|
+
expect.objectContaining({
|
|
446
|
+
type: 'volume',
|
|
447
|
+
defaultSize: { width: 0.94, height: 0.94, depth: 0.1 },
|
|
448
|
+
}),
|
|
449
|
+
)
|
|
450
|
+
})
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
describe('initScene callback chaining', () => {
|
|
454
|
+
it('passes previous return value as next pre argument', () => {
|
|
455
|
+
const firstReturn = { defaultSize: { width: 1000, height: 1000 } }
|
|
456
|
+
const cb1 = vi.fn().mockReturnValue(firstReturn)
|
|
457
|
+
initScene('sa-chain', cb1)
|
|
458
|
+
expect(cb1).toHaveBeenCalledWith(
|
|
459
|
+
expect.objectContaining({ defaultSize: { width: 1280, height: 720 } }),
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
const cb2 = vi.fn().mockReturnValue({})
|
|
463
|
+
initScene('sa-chain', cb2)
|
|
464
|
+
expect(cb2).toHaveBeenCalledWith(firstReturn)
|
|
465
|
+
})
|
|
376
466
|
})
|