summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webxr/gamepads-module
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/webxr/gamepads-module
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/webxr/gamepads-module')
-rw-r--r--testing/web-platform/tests/webxr/gamepads-module/META.yml1
-rw-r--r--testing/web-platform/tests/webxr/gamepads-module/idlharness.https.window.js16
-rw-r--r--testing/web-platform/tests/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html159
-rw-r--r--testing/web-platform/tests/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html130
4 files changed, 306 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webxr/gamepads-module/META.yml b/testing/web-platform/tests/webxr/gamepads-module/META.yml
new file mode 100644
index 0000000000..a6751571a7
--- /dev/null
+++ b/testing/web-platform/tests/webxr/gamepads-module/META.yml
@@ -0,0 +1 @@
+spec: https://immersive-web.github.io/webxr-gamepads-module/
diff --git a/testing/web-platform/tests/webxr/gamepads-module/idlharness.https.window.js b/testing/web-platform/tests/webxr/gamepads-module/idlharness.https.window.js
new file mode 100644
index 0000000000..4509c67a84
--- /dev/null
+++ b/testing/web-platform/tests/webxr/gamepads-module/idlharness.https.window.js
@@ -0,0 +1,16 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+'use strict';
+
+// https://immersive-web.github.io/webxr-gamepads-module/
+
+idl_test(
+ ['webxr-gamepads-module'],
+ ['webxr', 'dom'],
+ async idl_array => {
+ idl_array.add_objects({
+ // TODO: XRInputSource
+ });
+ }
+);
diff --git a/testing/web-platform/tests/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html b/testing/web-platform/tests/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html
new file mode 100644
index 0000000000..bd69649d44
--- /dev/null
+++ b/testing/web-platform/tests/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html
@@ -0,0 +1,159 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/webxr_util.js"></script>
+<script src="../resources/webxr_test_constants.js"></script>
+
+<script>
+let testName = "WebXR InputSource's gamepad gets disconnected when the input source is removed";
+
+let watcherDone = new Event("watcherdone");
+
+let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE;
+
+let testFunction = function(session, fakeDeviceController, t) {
+ let eventWatcher = new EventWatcher(t, session, ["watcherdone"]);
+ let eventPromise = eventWatcher.wait_for(["watcherdone"]);
+
+ let inputChangeEvents = 0;
+ let cached_input_source = null;
+ function onInputSourcesChange(event) {
+ t.step(() => {
+ inputChangeEvents++;
+
+ // The first change event should be adding our controller/gamepad.
+ if (inputChangeEvents === 1) {
+ // We should have one input source
+ assert_equals(session.inputSources.length, 1,
+ "should initially have an input source");
+ assertGamepadConnected();
+ } else if (inputChangeEvents === 2) {
+ // The second event should be disconnecting our gamepad, we should still
+ // have an input source.
+ assert_equals(session.inputSources.length, 1,
+ "removing the gamepad shouldn't remove the input source");
+ // However, disconnecting the gamepad from the input source should cause
+ // the input source to be re-created. Verify this.
+ assertInputSourceRecreated(event);
+ assertGamepadDisconnected();
+ cached_input_source = session.inputSources[0];
+ } else if (inputChangeEvents === 3) {
+ assert_equals(session.inputSources.length, 1,
+ "re-adding the gamepad shouldn't add an extra input source");
+ // The third event should be reconnecting our gamepad, we should still
+ // have an input source. However, it should have been re-created.
+ assertInputSourceRecreated(event);
+ assertGamepadConnected();
+ } else if (inputChangeEvents === 4) {
+ // The fourth event should be disconnecting our gamepad, we should no
+ // longer have an input source.
+ assert_equals(session.inputSources.length, 0,
+ "input source should have been disconnected");
+ assertGamepadDisconnected();
+ } else if (inputChangeEvents === 5) {
+ // The fifth event should be re-connecting our gamepad to prep for
+ // ending the session.
+ assert_equals(session.inputSources.length, 1,
+ "input source should have been re-connected");
+ assertGamepadConnected();
+ session.dispatchEvent(watcherDone);
+ }
+ });
+ }
+
+ function assertInputSourceRecreated(event) {
+ assert_equals(event.added.length, 1);
+ assert_equals(event.removed.length, 1);
+ assert_equals(session.inputSources[0], event.added[0]);
+ assert_equals(cached_input_source, event.removed[0]);
+ }
+
+ function assertGamepadConnected() {
+ cached_input_source = session.inputSources[0];
+ assert_not_equals(cached_input_source, null,
+ "Expect to get a cached_input_source, iteration: " + inputChangeEvents);
+ assert_not_equals(cached_input_source.gamepad, null,
+ "Expect to have a gamepad, iteration: " + inputChangeEvents);
+ assert_equals(cached_input_source.gamepad.index, -1,
+ "WebXR Gamepad.index must be -1, iteration: " + inputChangeEvents);
+ assert_equals(cached_input_source.gamepad.id, "",
+ "WebXR Gamepad.id must be empty string, iteration: " + inputChangeEvents);
+ assert_true(cached_input_source.gamepad.connected,
+ "Expect the gamepad to be connected, iteration: " + inputChangeEvents);
+ }
+
+ function assertGamepadDisconnected() {
+ assert_not_equals(cached_input_source, null,
+ "Expect to have a cached_input_source, iteration: " + inputChangeEvents);
+ assert_not_equals(cached_input_source.gamepad, null,
+ "Expect to have a gamepad on cached_input_source, iteration: " + inputChangeEvents);
+ assert_equals(cached_input_source.gamepad.index, -1,
+ "WebXR Gamepad.index must be -1, iteration: " + inputChangeEvents);
+ assert_equals(cached_input_source.gamepad.id, "",
+ "WebXR Gamepad.id must be empty string, iteration: " + inputChangeEvents);
+ assert_false(cached_input_source.gamepad.connected,
+ "Expect cached gamepad to be disconnected, iteration: " + inputChangeEvents);
+ }
+
+ session.addEventListener('inputsourceschange', onInputSourcesChange, false);
+
+ // A set of supported buttons which should cause the runtime to treat the
+ // controller as supporting a gamepad.
+ let gamepadButtons = [
+ {
+ buttonType: 'grip',
+ pressed: false,
+ touched: false,
+ pressedValue: 0
+ },
+ {
+ buttonType: 'touchpad',
+ pressed: false,
+ touched: false,
+ pressedValue: 0
+ }
+ ];
+
+ let input_source = fakeDeviceController.simulateInputSourceConnection({
+ handedness: "right",
+ targetRayMode: "tracked-pointer",
+ pointerOrigin: VALID_POINTER_TRANSFORM,
+ profiles: [],
+ supportedButtons: gamepadButtons
+ });
+
+ // Input events need one frame to propagate, so this does (in order and running
+ // a rAF after each step:
+ // 1. Disconnect the gamepad (so we can verify that the gamepad is disconnected)
+ // 2. Reconnect the gamepad (so we can set up to disconnect the controller)
+ // 3. Disconnect the controller (so we can verify that it's gamepad gets disconnected).
+ // 4. Adds the controller back (so we can test the end Session)
+ // 5. Waits for all of the input events to finish propagating, then ends the
+ // session, at which point the controller should be disconnected.
+ return new Promise((resolve) => {
+ requestSkipAnimationFrame(session, () => {
+ input_source.setSupportedButtons([]);
+ session.requestAnimationFrame(() => {
+ input_source.setSupportedButtons(gamepadButtons);
+ session.requestAnimationFrame(() => {
+ input_source.disconnect();
+ session.requestAnimationFrame(() => {
+ input_source.reconnect();
+ session.requestAnimationFrame(() => {
+ eventPromise.then(() => {
+ session.end().then(() => {
+ assertGamepadDisconnected();
+ resolve();
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+};
+
+xr_session_promise_test(
+ testName, testFunction, fakeDeviceInitParams, 'immersive-vr');
+</script>
diff --git a/testing/web-platform/tests/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html b/testing/web-platform/tests/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html
new file mode 100644
index 0000000000..28f3084671
--- /dev/null
+++ b/testing/web-platform/tests/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/webxr_util.js"></script>
+<script src="../resources/webxr_test_constants.js"></script>
+
+<script>
+let testName = "WebXR InputSource's gamepad properly registers input";
+
+let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE;
+
+let testFunction = function(session, fakeDeviceController, t) {
+
+ // There should only be one input source change event, which is from adding
+ // the input source at the start of the test.
+ let inputChangeEvents = 0;
+ function onInputSourcesChange(event) {
+ assert_equals(inputChangeEvents, 0,
+ "Gamepad button or input axis value changes should not fire an input source change event.");
+ inputChangeEvents++;
+ }
+
+ session.addEventListener('inputsourceschange', onInputSourcesChange, false);
+
+ // Create our input source and immediately toggle the primary input so that
+ // it appears as already needing to send a click event when it appears.
+ let input_source = fakeDeviceController.simulateInputSourceConnection({
+ handedness: "right",
+ targetRayMode: "tracked-pointer",
+ pointerOrigin: VALID_POINTER_TRANSFORM,
+ profiles: [],
+ supportedButtons: [
+ {
+ buttonType: 'grip',
+ pressed: false,
+ touched: false,
+ pressedValue: 0
+ },
+ {
+ buttonType: 'touchpad',
+ pressed: false,
+ touched: false,
+ pressedValue: 0
+ }
+ ]
+ });
+
+ let cached_input_source = null;
+ let cached_gamepad = null;
+
+ function assertSameObjects() {
+ assert_equals(session.inputSources[0], cached_input_source);
+ assert_equals(cached_input_source.gamepad, cached_gamepad);
+
+ // Also make sure that WebXR gamepads have the index and id values required
+ // by the spec.
+ assert_equals(cached_gamepad.index, -1);
+ assert_equals(cached_gamepad.id, "");
+ }
+
+ // Input events and gamepad state changes (button presses, axis movements)
+ // need one frame to propagate, so this does (in order and running a rAF after
+ // each step):
+ // 1) Press the mock gamepad's button (so we can verify the button press makes
+ // its way to the WebXR gamepad and that it does not fire an
+ // inputsourceschange event).
+ // 2) Update the mock gamepad's input axes values (so we can verify the
+ // updated values make their way to the WebXR gamepad and that it does not
+ // fire an inputsourceschange event).
+ return new Promise((resolve) => {
+ requestSkipAnimationFrame(session, () => {
+ // Make sure the exposed gamepad has the number of buttons and axes we
+ // requested.
+ // 3 Buttons: trigger, grip, touchpad
+ // 2 Axes from the touchpad
+ cached_input_source = session.inputSources[0];
+ cached_gamepad = cached_input_source.gamepad;
+ t.step(() => {
+ assert_equals(cached_gamepad.index, -1);
+ assert_equals(cached_gamepad.id, "");
+ assert_equals(cached_gamepad.buttons.length, 3);
+ assert_equals(cached_gamepad.axes.length, 2);
+ // Initially, the button should not be pressed and the axes values should
+ // be set to 0.
+ assert_false(cached_gamepad.buttons[1].pressed);
+ assert_equals(cached_gamepad.axes[0], 0);
+ assert_equals(cached_gamepad.axes[1], 0);
+ }, "Verify initial state");
+ // Simulate button press.
+ input_source.updateButtonState({
+ buttonType: 'grip',
+ pressed: true,
+ touched: true,
+ value: 1.0
+ });
+ session.requestAnimationFrame(() => {
+ t.step(() => {
+ assertSameObjects();
+ assert_true(cached_gamepad.buttons[1].pressed);
+ }, "Gamepad is updated in place when a button is pressed");
+
+ // Simulate input axes movement.
+ input_source.updateButtonState({
+ buttonType: 'touchpad',
+ pressed: false,
+ touched: true,
+ value: 0,
+ xValue: 0.5,
+ yValue: -0.5
+ });
+ session.requestAnimationFrame(() => {
+ // Input source and gamepad should not be re-created. They should be
+ // updated in place when input axes values change.
+ t.step(() => {
+ assertSameObjects();
+ assert_equals(cached_gamepad.axes[0], 0.5);
+ assert_equals(cached_gamepad.axes[1], -0.5);
+ // Button that was pressed last frame should still be pressed.
+ assert_true(cached_gamepad.buttons[1].pressed);
+ }, "Gamepad is updated in place when axes values change");
+ resolve();
+ });
+ });
+ });
+ });
+};
+
+xr_session_promise_test(
+ testName, testFunction, fakeDeviceInitParams, 'immersive-vr');
+</script>