'use strict'; // These tests rely on the User Agent providing an implementation of // platform sensor backends. // // In Chromium-based browsers this implementation is provided by a polyfill // in order to reduce the amount of test-only code shipped to users. To enable // these tests the browser must be run with these options: // // --enable-blink-features=MojoJS,MojoJSTest async function loadChromiumResources() { await import('/resources/chromium/generic_sensor_mocks.js'); } async function initialize_generic_sensor_tests() { if (typeof GenericSensorTest === 'undefined') { const script = document.createElement('script'); script.src = '/resources/test-only-api.js'; script.async = false; const p = new Promise((resolve, reject) => { script.onload = () => { resolve(); }; script.onerror = e => { reject(e); }; }) document.head.appendChild(script); await p; if (isChromiumBased) { await loadChromiumResources(); } } assert_implements(GenericSensorTest, 'GenericSensorTest is unavailable.'); let sensorTest = new GenericSensorTest(); await sensorTest.initialize(); return sensorTest; } function sensor_test(func, name, properties) { promise_test(async (t) => { t.add_cleanup(() => { if (sensorTest) return sensorTest.reset(); }); let sensorTest = await initialize_generic_sensor_tests(); return func(t, sensorTest.getSensorProvider()); }, name, properties); } const MOTION_ROTATION_EPSILON = 1e-8; function generateMotionData(accelerationX, accelerationY, accelerationZ, accelerationIncludingGravityX, accelerationIncludingGravityY, accelerationIncludingGravityZ, rotationRateAlpha, rotationRateBeta, rotationRateGamma, interval = 16) { const motionData = {accelerationX: accelerationX, accelerationY: accelerationY, accelerationZ: accelerationZ, accelerationIncludingGravityX: accelerationIncludingGravityX, accelerationIncludingGravityY: accelerationIncludingGravityY, accelerationIncludingGravityZ: accelerationIncludingGravityZ, rotationRateAlpha: rotationRateAlpha, rotationRateBeta: rotationRateBeta, rotationRateGamma: rotationRateGamma, interval: interval}; return motionData; } function generateOrientationData(alpha, beta, gamma, absolute) { const orientationData = {alpha: alpha, beta: beta, gamma: gamma, absolute: absolute}; return orientationData; } async function setMockSensorDataForType(sensorProvider, sensorType, mockDataArray) { const createdSensor = await sensorProvider.getCreatedSensor(sensorType); // We call setSensorReadingAndUpdateSharedBuffer() rather than // setSensorReading() to accommodate Blink's Device Orientation // implementation, which uses its own timer to read the sensor's shared // memory buffer rather than relying on SensorReadingChanged(). This timer // may fire out of sync with the JS timer in MockSensor.startReading(), so // the former might read the shared memory buffer before the latter has // updated |this.buffer_|. We thus immediately update the buffer here // (without consuming data from the ring buffer). return createdSensor.setSensorReadingImmediately([mockDataArray]); } // Device[Orientation|Motion]EventPump treat NaN as a missing value. let nullToNan = x => (x === null ? NaN : x); function setMockMotionData(sensorProvider, motionData) { const degToRad = Math.PI / 180; return Promise.all([ setMockSensorDataForType(sensorProvider, "Accelerometer", [ nullToNan(motionData.accelerationIncludingGravityX), nullToNan(motionData.accelerationIncludingGravityY), nullToNan(motionData.accelerationIncludingGravityZ), ]), setMockSensorDataForType(sensorProvider, "LinearAccelerationSensor", [ nullToNan(motionData.accelerationX), nullToNan(motionData.accelerationY), nullToNan(motionData.accelerationZ), ]), setMockSensorDataForType(sensorProvider, "Gyroscope", [ nullToNan(motionData.rotationRateAlpha) * degToRad, nullToNan(motionData.rotationRateBeta) * degToRad, nullToNan(motionData.rotationRateGamma) * degToRad, ]), ]); } function setMockOrientationData(sensorProvider, orientationData) { let sensorType = orientationData.absolute ? "AbsoluteOrientationEulerAngles" : "RelativeOrientationEulerAngles"; return setMockSensorDataForType(sensorProvider, sensorType, [ nullToNan(orientationData.beta), nullToNan(orientationData.gamma), nullToNan(orientationData.alpha), ]); } function assertEventEquals(actualEvent, expectedEvent) { for (let key1 of Object.keys(Object.getPrototypeOf(expectedEvent))) { if (typeof expectedEvent[key1] === "object" && expectedEvent[key1] !== null) { for (let key2 of Object.keys(expectedEvent[key1])) { assert_equals(actualEvent[key1][key2], expectedEvent[key1][key2], `$[key1].$[key2]`); } } else { assert_equals(actualEvent[key1], expectedEvent[key1], key1); } } } function getExpectedOrientationEvent(expectedOrientationData) { return new DeviceOrientationEvent('deviceorientation', { alpha: expectedOrientationData.alpha, beta: expectedOrientationData.beta, gamma: expectedOrientationData.gamma, absolute: expectedOrientationData.absolute, }); } function getExpectedAbsoluteOrientationEvent(expectedOrientationData) { return new DeviceOrientationEvent('deviceorientationabsolute', { alpha: expectedOrientationData.alpha, beta: expectedOrientationData.beta, gamma: expectedOrientationData.gamma, absolute: expectedOrientationData.absolute, }); } function getExpectedMotionEvent(expectedMotionData) { return new DeviceMotionEvent('devicemotion', { acceleration: { x: expectedMotionData.accelerationX, y: expectedMotionData.accelerationY, z: expectedMotionData.accelerationZ, }, accelerationIncludingGravity: { x: expectedMotionData.accelerationIncludingGravityX, y: expectedMotionData.accelerationIncludingGravityY, z: expectedMotionData.accelerationIncludingGravityZ, }, rotationRate: { alpha: expectedMotionData.rotationRateAlpha, beta: expectedMotionData.rotationRateBeta, gamma: expectedMotionData.rotationRateGamma, }, interval: expectedMotionData.interval, }); } function waitForEvent(expected_event) { return new Promise((resolve, reject) => { window.addEventListener(expected_event.type, (event) => { try { assertEventEquals(event, expected_event); resolve(); } catch (e) { reject(e); } }, { once: true }); }); }