import * as THREE from 'three'; import {describe, it, expect} from 'vitest'; import {XRDeviceCamera} from './XRDeviceCamera'; import { detectDeviceCameraTarget, getCameraParametersSnapshot, isDeviceCameraPoseAvailable, } from './CameraUtils'; function makeXrCameras(count: number): THREE.WebXRArrayCamera { return { cameras: new Array(count).fill({}), } as unknown as THREE.WebXRArrayCamera; } function makeDeviceCamera(withSimulatorCamera: boolean): XRDeviceCamera { return { simulatorCamera: withSimulatorCamera ? new THREE.PerspectiveCamera() : undefined, } as unknown as XRDeviceCamera; } describe('detectDeviceCameraTarget', () => { it('picks the Quest profile in the Meta Quest browser', () => { expect( detectDeviceCameraTarget( 'Mozilla/5.0 (X11; Linux x86_64; Quest 3) AppleWebKit/537.36 ' + '(KHTML, like Gecko) OculusBrowser/40.0 Chrome/136.0 VR Safari/537.36' ) ).toBe('quest3'); }); it('defaults to the Galaxy XR profile', () => { expect( detectDeviceCameraTarget( 'Mozilla/5.0 (Linux; Android 14; SM-I610) AppleWebKit/537.36 ' + '(KHTML, like Gecko) Chrome/136.0 Mobile Safari/537.36' ) ).toBe('galaxyxr'); expect(detectDeviceCameraTarget('')).toBe('galaxyxr'); }); }); describe('isDeviceCameraPoseAvailable', () => { it('is false before either camera source is ready', () => { expect(isDeviceCameraPoseAvailable(undefined, null)).toBe(false); expect(isDeviceCameraPoseAvailable(undefined, makeXrCameras(0))).toBe( false ); }); it('is true when the simulator or XR camera is ready', () => { expect(isDeviceCameraPoseAvailable(makeDeviceCamera(true), null)).toBe( true ); expect(isDeviceCameraPoseAvailable(undefined, makeXrCameras(2))).toBe(true); }); }); describe('getCameraParametersSnapshot', () => { const renderCamera = new THREE.PerspectiveCamera(75, 1.5, 0.1, 100); renderCamera.updateMatrixWorld(); it('returns null while no camera pose is available', () => { const snapshot = getCameraParametersSnapshot( renderCamera, null, makeDeviceCamera(false), 'galaxyxr' ); expect(snapshot).toBeNull(); }); it('returns a full snapshot once the simulator camera is available', () => { const snapshot = getCameraParametersSnapshot( renderCamera, null, makeDeviceCamera(true), 'galaxyxr' ); expect(snapshot).not.toBeNull(); expect(snapshot!.clipFromView).toBeInstanceOf(THREE.Matrix4); expect(snapshot!.viewFromClip).toBeInstanceOf(THREE.Matrix4); expect(snapshot!.worldFromView).toBeInstanceOf(THREE.Matrix4); expect(snapshot!.worldFromClip).toBeInstanceOf(THREE.Matrix4); }); });