diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/orientation-event | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/orientation-event')
36 files changed, 1848 insertions, 0 deletions
diff --git a/testing/web-platform/tests/orientation-event/META.yml b/testing/web-platform/tests/orientation-event/META.yml new file mode 100644 index 0000000000..88014849d0 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/META.yml @@ -0,0 +1,4 @@ +spec: https://w3c.github.io/deviceorientation/ +suggested_reviewers: + - reillyeon + - timvolodine diff --git a/testing/web-platform/tests/orientation-event/README.md b/testing/web-platform/tests/orientation-event/README.md new file mode 100644 index 0000000000..14ea2f5117 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/README.md @@ -0,0 +1,8 @@ +The `resources/orientation-event-helpers.js` tests depend on the implementation of +the `GenericSensorTest` interface which is defined in [README.md](../generic-sensor/README.md). + +The Chromium implementation of the `GenericSensorTest` interface is located in +[generic_sensor_mocks.js](../resources/chromium/generic_sensor_mocks.js). + +Other browser vendors should provide their own implementations of +the `GenericSensorTest` interface. diff --git a/testing/web-platform/tests/orientation-event/device-orientation-events-of-detached-documents.https.html b/testing/web-platform/tests/orientation-event/device-orientation-events-of-detached-documents.https.html new file mode 100644 index 0000000000..f05be6d0d2 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/device-orientation-events-of-detached-documents.https.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html> +<head> +<title>Device sensor event listeners for `window` of detached documents.</title> +</head> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="resources/orientation-event-helpers.js"></script> +<script> + +promise_test(async t => { + const childFrame = document.createElement('iframe'); + childFrame.src = "/common/blank.html"; + document.body.append(childFrame); + + const childLoadWatcher = new EventWatcher(t, childFrame, ["load"]); + await childLoadWatcher.wait_for("load"); + + const contentWindow = childFrame.contentWindow; + const contentDocument = childFrame.contentDocument; + + await test_driver.set_permission({ name: 'accelerometer' }, 'granted', contentWindow); + await test_driver.set_permission({ name: 'gyroscope' }, 'granted', contentWindow); + await test_driver.set_permission({ name: 'magnetometer' }, 'granted', contentWindow); + + assert_equals(await contentWindow.DeviceOrientationEvent.requestPermission(), + 'granted'); + assert_equals(await contentWindow.DeviceMotionEvent.requestPermission(), + 'granted'); + + document.body.remove(childFrame); + + assert_not_equals(contentWindow, null); + assert_not_equals(contentDocument, null); + assert_equals(contentDocument.defaultView, null); + + contentWindow.addEventListener("devicemotion", () => {}); + contentWindow.addEventListener("deviceorientation", () => {}); + contentWindow.addEventListener("deviceorientationabsolute", () => {}); + +}, 'Adding an event listener on the window of a detached document does not crash.'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/orientation-event/device-orientation-events-unavailable-on-insecure-origins.html b/testing/web-platform/tests/orientation-event/device-orientation-events-unavailable-on-insecure-origins.html new file mode 100644 index 0000000000..6d2eee402f --- /dev/null +++ b/testing/web-platform/tests/orientation-event/device-orientation-events-unavailable-on-insecure-origins.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<title>Device Sensor Events not exposed to insecure origins</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="resources/orientation-event-helpers.js"></script> +<script> + +if (window.location.origin != get_host_info().HTTP_ORIGIN) { + window.location = get_host_info().HTTP_ORIGIN + window.location.pathname; + promise_test(_ => new Promise(_ => {}), "Stall tests on the wrong host."); +} else { + test(() => { + assert_false('DeviceMotionEvent' in window); + assert_false('DeviceOrientationEvent' in window); + assert_false('DeviceOrientationAbsoluteEvent' in window); + assert_false('DeviceMotionEventAcceleration' in window); + assert_false('DeviceMotionEventRotationRate' in window); + assert_false('ondevicemotion' in window); + assert_false('ondeviceorientation' in window); + assert_false('ondeviceorientationabsolute' in window); + }, 'Event interfaces and event handlers are not exposed on `window`.'); + + promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'devicemotion'); + await helper.initializeSensors(); + const motionData = generateMotionData(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + await helper.setData(motionData); + + window.ondevicemotion = t.unreached_func("devicemotion event should not be fired."); + + await new Promise(r => t.step_timeout(r, 1000)); + }, 'addEventListener() for `devicemotion` does not crash but the handler never fires.'); + + promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientation'); + await helper.initializeSensors(); + const orientationData = generateOrientationData(1.1, 2.2, 3.3, false); + await helper.setData(orientationData); + + window.ondeviceorientation = t.unreached_func("deviceorientation event should not be fired."); + + await new Promise(r => t.step_timeout(r, 1000)); + }, 'addEventListener() for `deviceorientation` does not crash but the handler never fires.'); + + promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientationabsolute'); + await helper.initializeSensors(); + const orientationData = generateOrientationData(1.1, 2.2, 3.3, true); + await helper.setData(orientationData); + + window.ondeviceorientationabsolute = t.unreached_func("deviceorientationabsolute event should not be fired."); + + await new Promise(r => t.step_timeout(r, 1000)); + }, 'addEventListener() for `deviceorientationabsolute` does not crash but the handler never fires.'); +} +</script> diff --git a/testing/web-platform/tests/orientation-event/idlharness.https.window.js b/testing/web-platform/tests/orientation-event/idlharness.https.window.js new file mode 100644 index 0000000000..ba816bb87c --- /dev/null +++ b/testing/web-platform/tests/orientation-event/idlharness.https.window.js @@ -0,0 +1,19 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: timeout=long + +// https://w3c.github.io/deviceorientation/spec-source-orientation.html + +'use strict'; + +idl_test( + ['orientation-event'], + ['html', 'dom'], + idl_array => { + idl_array.add_objects({ + Window: ['window'], + DeviceOrientationEvent: ['new DeviceOrientationEvent("foo")'], + DeviceMotionEvent: ['new DeviceMotionEvent("foo")'], + }); + } +); diff --git a/testing/web-platform/tests/orientation-event/motion/add-during-dispatch.https.html b/testing/web-platform/tests/orientation-event/motion/add-during-dispatch.https.html new file mode 100644 index 0000000000..262715ce55 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/add-during-dispatch.https.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'devicemotion'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const motionData = generateMotionData(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + await helper.setData(motionData); + + return new Promise((resolve, reject) => { + let result = reject; + window.addEventListener('devicemotion', event1 => { + // Now we are in event dispatch. + assertEventEquals(event1, getExpectedMotionEvent(motionData)); + + window.addEventListener('devicemotion', event2 => { + // Not called until the outer function returns. + assertEventEquals(event2, getExpectedMotionEvent(motionData)); + result(); + }, {once: true}); + + result = resolve; + }, {once: true}); + }); +}, 'Test no fire listeners added during event dispatch.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/motion/add-listener-from-callback.https.html b/testing/web-platform/tests/orientation-event/motion/add-listener-from-callback.https.html new file mode 100644 index 0000000000..1f8cca86b2 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/add-listener-from-callback.https.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'devicemotion'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const motionData = generateMotionData(1.1, 2.1, 3.1, + 1.2, 2.2, 3.2, + 1.3, 2.3, 3.3); + + let firstListener = null; + let secondListener = null; + let firstEventCount = 0; + let firstPromise = new Promise(resolve => { + firstListener = (event) => { + assert_true(event instanceof DeviceMotionEvent, 'event is DeviceMotionEvent'); + assert_equals(event.type, 'devicemotion', 'event.type is devicemotion'); + assert_true(event.target instanceof Window, 'event is fired on the window object'); + assertEventEquals(event, getExpectedMotionEvent(motionData)); + window.removeEventListener('devicemotion', firstListener); + if (++firstEventCount == 1) { + window.addEventListener('devicemotion', secondListener); + } + resolve(event); + }; + }); + + let secondEventCount = 0; + let secondPromise = new Promise(resolve => { + secondListener = (event) => { + assertEventEquals(event, getExpectedMotionEvent(motionData)); + window.removeEventListener('devicemotion', secondListener); + ++secondEventCount; + resolve(event); + }; + }); + + await helper.setData(motionData); + window.addEventListener('devicemotion', firstListener); + await firstPromise; + await secondPromise; + assert_equals(firstEventCount, 1, "Too many events fired for the first listener"); + assert_equals(secondEventCount, 1, "Too many events fired for the second listener"); +}, 'Tests that adding a new devicemotion event listener from a callback works as expected.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/motion/create-event.https.html b/testing/web-platform/tests/orientation-event/motion/create-event.https.html new file mode 100644 index 0000000000..e8a2c469b1 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/create-event.https.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +'use strict'; + +test(test => { + const event = document.createEvent('DeviceMotionEvent'); + const newEvent = new CustomEvent("devicemotion", { + bubbles: false, cancelable: false, + acceleration: {x:1.5,y:2.5,z:3.5}, + accelerationIncludingGravity: {x:4.5,y:5.5,z:6.5}, + rotationRate: {alpha:7.5,beta:8.5,gamma:9.5}, + interval: 0.5 + }); + + assert_equals(typeof event, 'object'); + assert_equals(Object.getPrototypeOf(event), DeviceMotionEvent.prototype); + + assert_true('type' in event); + assert_true('bubbles' in event); + assert_true('cancelable' in event); + assert_true('acceleration' in event); + assert_true('accelerationIncludingGravity' in event); + assert_true('rotationRate' in event); + assert_true('interval' in event); + + assert_equals(typeof newEvent.type, 'string'); + assert_equals(newEvent.type, "devicemotion"); + assert_equals(typeof newEvent.bubbles, 'boolean'); + assert_false(event.bubbles); + assert_false(newEvent.bubbles); + assert_equals(typeof newEvent.cancelable, 'boolean'); + assert_false(event.cancelable); + assert_false(newEvent.cancelable); + assert_equals(typeof event.acceleration, 'object'); + assert_equals(typeof event.accelerationIncludingGravity, 'object'); + assert_equals(typeof event.rotationRate, 'object'); + assert_equals(typeof event.interval, 'number'); +}, 'Tests that document.createEvent() works with DeviceMotionEvent.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/motion/free-fall-manual.https.html b/testing/web-platform/tests/orientation-event/motion/free-fall-manual.https.html new file mode 100644 index 0000000000..c71f61fa69 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/free-fall-manual.https.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html> + <head> + <title>DeviceMotionEvent: A device in free-fall, with the screen horizontal and upmost</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author' title='Mosquito FP7"> + <link rel="reviewer author" title="Zhiqiang Zhang" href="mailto:zhiqiang.zhang@intel.com"> <!-- 2013-10-14 --> + </head> + <body> + <p>Free fall the device to run the test, with the screen horizontal and upmost.</p> + <div id="log"></div> + <script> + var t = async_test(); + var run = false; + + /* + * A device in free-fall, with the screen horizontal and upmost, + * has an accelerationIncludingGravity of zero and + * the following value for acceleration: + * { + * x: 0, + * y: 0, + * z: -9.81 + * }; + */ + window.addEventListener("devicemotion", function(e) { + if (!run) { + run = true; + t.step(function() { + var gvt = e.accelerationIncludingGravity; + var acc = e.acceleration; + + assert_approx_equals(gvt.x, 0, 1); + assert_approx_equals(gvt.y, 0, 1); + assert_approx_equals(gvt.z, 0, 1); + + assert_approx_equals(acc.x, 0, 1); + assert_approx_equals(acc.y, 0, 1); + assert_approx_equals(acc.z, -9.81, 1.5); + }); + t.done(); + } + }, false); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/orientation-event/motion/multiple-event-listeners.https.html b/testing/web-platform/tests/orientation-event/motion/multiple-event-listeners.https.html new file mode 100644 index 0000000000..f94c9d136e --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/multiple-event-listeners.https.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'devicemotion'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const motionData1 = generateMotionData(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + await helper.setData(motionData1); + await Promise.all([ + waitForEvent(getExpectedMotionEvent(motionData1)), + waitForEvent(getExpectedMotionEvent(motionData1)) + ]); + + const motionData2 = generateMotionData(11, 12, 13, + 14, 15, 16, + 17, 18, 19); + await helper.setData(motionData2); + await waitForEvent(getExpectedMotionEvent(motionData2)); +}, 'Tests using multiple event handlers for the Device Motion API.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/motion/null-values.https.html b/testing/web-platform/tests/orientation-event/motion/null-values.https.html new file mode 100644 index 0000000000..f875afcd64 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/null-values.https.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'devicemotion'); + await helper.grantSensorsPermissions(); + + const motionData1 = generateMotionData(1, 2, 3, + null, null, null, + null, null, null); + + const motionData2 = generateMotionData(null, null, null, + 1, 2, 3, + null, null, null); + + const motionData3 = generateMotionData(null, null, null, + null, null, null, + 1, 2, 3); + + const motionData4 = generateMotionData(null, null, null, + null, null, null, + null, null, null); + + await helper.initializeSensors({disabledSensors: ['accelerometer','gyroscope']}); + await helper.setData(motionData1); + await waitForEvent(getExpectedMotionEvent(motionData1)); + // If test needs to change virtual sensor state from connected to not + // connected or vise versa, reset needs to be called. It removes created + // virtual sensors and creating them with different connection state is then + // possible. + await helper.reset(); + + await helper.initializeSensors({disabledSensors: ['linear-acceleration','gyroscope']}); + await helper.setData(motionData2); + await waitForEvent(getExpectedMotionEvent(motionData2)); + await helper.reset(); + + await helper.initializeSensors({disabledSensors: ['accelerometer','linear-acceleration']}); + await helper.setData(motionData3); + await waitForEvent(getExpectedMotionEvent(motionData3)); + await helper.reset(); + + await helper.initializeSensors({disabledSensors: ['accelerometer','linear-acceleration','gyroscope']}); + await helper.setData(motionData4); + await waitForEvent(getExpectedMotionEvent(motionData4)); +}, 'Tests using null values for some or all of the event properties.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/motion/optional-event-properties.https.html b/testing/web-platform/tests/orientation-event/motion/optional-event-properties.https.html new file mode 100644 index 0000000000..0a73721cb9 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/optional-event-properties.https.html @@ -0,0 +1,257 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +'use strict'; + +function ObjectThrowingException() {}; +ObjectThrowingException.prototype.valueOf = () => { throw new Error('valueOf threw exception'); } +ObjectThrowingException.prototype.__defineGetter__("x", () => { throw new Error('x getter exception'); }); +ObjectThrowingException.prototype.__defineGetter__("alpha", () => { throw new Error('alpha getter exception'); }); +const objectThrowingException = new ObjectThrowingException(); + +test(test => { + event = document.createEvent('DeviceMotionEvent'); + assert_equals(event.type, ""); + assert_equals(event.acceleration, null); + assert_equals(event.accelerationIncludingGravity, null); + assert_equals(event.rotationRate, null); + assert_equals(event.interval, 0); +}, 'Tests creating a DeviceMotionEvent.'); + +test(test => { + event = new DeviceMotionEvent('foo', {acceleration: {x: 0, y: 1, z: 2}, + accelerationIncludingGravity: {x: 3, y: 4, z: 5}, + rotationRate: {alpha: 6, beta: 7, gamma: 8}, + interval: 9}); + assert_equals(event.type, "foo"); + assert_equals(event.acceleration.x, 0); + assert_equals(event.acceleration.y, 1); + assert_equals(event.acceleration.z, 2); + assert_equals(event.accelerationIncludingGravity.x, 3); + assert_equals(event.accelerationIncludingGravity.y, 4); + assert_equals(event.accelerationIncludingGravity.z, 5); + assert_equals(event.rotationRate.alpha, 6); + assert_equals(event.rotationRate.beta, 7); + assert_equals(event.rotationRate.gamma, 8); + assert_equals(event.interval, 9); +}, 'Tests no missing value.'); + +test(test => { + try { + event = new DeviceMotionEvent('', {acceleration: objectThrowingException, + accelerationIncludingGravity: {x: 3, z: 5}, + rotationRate: {gamma: 8, beta: 7}, + interval: 9}); + assert_unreached("Invalid acceleration, must throw an Error exception"); + } catch (e) { + assert_equals(e.name, "Error"); + assert_equals(e.message, "x getter exception"); + } +}, 'Tests invalid acceleration.'); + +test(test => { + try { + event = new DeviceMotionEvent('', {acceleration: {x: 0, y: 1, z: 2}, + accelerationIncludingGravity: objectThrowingException, + rotationRate: {gamma: 8, beta: 7}, + interval: 9}); + assert_unreached("Invalid acelerationIncludingGravity, must throw an Error exception"); + } catch (e) { + assert_equals(e.name, "Error"); + assert_equals(e.message, "x getter exception"); + } +}, 'Tests invalid acelerationIncludingGravity.'); + +test(test => { + try { + event = new DeviceMotionEvent('', {acceleration: {x: 0, y: 1, z: 2}, + accelerationIncludingGravity: {x: 3, z: 5}, + rotationRate: objectThrowingException, + interval: 9}); + assert_unreached("Invalid rotationRate, must throw an Error exception"); + } catch (e) { + assert_equals(e.name, "Error"); + assert_equals(e.message, "alpha getter exception"); + } +}, 'Tests invalid rotationRate.'); + +test(test => { + try { + event = new DeviceMotionEvent('', {acceleration: {x: objectThrowingException, y: 1, z: 2}, + accelerationIncludingGravity: {x: 3, y: 4, z: 5}, + rotationRate: {alpha: 6, beta: 7, gamma: 8}, + interval: 9}); + assert_unreached("Invalid acceleration.x, must throw an Error exception"); + } catch (e) { + assert_equals(e.name, "Error"); + assert_equals(e.message, "valueOf threw exception"); + } +}, 'Tests invalid acceleration.x.'); + +test(test => { + try { + event = new DeviceMotionEvent('', {acceleration: {x: 0, y: 1, z: 2}, + accelerationIncludingGravity: {x: 3, y: objectThrowingException, z: 5}, + rotationRate: {alpha: 6, beta: 7, gamma: 8}, + interval: 9}); + assert_unreached("Invalid accelerationIncludingGravity.y, must throw an Error exception"); + } catch (e) { + assert_equals(e.name, "Error"); + assert_equals(e.message, "valueOf threw exception"); + } +}, 'Tests invalid accelerationIncludingGravity.y.'); + +test(test => { + try { + event = new DeviceMotionEvent('', {acceleration: {x: 0, y: 1, z: 2}, + accelerationIncludingGravity: {x: 3, y: 4, z: 5}, + rotationRate: {alpha: 6, beta: 7, gamma: objectThrowingException}, + interval: 9}); + assert_unreached("Invalid rotationRate.gamma, must throw an Error exception"); + } catch (e) { + assert_equals(e.name, "Error"); + assert_equals(e.message, "valueOf threw exception"); + } +}, 'Tests invalid rotationRate.gamma.'); + +test(test => { + event = new DeviceMotionEvent('', {acceleration: {y: 1, x: 0}, + accelerationIncludingGravity: {x: 3, z: 5}, + rotationRate: {gamma: 8, beta: 7}, + interval: 9}); + assert_equals(event.acceleration.x, 0); + assert_equals(event.acceleration.y, 1); + assert_equals(event.acceleration.z, null); + assert_equals(event.accelerationIncludingGravity.x, 3); + assert_equals(event.accelerationIncludingGravity.y, null); + assert_equals(event.accelerationIncludingGravity.z, 5); + assert_equals(event.rotationRate.alpha, null); + assert_equals(event.rotationRate.beta, 7); + assert_equals(event.rotationRate.gamma, 8); + assert_equals(event.interval, 9); +}, 'Tests missing fields should be null.'); + +test(test => { + event = new DeviceMotionEvent(''); + assert_equals(event.acceleration, null); + assert_equals(event.accelerationIncludingGravity, null); + assert_equals(event.rotationRate, null); + assert_equals(event.interval, 0); +}, 'Tests DeviceMotionEvent default constructor.'); + +test(test => { + event = new DeviceMotionEvent('', {acceleration: [], + accelerationIncludingGravity: [], + rotationRate: [], + interval: []}); + assert_equals(event.acceleration.x, null); + assert_equals(event.acceleration.y, null); + assert_equals(event.acceleration.z, null); + assert_equals(event.accelerationIncludingGravity.x, null); + assert_equals(event.accelerationIncludingGravity.y, null); + assert_equals(event.accelerationIncludingGravity.z, null); + assert_equals(event.rotationRate.alpha, null); + assert_equals(event.rotationRate.beta, null); + assert_equals(event.rotationRate.gamma, null); + assert_equals(event.interval, 0); +}, 'Tests all values are empty array.'); + +test(test => { + event = new DeviceMotionEvent('', {acceleration: [], + accelerationIncludingGravity: undefined, + rotationRate: undefined, + interval: undefined}); + assert_equals(event.acceleration.x, null); + assert_equals(event.acceleration.y, null); + assert_equals(event.acceleration.z, null); + assert_equals(event.accelerationIncludingGravity, null); + assert_equals(event.rotationRate, null); + assert_equals(event.interval, 0); +}, 'Tests some values are empty array and some values are undefined.'); + +test(test => { + event = new DeviceMotionEvent('', {acceleration: null, + accelerationIncludingGravity: null, + rotationRate: null, + interval: null}); + assert_equals(event.acceleration.x, null); + assert_equals(event.acceleration.y, null); + assert_equals(event.acceleration.z, null); + assert_equals(event.accelerationIncludingGravity.x, null); + assert_equals(event.accelerationIncludingGravity.y, null); + assert_equals(event.accelerationIncludingGravity.z, null); + assert_equals(event.rotationRate.alpha, null); + assert_equals(event.rotationRate.beta, null); + assert_equals(event.rotationRate.gamma, null); + assert_equals(event.interval, 0); +}, "Tests all values are null."); + +test(test => { + event = new DeviceMotionEvent('', {acceleration: {x: null, y: null, z: null}, + accelerationIncludingGravity: {x: null, y: null, z: null}, + rotationRate: {alpha: null, beta: null, gamma: null}, + interval: null}); + assert_equals(event.acceleration.x, null); + assert_equals(event.acceleration.y, null); + assert_equals(event.acceleration.z, null); + assert_equals(event.accelerationIncludingGravity.x, null); + assert_equals(event.accelerationIncludingGravity.y, null); + assert_equals(event.accelerationIncludingGravity.z, null); + assert_equals(event.rotationRate.alpha, null); + assert_equals(event.rotationRate.beta, null); + assert_equals(event.rotationRate.gamma, null); + assert_equals(event.interval, 0); +}, 'Tests all fields are null.'); + +test(test => { + event = new DeviceMotionEvent('', {acceleration: {x: null, y: null, z: 1}, + accelerationIncludingGravity: {x: null, y: null, z: 2}, + rotationRate: {alpha: null, beta: null, gamma: 3}, + interval: null}); + assert_equals(event.acceleration.x, null); + assert_equals(event.acceleration.y, null); + assert_equals(event.acceleration.z, 1); + assert_equals(event.accelerationIncludingGravity.x, null); + assert_equals(event.accelerationIncludingGravity.y, null); + assert_equals(event.accelerationIncludingGravity.z, 2); + assert_equals(event.rotationRate.alpha, null); + assert_equals(event.rotationRate.beta, null); + assert_equals(event.rotationRate.gamma, 3); + assert_equals(event.interval, 0); +}, 'Tests some fields are null.'); + +test(test => { + event = new DeviceMotionEvent('', {acceleration: {x: undefined, y: undefined, z: undefined}, + accelerationIncludingGravity: {x: undefined, y: undefined, z: undefined}, + rotationRate: {alpha: undefined, beta: undefined, gamma: undefined}, + interval: undefined}); + assert_equals(event.acceleration.x, null); + assert_equals(event.acceleration.y, null); + assert_equals(event.acceleration.z, null); + assert_equals(event.accelerationIncludingGravity.x, null); + assert_equals(event.accelerationIncludingGravity.y, null); + assert_equals(event.accelerationIncludingGravity.z, null); + assert_equals(event.rotationRate.alpha, null); + assert_equals(event.rotationRate.beta, null); + assert_equals(event.rotationRate.gamma, null); + assert_equals(event.interval, 0); +}, 'Tests all fields are undefined.'); + +test(test => { + event = new DeviceMotionEvent('', {acceleration: {x: undefined, y: undefined, z: 1}, + accelerationIncludingGravity: {x: undefined, y: undefined, z: 2}, + rotationRate: {alpha: undefined, beta: undefined, gamma: 3}, + interval: undefined}); + assert_equals(event.acceleration.x, null); + assert_equals(event.acceleration.y, null); + assert_equals(event.acceleration.z, 1); + assert_equals(event.accelerationIncludingGravity.x, null); + assert_equals(event.accelerationIncludingGravity.y, null); + assert_equals(event.accelerationIncludingGravity.z, 2); + assert_equals(event.rotationRate.alpha, null); + assert_equals(event.rotationRate.beta, null); + assert_equals(event.rotationRate.gamma, 3); + assert_equals(event.interval, 0); +}, 'Tests some fields are undefined.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/motion/page-visibility.https.html b/testing/web-platform/tests/orientation-event/motion/page-visibility.https.html new file mode 100644 index 0000000000..2925af9331 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/page-visibility.https.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'devicemotion'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const motionData = generateMotionData(0, 0, 0, + 0, 0, 0, + 0, 0, 0); + + await helper.setData(motionData); + const event = getExpectedMotionEvent(motionData); + await waitForEvent(event); + + const {minimize, restore} = window_state_context(t); + await minimize(); + assert_true(document.hidden); + + let hiddenEventPromise = new Promise((resolve, reject) => { + window.addEventListener( + 'devicemotion', + event => { + if (document.hidden) { + reject(); + } else { + resolve(); + } + }, + { once: true }); + }); + + // devicemotion events fire every 16ms when active, so we sleep for a while + // here to make sure we're not actually getting any events. + await new Promise(resolve => { t.step_timeout(resolve, 100); }); + await restore(); + assert_false(document.hidden); + return Promise.all([hiddenEventPromise, waitForEvent(event)]); +}, 'Tests to check that devicemotion events are not fired when the page is not visible.'); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/orientation-event/motion/requestPermission.https.window.js b/testing/web-platform/tests/orientation-event/motion/requestPermission.https.window.js new file mode 100644 index 0000000000..2c96d26d10 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/requestPermission.https.window.js @@ -0,0 +1,48 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// The Device Orientation spec does not fully integrate with the Permissions +// spec and does not list the permissions that are expected for +// requestPermission() to work. The list below was based on the permission +// tokens corresponding to the sensors used to implement support for motion +// events. They also match the feature policy tokens required by both Blink and +// WebKit. +const permissionDescriptorNames = ['accelerometer', 'gyroscope']; + +promise_test(async (t) => { + await Promise.all(permissionDescriptorNames.map( + name => test_driver.set_permission({name}, 'granted'))); + + const permission = await DeviceMotionEvent.requestPermission(); + assert_equals(permission, 'granted'); +}, 'requestPermission() returns "granted" for granted permissions without user activation'); + +promise_test(async (t) => { + await Promise.all(permissionDescriptorNames.map( + name => test_driver.set_permission({name}, 'granted'))); + + return test_driver.bless('enable user activation', async () => { + const permission = await DeviceMotionEvent.requestPermission(); + assert_equals(permission, 'granted'); + }); +}, 'requestPermission() returns "granted" for granted permissions with user activation'); + +promise_test(async (t) => { + await Promise.all(permissionDescriptorNames.map( + name => test_driver.set_permission({name}, 'denied'))); + + const permission = await DeviceMotionEvent.requestPermission(); + assert_equals(permission, 'denied'); +}, 'requestPermission() returns "denied" for denied permissions without user activation'); + +promise_test(async (t) => { + await Promise.all(permissionDescriptorNames.map( + name => test_driver.set_permission({name}, 'denied'))); + + return test_driver.bless('enable user activation', async () => { + const permission = await DeviceMotionEvent.requestPermission(); + assert_equals(permission, 'denied'); + }); +}, 'requestPermission() returns "denied" for denied permissions with user activation'); diff --git a/testing/web-platform/tests/orientation-event/motion/screen-upmost-manual.https.html b/testing/web-platform/tests/orientation-event/motion/screen-upmost-manual.https.html new file mode 100644 index 0000000000..560c3e3a1f --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/screen-upmost-manual.https.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<html> + <head> + <title>DeviceMotionEvent: A device lying flat on a horizontal surface with the screen upmost</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author' title='Mosquito FP7"> + <link rel="reviewer author" title="Zhiqiang Zhang" href="mailto:zhiqiang.zhang@intel.com"> <!-- 2013-10-14 --> + </head> + <body> + <p>Put the device on a horizontal surface with the screen upmost.</p> + <div id="log"></div> + <script> + var t = async_test(); + var run = false; + + /* + * A device lying flat on a horizontal surface with the screen upmost + * has an acceleration of zero and the following value for + * accelerationIncludingGravity: + * { + * x: 0, + * y: 0, + * z: 9.81 + * }; + */ + window.addEventListener("devicemotion", function(e) { + if (!run) { + run = true; + t.step(function() { + var gvt = e.accelerationIncludingGravity; + var acc = e.acceleration; + var rot = e.rotationRate; + + assert_approx_equals(gvt.x, 0, 1); + assert_approx_equals(gvt.y, 0, 1); + assert_approx_equals(gvt.z, 9.81, 1.5); + + assert_approx_equals(acc.x, 0, 1); + assert_approx_equals(acc.y, 0, 1); + assert_approx_equals(acc.z, 0, 1); + + assert_equals(rot, null); + }); + t.done(); + } + }, false); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/orientation-event/motion/screen-upright-manual.https.html b/testing/web-platform/tests/orientation-event/motion/screen-upright-manual.https.html new file mode 100644 index 0000000000..8a1b6d27da --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/screen-upright-manual.https.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html> + <head> + <title>DeviceMotionEvent: A device with the screen upright</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author' title='Mosquito FP7"> + <link rel="reviewer author" title="Zhiqiang Zhang" href="mailto:zhiqiang.zhang@intel.com"> <!-- 2013-10-14 --> + </head> + <body> + <p>Put the device with the screen upright.</p> + <div id="log"></div> + <script> + var t = async_test(); + var run = false; + + /* + * A device with the screen upright has an acceleration of zero + * and the following value for accelerationIncludingGravity: + * { + * x: 0, + * y: -9.81, + * z: 0 + * }; + */ + window.addEventListener("devicemotion", function(e) { + if (!run) { + run = true; + t.step(function() { + var gvt = e.accelerationIncludingGravity; + var acc = e.acceleration; + var rot = e.rotationRate; + + assert_approx_equals(gvt.x, 0, 1); + assert_approx_equals(gvt.y, -9.81, 1.5); + assert_approx_equals(gvt.z, 0, 1); + + assert_approx_equals(acc.x, 0, 1); + assert_approx_equals(acc.y, 0, 1); + assert_approx_equals(acc.z, 0, 1); + + assert_equals(rot, null); + }); + t.done(); + } + }, false); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/orientation-event/motion/t025-manual.https.html b/testing/web-platform/tests/orientation-event/motion/t025-manual.https.html new file mode 100644 index 0000000000..9489855fcd --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/t025-manual.https.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> + <head> + <title>Implementations that are unable to provide acceleration data without the effect of gravity may instead supply the acceleration including the effect of gravity</title> + <meta name=viewport content="width=device-width, maximum-scale=1.0"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author" title="Mosquito FP7"> + <link rel="reviewer author" title="Zhiqiang Zhang" href="mailto:zhiqiang.zhang@intel.com"> <!-- 2013-10-14 --> + </head> + <body> + <p>Move the device to run the test.</p> + <div id="log"></div> + <script> + var t1 = async_test("Implementation is unable to provide 'acceleration' property"); + var t2 = async_test("Implementation is able to provide 'acceleration IncludingGravity' property"); + var run = false; + window.ondevicemotion = function(e) { + if (!run) { + run = true; + t1.step(function() { + assert_equals(e.acceleration, null); + }); + t1.done(); + t2.step(function() { + var eaccgvt = e.accelerationIncludingGravity; + assert_equals(typeof eaccgvt, "object"); + assert_not_equals(eaccgvt.x, 0); + assert_not_equals(eaccgvt.y, 0); + assert_not_equals(eaccgvt.z, 0); + }); + t2.done(); + } + }; + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/orientation-event/motion/t028-manual.https.html b/testing/web-platform/tests/orientation-event/motion/t028-manual.https.html new file mode 100644 index 0000000000..669c4e47e0 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/motion/t028-manual.https.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html> + <head> + <title>The interval property must be expressed in milliseconds. It must be a constant, to simplify filtering of the data by the Web application</title> + <meta name=viewport content="width=device-width, maximum-scale=1.0"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author" title="Mosquito FP7"> + <link rel="reviewer author" title="Zhiqiang Zhang" href="mailto:zhiqiang.zhang@intel.com"> <!-- 2013-10-14 --> + </head> + <body> + <p>Move the device to run the test.</p> + <div id="log"></div> + <script> + var t = async_test("The interval property must be different to zero and must be a constant"); + var inter1 = 0; + var inter2 = 0; + var run = false; + window.addEventListener("devicemotion", function(e) { + if (!run) { + run = true; + t.step(function() { + if (inter1 == 0) { + inter2 = e.interval; + } + inter1 = e.interval; + assert_not_equals(inter1, 0); + assert_not_equals(inter1, inter2); + }); + t.done(); + } + }, false); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/orientation-event/orientation/absolute-fallback.https.html b/testing/web-platform/tests/orientation-event/orientation/absolute-fallback.https.html new file mode 100644 index 0000000000..27a430728e --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/absolute-fallback.https.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientation'); + await helper.grantSensorsPermissions(); + + // Make the relative orientation sensor unavailable and set mock data for + // the absolute one. + await helper.initializeSensors({enabledSensors: ['absolute-orientation'], disabledSensors: ['relative-orientation']}); + const orientationData = generateOrientationData(1.1, 2.2, 3.3, true); + + // Check sensor values when fallback is activated. + await helper.setData(orientationData); + await waitForEvent(getExpectedOrientationEvent(orientationData)); +}, 'Tests that deviceorientation falls back to using absolute orientation data if relative is unavailable.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/orientation/add-listener-from-callback.https.html b/testing/web-platform/tests/orientation-event/orientation/add-listener-from-callback.https.html new file mode 100644 index 0000000000..7f664ab400 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/add-listener-from-callback.https.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientation'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const orientationData1 = generateOrientationData(1.1, 2.2, 3.3, false); + const orientationData2 = generateOrientationData(11.1, 22.2, 33.3, false); + + let firstListener = null; + let secondListener = null; + let firstEventCount = 0; + let firstPromise = new Promise(resolve => { + firstListener = async (event) => { + assert_true(event instanceof DeviceOrientationEvent, 'event is DeviceOrientationEvent'); + assert_equals(event.type, 'deviceorientation', 'event.type is devicemotion'); + assert_true(event.target instanceof Window, 'event is fired on the window object'); + assertEventEquals(event, getExpectedOrientationEvent(orientationData1)); + window.removeEventListener('deviceorientation', firstListener); + // Some implementations (e.g. Chromium) work without the call below + // because they disconnect from the virtual sensor in the + // removeEventListener() call above before connecting again, and in this + // case the same orientation data is still considered a significant + // change. This is an implementation detail though, so we explicitly pass + // different data here. + await helper.setData(orientationData2); + if (++firstEventCount == 1) { + window.addEventListener('deviceorientation', secondListener); + } + resolve(event); + }; + }); + + let secondEventCount = 0; + let secondPromise = new Promise(resolve => { + secondListener = (event) => { + assertEventEquals(event, getExpectedOrientationEvent(orientationData2)); + window.removeEventListener('deviceorientation', secondListener); + ++secondEventCount; + resolve(event); + }; + }); + + await helper.setData(orientationData1); + window.addEventListener('deviceorientation', firstListener); + await firstPromise; + await secondPromise; + assert_equals(firstEventCount, 1, "Too many events fired for the first listener"); + assert_equals(secondEventCount, 1, "Too many events fired for the second listener"); +}, 'Tests that adding a new deviceorientation event listener from a callback works as expected.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/orientation/basic-operation-absolute.https.html b/testing/web-platform/tests/orientation-event/orientation/basic-operation-absolute.https.html new file mode 100644 index 0000000000..bebd69b952 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/basic-operation-absolute.https.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientationabsolute'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const orientationData = generateOrientationData(1.1, 2.2, 3.3, true); + await helper.setData(orientationData); + await waitForEvent(getExpectedAbsoluteOrientationEvent(orientationData)); +}, 'Tests basic operation of deviceorientationabsolute event using mock data.'); + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientationabsolute'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors({disabledSensors: ['absolute-orientation']}); + + const orientationData = generateOrientationData(null, null, null, true); + const watcher = new EventWatcher(t, window, ['deviceorientationabsolute']); + + const event = await watcher.wait_for('deviceorientationabsolute'); + assert_equals(event.type, 'deviceorientationabsolute', 'type is set to \"deviceorientationabsolute\"'); + assert_true(event instanceof DeviceOrientationEvent, 'event is DeviceOrientationEvent'); + + assertEventEquals(event, getExpectedAbsoluteOrientationEvent(orientationData)); +}, 'If UA can never provide absolute information, the event should be fired as a null event.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/orientation/basic-operation.https.html b/testing/web-platform/tests/orientation-event/orientation/basic-operation.https.html new file mode 100644 index 0000000000..c4d26e3744 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/basic-operation.https.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientation'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const orientationData = generateOrientationData(1.1, 2.2, 3.3, false); + await helper.setData(orientationData); + await waitForEvent(getExpectedOrientationEvent(orientationData)); +}, 'Tests basic operation of deviceorientation event using mock data.'); + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientation'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors({disabledSensors: ['relative-orientation']}); + + const orientationData = generateOrientationData(null, null, null, false); + const watcher = new EventWatcher(t, window, ['deviceorientation']); + + const event = await watcher.wait_for('deviceorientation'); + assert_equals(event.type, 'deviceorientation', 'type is set to \"deviceorientation\"'); + assert_true(event instanceof DeviceOrientationEvent, 'event is DeviceOrientationEvent'); + + assertEventEquals(event, getExpectedOrientationEvent(orientationData)); +}, 'If UA can never provide orientation information, the event should be fired as a null event.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/orientation/create-event.https.html b/testing/web-platform/tests/orientation-event/orientation/create-event.https.html new file mode 100644 index 0000000000..a21f95655e --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/create-event.https.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +'use strict'; + +test(test => { + const event = document.createEvent('DeviceOrientationEvent'); + const newEvent = new CustomEvent("deviceorientation", { + bubbles: false, cancelable: false, + alpha: 1.0, + beta: 2.0, + gama: 3.0, + absolute: false + }); + + assert_equals(typeof event, 'object'); + assert_equals(Object.getPrototypeOf(event), DeviceOrientationEvent.prototype); + + assert_true('type' in event); + assert_true('bubbles' in event); + assert_true('cancelable' in event); + assert_true('alpha' in event); + assert_true('beta' in event); + assert_true('gamma' in event); + assert_true('absolute' in event); + + assert_equals(typeof event.type, 'string'); + assert_equals(typeof event.bubbles, 'boolean'); + assert_equals(typeof event.cancelable, 'boolean'); + assert_equals(typeof event.alpha, 'object'); + assert_equals(typeof event.beta, 'object'); + assert_equals(typeof event.gamma, 'object'); + assert_equals(typeof event.absolute, 'boolean'); + + assert_equals(newEvent.type, "deviceorientation"); + assert_false(newEvent.bubbles); + assert_false(newEvent.cancelable); +}, 'Tests that document.createEvent() works with DeviceOrientationEvent.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/orientation/horizontal-surface-manual.https.html b/testing/web-platform/tests/orientation-event/orientation/horizontal-surface-manual.https.html new file mode 100644 index 0000000000..0b7302e704 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/horizontal-surface-manual.https.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> + <head> + <title>DeviceOrientationEvent: A device lying flat on a horizontal surface</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author' title='Mosquito FP7"> + <link rel="reviewer author" title="Zhiqiang Zhang" href="mailto:zhiqiang.zhang@intel.com"> <!-- 2013-10-12 --> + </head> + <body> + <p>Put the device on a horizontal surface to run the test.</p> + <div id="log"></div> + <script> + var gamma, beta; + var run = false; + window.addEventListener("deviceorientation", function(e) { + if (!run) { + run = true; + gamma = e.gamma; // Gamma : angle par rapport a x + beta = e.beta; // Beta : angle par rapport a y + } + }, false); + + test(function() { + assert_approx_equals(gamma, 0, 2); + }, "X angle"); + + test(function() { + assert_approx_equals(beta, 0, 2); + }, "Y angle"); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/orientation-event/orientation/multiple-event-listeners.https.html b/testing/web-platform/tests/orientation-event/orientation/multiple-event-listeners.https.html new file mode 100644 index 0000000000..a32f9f3a1f --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/multiple-event-listeners.https.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientation'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const orientationData1 = generateOrientationData(1, 2, 3, false); + await helper.setData(orientationData1); + + await Promise.all([ + waitForEvent(getExpectedOrientationEvent(orientationData1)), + waitForEvent(getExpectedOrientationEvent(orientationData1)) + ]); + + const orientationData2 = generateOrientationData(11, 12, 13, false); + await helper.setData(orientationData2); + await waitForEvent(getExpectedOrientationEvent(orientationData2)); +}, 'Tests using multiple event handlers for the Device Orientation API.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/orientation/no-synchronous-events.https.html b/testing/web-platform/tests/orientation-event/orientation/no-synchronous-events.https.html new file mode 100644 index 0000000000..97dccfbc31 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/no-synchronous-events.https.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientation'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const orientationData = generateOrientationData(1.1, 2.2, 3.3, false); + await helper.setData(orientationData); + + return new Promise((resolve, reject) => { + let result = reject; + window.addEventListener('deviceorientation', event => result()); + result = resolve; + }); +}, 'Tests that events are never fired synchronously from a call to window.addEventListener().'); +</script> diff --git a/testing/web-platform/tests/orientation-event/orientation/null-values.https.html b/testing/web-platform/tests/orientation-event/orientation/null-values.https.html new file mode 100644 index 0000000000..c54d73da50 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/null-values.https.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientation'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors({disabledSensors: ['absolute-orientation', 'relative-orientation']}); + + const orientationData1 = generateOrientationData(1.1, 2.2, 3.3, false); + // Currently it is not possible to set individual values to null because the + // parsing algorithms used by + // https://w3c.github.io/sensors/#update-virtual-sensor-reading-command + // always expect numbers. + const orientationData2 = generateOrientationData(null, null, null, false); + + // An example how setting relative-orientation sensor as disabled will output + // null values. Even if we try to set non null values to sensor. + await helper.setData(orientationData1); + await waitForEvent(getExpectedOrientationEvent(orientationData2)); +}, 'Tests using null values for some of the event properties.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/orientation/optional-event-properties.https.html b/testing/web-platform/tests/orientation-event/orientation/optional-event-properties.https.html new file mode 100644 index 0000000000..150ce5ca1d --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/optional-event-properties.https.html @@ -0,0 +1,73 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +'use strict'; + +test(test => { + event = document.createEvent('DeviceOrientationEvent'); + assert_equals(event.type, ""); + assert_equals(event.alpha, null); + assert_equals(event.beta, null); + assert_equals(event.gamma, null); + assert_false(event.absolute); +}, 'Tests creating a DeviceOrientationEvent.'); + +test(test => { + event = new DeviceOrientationEvent('foo', {alpha: 0, beta: 1, gamma: 2, absolute: false}); + assert_equals(event.type, "foo"); + assert_equals(event.alpha, 0); + assert_equals(event.beta, 1); + assert_equals(event.gamma, 2); + assert_false(event.absolute); +}, 'Tests no missing value (absolute field is false).'); + +test(test => { + event = new DeviceOrientationEvent('', {alpha: 0, beta: 1, gamma: 2, absolute: true}); + assert_equals(event.alpha, 0); + assert_equals(event.beta, 1); + assert_equals(event.gamma, 2); + assert_true(event.absolute); +}, 'Tests no missing value (absolute field is true).'); + +test(test => { + event = new DeviceOrientationEvent(''); + assert_equals(event.alpha, null); + assert_equals(event.beta, null); + assert_equals(event.gamma, null); + assert_false(event.absolute); +}, 'Tests DeviceOrientationEvent default constructor.'); + +test(test => { + event = new DeviceOrientationEvent('', {alpha: [], beta: [], gamma: [], absolute: []}); + assert_equals(event.alpha, 0); + assert_equals(event.beta, 0); + assert_equals(event.gamma, 0); + assert_true(event.absolute); +}, 'Tests all values are empty array.'); + +test(test => { + event = new DeviceOrientationEvent('', {alpha: undefined, beta: undefined, gamma: undefined, absolute: undefined}); + assert_equals(event.alpha, null); + assert_equals(event.beta, null); + assert_equals(event.gamma, null); + assert_false(event.absolute); +}, 'Tests all values are undefined.'); + +test(test => { + event = new DeviceOrientationEvent('', {alpha: '', beta: '', gamma: '', absolute: ''}); + assert_equals(event.alpha, 0); + assert_equals(event.beta, 0); + assert_equals(event.gamma, 0); + assert_false(event.absolute); +}, 'Tests all values are empty string.'); + + +test(test => { + event = new DeviceOrientationEvent('', {alpha: null, beta: null, gamma: null, absolute: null}); + assert_equals(event.alpha, null); + assert_equals(event.beta, null); + assert_equals(event.gamma, null); + assert_false(event.absolute); +}, 'Tests all values are null.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/orientation/page-visibility.https.html b/testing/web-platform/tests/orientation-event/orientation/page-visibility.https.html new file mode 100644 index 0000000000..bcb4beeb8e --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/page-visibility.https.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientation'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const orientationData = generateOrientationData(1, 2, 3, false); + + await helper.setData(orientationData); + const event = getExpectedOrientationEvent(orientationData); + await waitForEvent(event); + + const {minimize, restore} = window_state_context(t); + await minimize(); + assert_true(document.hidden); + + let hiddenEventPromise = new Promise((resolve, reject) => { + window.addEventListener( + 'deviceorientation', + event => { + if (document.hidden) { + reject(); + } else { + resolve(); + } + }, + { once: true }); + }); + + // Sleep for a while to make sure no deviceorientation events are fired + // while the page is hidden. + await new Promise(resolve => { t.step_timeout(resolve, 100); }); + await restore(); + assert_false(document.hidden); + return Promise.all([hiddenEventPromise, waitForEvent(event)]); +}, 'Tests to check that deviceorientation events are not fired when the page is not visible.'); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/orientation-event/orientation/requestPermission.https.window.js b/testing/web-platform/tests/orientation-event/orientation/requestPermission.https.window.js new file mode 100644 index 0000000000..4a39a238d0 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/requestPermission.https.window.js @@ -0,0 +1,48 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// The Device Orientation spec does not fully integrate with the Permissions +// spec and does not list the permissions that are expected for +// requestPermission() to work. The list below was based on the permissions +// listed in https://w3c.github.io/orientation-sensor/#model for the low-level +// sensors that power absolute and relative orientation sensors. +const permissionDescriptorNames = + ['accelerometer', 'gyroscope', 'magnetometer']; + +promise_test(async (t) => { + await Promise.all(permissionDescriptorNames.map( + name => test_driver.set_permission({name}, 'granted'))); + + const permission = await DeviceOrientationEvent.requestPermission(); + assert_equals(permission, 'granted'); +}, 'requestPermission() returns "granted" for granted permissions without user activation'); + +promise_test(async (t) => { + await Promise.all(permissionDescriptorNames.map( + name => test_driver.set_permission({name}, 'granted'))); + + return test_driver.bless('enable user activation', async () => { + const permission = await DeviceOrientationEvent.requestPermission(); + assert_equals(permission, 'granted'); + }); +}, 'requestPermission() returns "granted" for granted permissions with user activation'); + +promise_test(async (t) => { + await Promise.all(permissionDescriptorNames.map( + name => test_driver.set_permission({name}, 'denied'))); + + const permission = await DeviceOrientationEvent.requestPermission(); + assert_equals(permission, 'denied'); +}, 'requestPermission() returns "denied" for denied permissions without user activation'); + +promise_test(async (t) => { + await Promise.all(permissionDescriptorNames.map( + name => test_driver.set_permission({name}, 'denied'))); + + return test_driver.bless('enable user activation', async () => { + const permission = await DeviceOrientationEvent.requestPermission(); + assert_equals(permission, 'denied'); + }); +}, 'requestPermission() returns "denied" for denied permissions with user activation'); diff --git a/testing/web-platform/tests/orientation-event/orientation/t006-manual.https.html b/testing/web-platform/tests/orientation-event/orientation/t006-manual.https.html new file mode 100644 index 0000000000..e41f4634e8 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/t006-manual.https.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> + <head> + <title>Rotate the device frame around its z axis</title> + <meta name=viewport content="width=device-width, maximum-scale=1.0"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author" title="Mosquito FP7"> + <link rel="reviewer author" title="Zhiqiang Zhang" href="mailto:zhiqiang.zhang@intel.com"> <!-- 2013-10-12 --> + </head> + <body> + <p>Rotate the device frame around its z axis to run the test.</p> + <div id="log"></div> + <script> + var t1 = async_test("Alpha is in [0, 360)"); + var run = false; + window.addEventListener("deviceorientation", function(e) { + if (!run && e.alpha !== null) { + run = true; + t1.step(function() { + assert_greater_than_equal(e.alpha, 0); + assert_less_than(e.alpha, 360); + }); + t1.done(); + } + }, false); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/orientation-event/orientation/t009-manual.https.html b/testing/web-platform/tests/orientation-event/orientation/t009-manual.https.html new file mode 100644 index 0000000000..d00f7e71b0 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/t009-manual.https.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> + <head> + <title>Rotate the device frame around its x axis</title> + <meta name=viewport content="width=device-width, maximum-scale=1.0"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author" title="Mosquito FP7"> + <link rel="reviewer author" title="Zhiqiang Zhang" href="mailto:zhiqiang.zhang@intel.com"> <!-- 2013-10-12 --> + </head> + <body> + <p>Rotate the device frame around its x axis to run the test.</p> + <div id="log"></div> + <script> + var t1 = async_test("Beta is in [-180, 180)"); + var run = false; + window.addEventListener("deviceorientation", function(e) { + if (!run && e.beta !== null) { + run = true; + t1.step(function() { + assert_greater_than_equal(e.beta, -180); + assert_less_than(e.beta, 180); + }); + t1.done(); + } + }, false); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/orientation-event/orientation/t010-manual.https.html b/testing/web-platform/tests/orientation-event/orientation/t010-manual.https.html new file mode 100644 index 0000000000..9a6e00e1f7 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/t010-manual.https.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> + <head> + <title>Rotate the device frame around its y axis</title> + <meta name=viewport content="width=device-width, maximum-scale=1.0"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author" title="Mosquito FP7"> + <link rel="reviewer author" title="Zhiqiang Zhang" href="mailto:zhiqiang.zhang@intel.com"> <!-- 2013-10-12 --> + </head> + <body> + <p>Rotate the device frame around its y axis to run the test.</p> + <div id="log"></div> + <script> + var t1 = async_test("Gamma is in [-90, 90)"); + var run = false; + window.addEventListener("deviceorientation", function(e) { + if (!run && e.gamma !== null) { + run = true; + t1.step(function() { + assert_greater_than_equal(e.gamma, -90); + assert_less_than(e.gamma, 90); + }); + t1.done(); + } + }, false); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/orientation-event/orientation/t012-manual.https.html b/testing/web-platform/tests/orientation-event/orientation/t012-manual.https.html new file mode 100644 index 0000000000..e5ac1c98b4 --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/t012-manual.https.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> + <head> + <title>Implementations that are unable to provide all three angles must set the values of the unknown angles to null</title> + <meta name=viewport content="width=device-width, maximum-scale=1.0"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author" title="Mosquito FP7"> + <link rel="reviewer author" title="Zhiqiang Zhang" href="mailto:zhiqiang.zhang@intel.com"> <!-- 2013-10-12 --> + </head> + <body> + <p>Precondition: implementation is unable to provide all three angles</p> + <p>Rotate the device to run the test.</p> + <div id="log"></div> + <script> + var t1 = async_test("Alpha, Beta and Gamma are null. absolute is false."); + var run = false; + window.addEventListener("deviceorientation", function(e) { + if (!run) { + run = true; + t1.step(function() { + assert_equals(e.alpha, null, "alpha is set to null"); + assert_equals(e.beta, null, "beta is set to null"); + assert_equals(e.gamma, null, "gamma is set to null"); + assert_false(e.absolute, "absolute is set to false"); + }); + t1.done(); + } + }, false); + + test(function() { + var evt = new DeviceOrientationEvent("foo"); + assert_equals(evt.alpha, null, "alpha is set to null"); + assert_equals(evt.beta, null, "beta is set to null"); + assert_equals(evt.gamma, null, "gamma is set to null"); + assert_false(evt.absolute, "absolute is set to false"); + }, "User created event is initialized properly"); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/orientation-event/orientation/updates.https.html b/testing/web-platform/tests/orientation-event/orientation/updates.https.html new file mode 100644 index 0000000000..fe1811535b --- /dev/null +++ b/testing/web-platform/tests/orientation-event/orientation/updates.https.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="../resources/orientation-event-helpers.js"></script> +<script> +'use strict'; + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientation'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const orientationData1 = generateOrientationData(1.1, 2.2, 3.3, false); + await helper.setData(orientationData1); + await waitForEvent(getExpectedOrientationEvent(orientationData1)); + + const orientationData2 = generateOrientationData(11.1, 22.2, 33.3, false); + await helper.setData(orientationData2); + await waitForEvent(getExpectedOrientationEvent(orientationData2)); +}, 'Tests that updates to the relative orientation causes new events to fire.'); + +promise_test(async (t) => { + const helper = new SensorTestHelper(t, 'deviceorientationabsolute'); + await helper.grantSensorsPermissions(); + await helper.initializeSensors(); + + const orientationData1 = generateOrientationData(1.1, 2.2, 3.3, true); + await helper.setData(orientationData1); + await waitForEvent(getExpectedAbsoluteOrientationEvent(orientationData1)); + + const orientationData2 = generateOrientationData(11.1, 22.2, 33.3, true); + await helper.setData(orientationData2); + await waitForEvent(getExpectedAbsoluteOrientationEvent(orientationData2)); +}, 'Tests that updates to the absolute orientation causes new events to fire.'); +</script> diff --git a/testing/web-platform/tests/orientation-event/resources/orientation-event-helpers.js b/testing/web-platform/tests/orientation-event/resources/orientation-event-helpers.js new file mode 100644 index 0000000000..01e91c62ae --- /dev/null +++ b/testing/web-platform/tests/orientation-event/resources/orientation-event-helpers.js @@ -0,0 +1,274 @@ +'use strict'; + +// @class SensorTestHelper +// +// SensorTestHelper is a helper utilities for orientation event tests. +// +// Usage example with device orientation: +// const helper = new SensorTestHelper(t, 'deviceorientation'); +// await helper.grantSensorsPermissions(); +// await helper.initializeSensors(); +// const generatedData = generateOrientationData(1, 2, 3, false); +// await helper.setData(generatedData); +// await waitForEvent(getExpectedOrientationEvent(generatedData)); +class SensorTestHelper { + #eventName; + #sensorsEnabledByDefault; + #enabledSensors; + #disabledSensors; + #testObject; + + // @param {object} t - A testharness.js subtest instance. + // @param {string} eventName - A name of event. Accepted values are + // devicemotion, deviceorientation or + // deviceorientationabsolute. + constructor(t, eventName) { + this.#eventName = eventName; + this.#testObject = t; + this.#testObject.add_cleanup(() => this.reset()); + + switch (this.#eventName) { + case 'devicemotion': + this.#sensorsEnabledByDefault = + new Set(['accelerometer', 'gyroscope', 'linear-acceleration']); + break; + case 'deviceorientation': + this.#sensorsEnabledByDefault = new Set(['relative-orientation']); + break; + case 'deviceorientationabsolute': + this.#sensorsEnabledByDefault = new Set(['absolute-orientation']); + break; + default: + throw new Error(`Invalid event name ${this.#eventName}`); + } + } + + // Creates virtual sensors that will be used in tests. + // + // This function must be called before event listeners are added or calls + // to setData() or waitForEvent() are made. + // + // The |options| parameter is an object that accepts the following entries: + // - enabledSensors: A list of virtual sensor names that will be created + // instead of the default ones for a given event type. + // - disabledSensors: A list of virtual sensor names that will be created + // in a disabled state, so that creating a sensor of + // a given type is guaranteed to fail. + // An Error is thrown if the same name is passed to both options. + // + // A default list of virtual sensors based on the |eventName| parameter passed + // to the constructor is used if |options| is not specified. + // + // Usage examples + // Use default sensors for the given event type: + // await helper.initializeSensors() + // Enable specific sensors: + // await helper.initializeSensors({ + // enabledSensors: ['accelerometer', 'gyroscope'] + // }) + // Disable some sensors, make some report as not available: + // await helper.initializeSensors({ + // disabledSensors: ['gyroscope'] + // }) + // Enable some sensors, make some report as not available: + // await helper.initializeSensors({ + // enabledSensors: ['accelerometer'], + // disabledSensors: ['gyroscope'] + // }) + async initializeSensors(options = {}) { + this.#disabledSensors = new Set(options.disabledSensors || []); + // Check that a sensor name is not in both |options.enabledSensors| and + // |options.disabledSensors|. + for (const sensor of (options.enabledSensors || [])) { + if (this.#disabledSensors.has(sensor)) { + throw new Error(`${sensor} can be defined only as enabledSensors or disabledSensors`); + } + } + + this.#enabledSensors = new Set(options.enabledSensors || this.#sensorsEnabledByDefault); + // Remove sensors from enabledSensors that are in disabledSensors + for (const sensor of this.#disabledSensors) { + this.#enabledSensors.delete(sensor); + } + + const createVirtualSensorPromises = []; + for (const sensor of this.#enabledSensors) { + createVirtualSensorPromises.push( + test_driver.create_virtual_sensor(sensor)); + } + for (const sensor of this.#disabledSensors) { + createVirtualSensorPromises.push( + test_driver.create_virtual_sensor(sensor, {connected: false})); + } + await Promise.all(createVirtualSensorPromises); + } + + // Updates virtual sensor with given data. + // @param {object} data - Generated data by generateMotionData or + // generateOrientationData which is passed to + // test_driver.update_virtual_sensor(). + async setData(data) { + // WebDriver expects numbers for all values in the readings it receives. We + // convert null to zero here, but any other numeric value would work, as it + // is the presence of one or more sensors in initializeSensors()' + // options.disabledSensors that cause null to be reported in one or more + // event attributes. + const nullToZero = x => (x === null ? 0 : x); + if (this.#eventName === 'devicemotion') { + const degToRad = Math.PI / 180; + await Promise.all([ + test_driver.update_virtual_sensor('accelerometer', { + 'x': nullToZero(data.accelerationIncludingGravityX), + 'y': nullToZero(data.accelerationIncludingGravityY), + 'z': nullToZero(data.accelerationIncludingGravityZ), + }), + test_driver.update_virtual_sensor('linear-acceleration', { + 'x': nullToZero(data.accelerationX), + 'y': nullToZero(data.accelerationY), + 'z': nullToZero(data.accelerationZ), + }), + test_driver.update_virtual_sensor('gyroscope', { + 'x': nullToZero(data.rotationRateAlpha) * degToRad, + 'y': nullToZero(data.rotationRateBeta) * degToRad, + 'z': nullToZero(data.rotationRateGamma) * degToRad, + }), + ]); + } else { + const sensorType = + data.absolute ? 'absolute-orientation' : 'relative-orientation'; + await test_driver.update_virtual_sensor(sensorType, { + alpha: nullToZero(data.alpha), + beta: nullToZero(data.beta), + gamma: nullToZero(data.gamma), + }); + } + } + + // Grants permissions to sensors. Depending on |eventName|, requests + // permission to use either the DeviceMotionEvent or the + // DeviceOrientationEvent API. + async grantSensorsPermissions() { + // Required by all event types. + await test_driver.set_permission({name: 'accelerometer'}, 'granted'); + await test_driver.set_permission({name: 'gyroscope'}, 'granted'); + if (this.#eventName == 'deviceorientationabsolute') { + await test_driver.set_permission({name: 'magnetometer'}, 'granted'); + } + + const interfaceName = this.#eventName == 'devicemotion' ? + DeviceMotionEvent : + DeviceOrientationEvent; + await test_driver.bless('enable user activation', async () => { + const permission = await interfaceName.requestPermission(); + assert_equals(permission, 'granted'); + }); + } + + // Resets SensorTestHelper to default state. Removes all created virtual + // sensors. + async reset() { + const createdVirtualSensors = + new Set([...this.#enabledSensors, ...this.#disabledSensors]); + + const sensorRemovalPromises = []; + for (const sensor of createdVirtualSensors) { + sensorRemovalPromises.push(test_driver.remove_virtual_sensor(sensor)); + } + await Promise.all(sensorRemovalPromises); + } +} + +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; +} + +function assertEventEquals(actualEvent, expectedEvent) { + // If two doubles differ by less than this amount, we can consider them + // to be effectively equal. + const EPSILON = 1e-8; + + for (let key1 of Object.keys(Object.getPrototypeOf(expectedEvent))) { + if (typeof expectedEvent[key1] === 'object' && + expectedEvent[key1] !== null) { + assertEventEquals(actualEvent[key1], expectedEvent[key1]); + } else if (typeof expectedEvent[key1] === 'number') { + assert_approx_equals( + actualEvent[key1], expectedEvent[key1], EPSILON, key1); + } 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}); + }); +} |