diff options
Diffstat (limited to 'testing/web-platform/tests/webxr/gamepads-module')
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> |