diff --git a/docs/writing-tests/testdriver.md b/docs/writing-tests/testdriver.md index d831e2b7c6af87..462c7b85503cb9 100644 --- a/docs/writing-tests/testdriver.md +++ b/docs/writing-tests/testdriver.md @@ -278,3 +278,11 @@ const event = await log_entry_promise; .. js:autofunction:: test_driver.bidi.log.entry_added.on .. js:autofunction:: test_driver.bidi.log.entry_added.once ``` + +### Bluetooth ### + +The module provides access to [Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth). + +```eval_rst +.. js:autofunction:: test_driver.bidi.bluetooth.simulate_adapter +``` diff --git a/infrastructure/metadata/infrastructure/testdriver/bidi/bluetooth/simulate_adapter.https.html.ini b/infrastructure/metadata/infrastructure/testdriver/bidi/bluetooth/simulate_adapter.https.html.ini new file mode 100644 index 00000000000000..7c3127d167a740 --- /dev/null +++ b/infrastructure/metadata/infrastructure/testdriver/bidi/bluetooth/simulate_adapter.https.html.ini @@ -0,0 +1 @@ +disabled: https://github.com/web-platform-tests/wpt/issues/47544 diff --git a/infrastructure/testdriver/bidi/bluetooth/simulate_adapter.https.html b/infrastructure/testdriver/bidi/bluetooth/simulate_adapter.https.html new file mode 100644 index 00000000000000..3850fa26974a32 --- /dev/null +++ b/infrastructure/testdriver/bidi/bluetooth/simulate_adapter.https.html @@ -0,0 +1,36 @@ + + +TestDriver bidi.bluetooth.simulate_adapter method + + + + + + diff --git a/resources/testdriver.js b/resources/testdriver.js index 2afd86d8761fe6..bdd18cc0e7d063 100644 --- a/resources/testdriver.js +++ b/resources/testdriver.js @@ -58,7 +58,35 @@ * be specified by its ID (a string) or using a `WindowProxy` * object. */ - + /** + * `bluetooth `_ module. + */ + bluetooth: { + /** + * Creates a simulated bluetooth adapter with the given params. Matches the + * `bluetooth.simulateAdapter `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.simulate_adapter({ + * state: "powered-on" + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.state The state of the simulated bluetooth adapter. + * Matches the + * `bluetooth.SimulateAdapterParameters:state `_ + * value. + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context the simulated bluetooth adapter should be set. If not + * provided, the current browsing context is used. + * @returns {Promise} fulfilled after the simulated bluetooth adapter is created + * and set, or rejected if the operation fails. + */ + simulate_adapter: function (params) { + return window.test_driver_internal.bidi.bluetooth.simulate_adapter(params); + } + }, /** * `log `_ module. */ @@ -1287,6 +1315,12 @@ in_automation: false, bidi: { + bluetooth: { + simulate_adapter: function () { + throw new Error( + "bidi.bluetooth.simulate_adapter is not implemented by testdriver-vendor.js"); + } + }, log: { entry_added: { async subscribe() { diff --git a/tools/wptrunner/wptrunner/executors/asyncactions.py b/tools/wptrunner/wptrunner/executors/asyncactions.py index c49c2a3ca61d82..ef5344e19b29a7 100644 --- a/tools/wptrunner/wptrunner/executors/asyncactions.py +++ b/tools/wptrunner/wptrunner/executors/asyncactions.py @@ -7,6 +7,32 @@ def do_delayed_imports(): global webdriver import webdriver + +class BidiBluetoothSimulateAdapterAction: + name = "bidi.bluetooth.simulate_adapter" + + def __init__(self, logger, protocol): + do_delayed_imports() + self.logger = logger + self.protocol = protocol + + async def __call__(self, payload): + if payload["context"] is None: + raise ValueError("Missing required parameter: context") + + context = payload["context"] + if isinstance(context, str): + pass + elif isinstance(context, webdriver.bidi.protocol.BidiWindow): + # Context can be a serialized WindowProxy. + context = context.browsing_context + else: + raise ValueError("Unexpected context type: %s" % context) + + state = payload["state"] + return await self.protocol.bidi_bluetooth.simulate_adapter(context, state) + + class BidiSessionSubscribeAction: name = "bidi.session.subscribe" @@ -49,4 +75,7 @@ async def __call__(self, payload): origin) -async_actions = [BidiPermissionsSetPermissionAction, BidiSessionSubscribeAction] +async_actions = [ + BidiBluetoothSimulateAdapterAction, + BidiPermissionsSetPermissionAction, + BidiSessionSubscribeAction] diff --git a/tools/wptrunner/wptrunner/executors/executorwebdriver.py b/tools/wptrunner/wptrunner/executors/executorwebdriver.py index 8ec2fbe27979fb..c2923d13a9ead5 100644 --- a/tools/wptrunner/wptrunner/executors/executorwebdriver.py +++ b/tools/wptrunner/wptrunner/executors/executorwebdriver.py @@ -37,6 +37,7 @@ RPHRegistrationsProtocolPart, FedCMProtocolPart, VirtualSensorProtocolPart, + BidiBluetoothProtocolPart, BidiBrowsingContextProtocolPart, BidiEventsProtocolPart, BidiPermissionsProtocolPart, @@ -115,6 +116,21 @@ def wait(self): return False +class WebDriverBidiBluetoothProtocolPart(BidiBluetoothProtocolPart): + def __init__(self, parent): + super().__init__(parent) + self.webdriver = None + + def setup(self): + self.webdriver = self.parent.webdriver + + async def simulate_adapter(self, + context: str, + state: str) -> None: + await self.webdriver.bidi_session.bluetooth.simulate_adapter( + context=context, state=state) + + class WebDriverBidiBrowsingContextProtocolPart(BidiBrowsingContextProtocolPart): def __init__(self, parent): super().__init__(parent) @@ -692,7 +708,8 @@ def after_connect(self): class WebDriverBidiProtocol(WebDriverProtocol): enable_bidi = True - implements = [WebDriverBidiBrowsingContextProtocolPart, + implements = [WebDriverBidiBluetoothProtocolPart, + WebDriverBidiBrowsingContextProtocolPart, WebDriverBidiEventsProtocolPart, WebDriverBidiPermissionsProtocolPart, WebDriverBidiScriptProtocolPart, diff --git a/tools/wptrunner/wptrunner/executors/protocol.py b/tools/wptrunner/wptrunner/executors/protocol.py index 33f4066893ed5f..19d5b49d2b7fb4 100644 --- a/tools/wptrunner/wptrunner/executors/protocol.py +++ b/tools/wptrunner/wptrunner/executors/protocol.py @@ -331,6 +331,23 @@ def get_computed_role(self, element): pass +class BidiBluetoothProtocolPart(ProtocolPart): + """Protocol part for managing BiDi events""" + __metaclass__ = ABCMeta + name = "bidi_bluetooth" + + @abstractmethod + async def simulate_adapter(self, + context: str, + state: str) -> None: + """ + Creates a simulated bluetooth adapter. + :param context: Browsing context to set the simulated adapter to. + :param state: The state of the simulated bluetooth adapter. + """ + pass + + class BidiBrowsingContextProtocolPart(ProtocolPart): """Protocol part for managing BiDi events""" __metaclass__ = ABCMeta diff --git a/tools/wptrunner/wptrunner/testdriver-extra.js b/tools/wptrunner/wptrunner/testdriver-extra.js index 88eb95a09c5912..c4a02ef40a7eda 100644 --- a/tools/wptrunner/wptrunner/testdriver-extra.js +++ b/tools/wptrunner/wptrunner/testdriver-extra.js @@ -208,6 +208,14 @@ window.test_driver_internal.in_automation = true; + window.test_driver_internal.bidi.bluetooth.simulate_adapter = function (params) { + return create_action("bidi.bluetooth.simulate_adapter", { + // Default to the current window. + context: window, + ...params + }); + } + window.test_driver_internal.bidi.log.entry_added.subscribe = function (params) { return subscribe({