From 756bb0f4c8a94de98765bf957ed4b1711dfaac52 Mon Sep 17 00:00:00 2001 From: Maksim Sadym Date: Fri, 8 Nov 2024 12:17:13 +0100 Subject: [PATCH 1/6] Add bluetooth bidi module --- tools/webdriver/webdriver/bidi/client.py | 1 + .../webdriver/bidi/modules/__init__.py | 1 + .../webdriver/bidi/modules/bluetooth.py | 21 +++++++++++++ webdriver/tests/bidi/bluetooth/__init__.py | 0 .../bluetooth/simulate_adapter/__init__.py | 18 +++++++++++ .../bluetooth/simulate_adapter/context.py | 19 ++++++++++++ .../bluetooth/simulate_adapter/invalid.py | 31 +++++++++++++++++++ .../bidi/bluetooth/simulate_adapter/state.py | 31 +++++++++++++++++++ 8 files changed, 122 insertions(+) create mode 100644 tools/webdriver/webdriver/bidi/modules/bluetooth.py create mode 100644 webdriver/tests/bidi/bluetooth/__init__.py create mode 100644 webdriver/tests/bidi/bluetooth/simulate_adapter/__init__.py create mode 100644 webdriver/tests/bidi/bluetooth/simulate_adapter/context.py create mode 100644 webdriver/tests/bidi/bluetooth/simulate_adapter/invalid.py create mode 100644 webdriver/tests/bidi/bluetooth/simulate_adapter/state.py diff --git a/tools/webdriver/webdriver/bidi/client.py b/tools/webdriver/webdriver/bidi/client.py index d4cc78588e9fd8..8ba93bb7c2affe 100644 --- a/tools/webdriver/webdriver/bidi/client.py +++ b/tools/webdriver/webdriver/bidi/client.py @@ -90,6 +90,7 @@ def __init__(self, # Modules. # For each module, have a property representing that module + self.bluetooth = modules.Bluetooth(self) self.browser = modules.Browser(self) self.browsing_context = modules.BrowsingContext(self) self.input = modules.Input(self) diff --git a/tools/webdriver/webdriver/bidi/modules/__init__.py b/tools/webdriver/webdriver/bidi/modules/__init__.py index 0a2ef500c42ce0..81dd9e6e6f628b 100644 --- a/tools/webdriver/webdriver/bidi/modules/__init__.py +++ b/tools/webdriver/webdriver/bidi/modules/__init__.py @@ -1,5 +1,6 @@ # flake8: noqa +from .bluetooth import Bluetooth from .browser import Browser from .browsing_context import BrowsingContext from .input import Input diff --git a/tools/webdriver/webdriver/bidi/modules/bluetooth.py b/tools/webdriver/webdriver/bidi/modules/bluetooth.py new file mode 100644 index 00000000000000..1f32044f404cd9 --- /dev/null +++ b/tools/webdriver/webdriver/bidi/modules/bluetooth.py @@ -0,0 +1,21 @@ +from typing import Any, Mapping, MutableMapping + +from ._module import BidiModule, command + + +class Bluetooth(BidiModule): + """ + Represents bluetooth automation module specified in + https://webbluetoothcg.github.io/web-bluetooth/#automated-testing + """ + + @command + def simulate_adapter(self, context: str, state: str) -> Mapping[str, Any]: + """ + Represents a command `bluetooth.simulateAdapter` specified in + https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateAdapter-command + """ + return { + "context": context, + "state": state + } diff --git a/webdriver/tests/bidi/bluetooth/__init__.py b/webdriver/tests/bidi/bluetooth/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/webdriver/tests/bidi/bluetooth/simulate_adapter/__init__.py b/webdriver/tests/bidi/bluetooth/simulate_adapter/__init__.py new file mode 100644 index 00000000000000..ea1a7e6f232d42 --- /dev/null +++ b/webdriver/tests/bidi/bluetooth/simulate_adapter/__init__.py @@ -0,0 +1,18 @@ +from webdriver.bidi.modules.script import ContextTarget + + +async def get_bluetooth_availability(bidi_session, context): + result = await bidi_session.script.evaluate( + expression="navigator.bluetooth.getAvailability()", + target=ContextTarget(context["context"]), await_promise=True, ) + return result['value'] + + +async def set_simulate_adapter(bidi_session, context, test_page, state): + # Navigate to a page, as bluetooth is not guaranteed to work on + # `about:blank`. + await bidi_session.browsing_context.navigate(context=context['context'], + url=test_page, wait="complete") + + await bidi_session.bluetooth.simulate_adapter(context=context["context"], + state=state) diff --git a/webdriver/tests/bidi/bluetooth/simulate_adapter/context.py b/webdriver/tests/bidi/bluetooth/simulate_adapter/context.py new file mode 100644 index 00000000000000..dc9e9a587376f4 --- /dev/null +++ b/webdriver/tests/bidi/bluetooth/simulate_adapter/context.py @@ -0,0 +1,19 @@ +import pytest + +from . import get_bluetooth_availability, set_simulate_adapter + +pytestmark = pytest.mark.asyncio + + +async def test_contexts_are_isolated(bidi_session, top_context, test_page): + another_browsing_context = await bidi_session.browsing_context.create( + type_hint="tab") + + await set_simulate_adapter(bidi_session, top_context, test_page, + "powered-on") + await set_simulate_adapter(bidi_session, another_browsing_context, + test_page, "absent") + + assert await get_bluetooth_availability(bidi_session, top_context) == True + assert await get_bluetooth_availability(bidi_session, + another_browsing_context) == False diff --git a/webdriver/tests/bidi/bluetooth/simulate_adapter/invalid.py b/webdriver/tests/bidi/bluetooth/simulate_adapter/invalid.py new file mode 100644 index 00000000000000..8fe2538873b8ba --- /dev/null +++ b/webdriver/tests/bidi/bluetooth/simulate_adapter/invalid.py @@ -0,0 +1,31 @@ +import pytest +import webdriver.bidi.error as error + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize("state", [None, False, 42, {}, []]) +async def test_state_invalid_type(bidi_session, top_context, state): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.bluetooth.simulate_adapter( + context=top_context["context"], state=state) + + +@pytest.mark.parametrize("state", ["", "invalid"]) +async def test_state_invalid_value(bidi_session, top_context, state): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.bluetooth.simulate_adapter( + context=top_context["context"], state=state) + + +@pytest.mark.parametrize("context", [None, False, 42, {}, []]) +async def test_context_invalid_type(bidi_session, context): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.bluetooth.simulate_adapter( + context=context, state="powered-on") + + +async def test_context_unknown_value(bidi_session): + with pytest.raises(error.NoSuchFrameException): + await bidi_session.bluetooth.simulate_adapter( + context="UNKNOWN_CONTEXT", state="powered-on") diff --git a/webdriver/tests/bidi/bluetooth/simulate_adapter/state.py b/webdriver/tests/bidi/bluetooth/simulate_adapter/state.py new file mode 100644 index 00000000000000..ad21326081e077 --- /dev/null +++ b/webdriver/tests/bidi/bluetooth/simulate_adapter/state.py @@ -0,0 +1,31 @@ +import pytest + +from . import get_bluetooth_availability, set_simulate_adapter + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize("state,availability", + [("absent", False), ("powered-off", True), + ("powered-on", True)]) +async def test_state(bidi_session, top_context, test_page, state, availability): + await set_simulate_adapter(bidi_session, top_context, test_page, state) + assert await get_bluetooth_availability(bidi_session, + top_context) == availability + + +@pytest.mark.parametrize("state_1,availability_1", + [("absent", False), ("powered-off", True), + ("powered-on", True)]) +@pytest.mark.parametrize("state_2,availability_2", + [("absent", False), ("powered-off", True), + ("powered-on", True)]) +async def test_set_twice(bidi_session, top_context, test_page, state_1, + availability_1, state_2, availability_2): + await set_simulate_adapter(bidi_session, top_context, test_page, state_1) + assert await get_bluetooth_availability(bidi_session, + top_context) == availability_1 + + await set_simulate_adapter(bidi_session, top_context, test_page, state_2) + assert await get_bluetooth_availability(bidi_session, + top_context) == availability_2 From 52f0a4f825d1b71b76267166a2d950e99c42340f Mon Sep 17 00:00:00 2001 From: Maksim Sadym Date: Fri, 8 Nov 2024 16:17:40 +0100 Subject: [PATCH 2/6] Add documentation for extending BiDi --- docs/writing-tests/wdspec.md | 83 +++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/docs/writing-tests/wdspec.md b/docs/writing-tests/wdspec.md index 1943fb9e943612..195380f24bc924 100644 --- a/docs/writing-tests/wdspec.md +++ b/docs/writing-tests/wdspec.md @@ -1,7 +1,8 @@ # wdspec tests The term "wdspec" describes a type of test in WPT which verifies some aspect of -[the WebDriver protocol](https://w3c.github.io/webdriver/). These tests are +[WebDriver Classic](https://w3c.github.io/webdriver/) or +[WebDriver BiDi](https://w3c.github.io/webdriver-bidi) protocols. These tests are written in [the Python programming language](https://www.python.org/) and structured with [the pytest testing framework](https://docs.pytest.org/en/latest/). @@ -66,3 +67,83 @@ a WebDriver session) are defined in terms of Pytest "fixtures" and must be loaded accordingly. For more detail on how to define and use test fixtures, please refer to [the pytest project's documentation on the topic](https://docs.pytest.org/en/latest/fixture.html). + +## WebDriver BiDi + +The wdspec tests for [WebDriver BiDi](https://w3c.github.io/webdriver-bidi) are +located in the `tests/bidi/` and `tests/interop` directory. The abstraction +`webdriver.bidi.client.BidiSession` represents the BiDi client and contains +properties corresponding to the +[WebDriver BiDi modules](https://w3c.github.io/webdriver-bidi/#protocol-modules). + +### Extending WebDriver BiDi + +This section describes extending WebDriver BiDi client in the example of adding +support for [Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth). + +#### Adding new module + +##### Create `BidiModule` + +The BiDi modules are presented in `tools/webdriver/webdriver/bidi/modules/` +directory. In order to add new module `bluetooth`, declare a python class +`webdriver.bidi.modules.bluetooth.Bluetooth` inheriting from the `BidiModule`and +store it in `tools/webdriver/webdriver/bidi/modules/bluetooth.py`: +```python +class Bluetooth(BidiModule): + """ + Represents bluetooth automation module specified in + https://webbluetoothcg.github.io/web-bluetooth/#automated-testing + """ + pass +``` + +#### Import module in `bidi/modules/__init__.py` + +This class +should be imported in `tools/webdriver/webdriver/bidi/modules/__init__.py`. +```python +from .bluetooth import Bluetooth +``` + +#### Create an instance of the module in `webdriver.bidi.client.BidiSession` + +The `webdriver.bidi.client.BidiSession:__init__` method should create an instance of +`Bluetooth` and store it in `bluetooth` property: +```python +self.bluetooth = modules.Bluetooth(self) +``` + +#### Adding new command + +The [WebDriver BiDi commands](https://w3c.github.io/webdriver-bidi/#commands) +are represented as module methods with `@command` decorator +(`webdriver.bidi.modules._module.command`). In order to add a new command, a method +with the corresponding name (translated camel case to snake case) should be added to +the module. The method returns a dictionary which is used as +[command-parameters](https://w3c.github.io/webdriver-bidi/#command-command-parameters). +For example to add +[`bluetooth.simulateAdapter`](https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateAdapter-command) +command, add the following `simulate_adapter` method to `Bluetooth` class: +```python +from ._module import command +... +class Bluetooth(BidiModule): + ... + @command + def simulate_adapter(self, context: str, state: str) -> Mapping[str, Any]: + return { + "context": context, + "state": state + } +``` + +### Adding tests + +Normally a single test file contains tests of a single parameter or feature. In +example of +[`bluetooth.simulateAdapter`](https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateAdapter-command), +it would make sense to split into: +* Invalid parameters: `webdriver/tests/bidi/bluetooth/simulate_adapter/invalid.py` +* State: `webdriver/tests/bidi/bluetooth/simulate_adapter/state.py` +* Context: `webdriver/tests/bidi/bluetooth/simulate_adapter/context.py` From 9d255cef35c76d5b2c348ee1c8bd55f17ac33def Mon Sep 17 00:00:00 2001 From: Maksim Sadym Date: Fri, 8 Nov 2024 16:30:29 +0100 Subject: [PATCH 3/6] Improve doc --- docs/writing-tests/wdspec.md | 74 ++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/docs/writing-tests/wdspec.md b/docs/writing-tests/wdspec.md index 195380f24bc924..82185646f7be62 100644 --- a/docs/writing-tests/wdspec.md +++ b/docs/writing-tests/wdspec.md @@ -71,60 +71,65 @@ topic](https://docs.pytest.org/en/latest/fixture.html). ## WebDriver BiDi The wdspec tests for [WebDriver BiDi](https://w3c.github.io/webdriver-bidi) are -located in the `tests/bidi/` and `tests/interop` directory. The abstraction -`webdriver.bidi.client.BidiSession` represents the BiDi client and contains -properties corresponding to the -[WebDriver BiDi modules](https://w3c.github.io/webdriver-bidi/#protocol-modules). +located in the `tests/bidi/` and `tests/interop` directories. +The `webdriver.bidi.client.BidiSession` class provides an abstraction for the BiDi +client and contains properties corresponding to the +[WebDriver BiDi modules](https://w3c.github.io/webdriver-bidi/#protocol-modules). It +can be retrieved by fixture `bidi_session`. ### Extending WebDriver BiDi -This section describes extending WebDriver BiDi client in the example of adding -support for [Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth). +This section describes how to extend the WebDriver BiDi client with an example of +adding support for [Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth). -#### Adding new module +#### Adding a New Module ##### Create `BidiModule` -The BiDi modules are presented in `tools/webdriver/webdriver/bidi/modules/` -directory. In order to add new module `bluetooth`, declare a python class -`webdriver.bidi.modules.bluetooth.Bluetooth` inheriting from the `BidiModule`and +BiDi modules are defined in the `tools/webdriver/webdriver/bidi/modules/` directory. +To add a new module called `bluetooth`, declare a Python class +`webdriver.bidi.modules.bluetooth.Bluetooth` that inherits from `BidiModule` and store it in `tools/webdriver/webdriver/bidi/modules/bluetooth.py`: + ```python class Bluetooth(BidiModule): """ - Represents bluetooth automation module specified in + Represents the Bluetooth automation module specified in https://webbluetoothcg.github.io/web-bluetooth/#automated-testing """ pass ``` -#### Import module in `bidi/modules/__init__.py` +##### Import the Module in `bidi/modules/__init__.py` + +Import this class in `tools/webdriver/webdriver/bidi/modules/__init__.py`: -This class -should be imported in `tools/webdriver/webdriver/bidi/modules/__init__.py`. ```python from .bluetooth import Bluetooth ``` -#### Create an instance of the module in `webdriver.bidi.client.BidiSession` +##### Create an Instance of the Module in `webdriver.bidi.client.BidiSession` + +Modify the `webdriver.bidi.client.BidiSession.__init__` method to create an instance +of `Bluetooth` and store it in a `bluetooth` property: -The `webdriver.bidi.client.BidiSession:__init__` method should create an instance of -`Bluetooth` and store it in `bluetooth` property: ```python self.bluetooth = modules.Bluetooth(self) ``` -#### Adding new command +#### Adding a New Command + +[WebDriver BiDi commands](https://w3c.github.io/webdriver-bidi/#commands) are +represented as module methods decorated with +`@command` (`webdriver.bidi.modules._module.command`). To add a new command, add +a method with the corresponding name (translated from camel case to snake case) to +the module. The method should return a dictionary that represents the +[command parameters](https://w3c.github.io/webdriver-bidi/#command-command-parameters). + +For example, to add the +[`bluetooth.simulateAdapter`](https://w3c.github.io/webdriver-bidi/#command-command-parameters) +command, add the following `simulate_adapter` method to the `Bluetooth` class: -The [WebDriver BiDi commands](https://w3c.github.io/webdriver-bidi/#commands) -are represented as module methods with `@command` decorator -(`webdriver.bidi.modules._module.command`). In order to add a new command, a method -with the corresponding name (translated camel case to snake case) should be added to -the module. The method returns a dictionary which is used as -[command-parameters](https://w3c.github.io/webdriver-bidi/#command-command-parameters). -For example to add -[`bluetooth.simulateAdapter`](https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateAdapter-command) -command, add the following `simulate_adapter` method to `Bluetooth` class: ```python from ._module import command ... @@ -138,12 +143,17 @@ class Bluetooth(BidiModule): } ``` -### Adding tests +### Adding Tests -Normally a single test file contains tests of a single parameter or feature. In -example of -[`bluetooth.simulateAdapter`](https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateAdapter-command), -it would make sense to split into: +Generally, a single test file should contain tests for a single parameter or feature +and stored in `webdriver/tests/bidi/{MODULE}/{METHOD}/{FEATURE}.py` +For example, tests for +[`bluetooth.simulateAdapter`](https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateAdapter-command) +could be split into: * Invalid parameters: `webdriver/tests/bidi/bluetooth/simulate_adapter/invalid.py` * State: `webdriver/tests/bidi/bluetooth/simulate_adapter/state.py` * Context: `webdriver/tests/bidi/bluetooth/simulate_adapter/context.py` + +In the example of [`bluetooth.simulateAdapter`](https://w3c.github.io/webdriver-bidi/#command-command-parameters), +tests can use `bidi_session.bluetooth.simulate_adapter` method to send the command +and verify its side effects. From 290f02ae4e0e002e923264dd432e7c2ef0cec91a Mon Sep 17 00:00:00 2001 From: Maksim Sadym Date: Fri, 8 Nov 2024 17:57:37 +0100 Subject: [PATCH 4/6] Move bluetooth to external --- docs/writing-tests/wdspec.md | 11 +++++++---- .../tests/bidi/{bluetooth => external}/__init__.py | 0 webdriver/tests/bidi/external/bluetooth/__init__.py | 0 .../bluetooth/simulate_adapter/__init__.py | 0 .../bluetooth/simulate_adapter/context.py | 0 .../bluetooth/simulate_adapter/invalid.py | 0 .../bluetooth/simulate_adapter/state.py | 0 7 files changed, 7 insertions(+), 4 deletions(-) rename webdriver/tests/bidi/{bluetooth => external}/__init__.py (100%) create mode 100644 webdriver/tests/bidi/external/bluetooth/__init__.py rename webdriver/tests/bidi/{ => external}/bluetooth/simulate_adapter/__init__.py (100%) rename webdriver/tests/bidi/{ => external}/bluetooth/simulate_adapter/context.py (100%) rename webdriver/tests/bidi/{ => external}/bluetooth/simulate_adapter/invalid.py (100%) rename webdriver/tests/bidi/{ => external}/bluetooth/simulate_adapter/state.py (100%) diff --git a/docs/writing-tests/wdspec.md b/docs/writing-tests/wdspec.md index 82185646f7be62..861ea854aa9f49 100644 --- a/docs/writing-tests/wdspec.md +++ b/docs/writing-tests/wdspec.md @@ -71,7 +71,11 @@ topic](https://docs.pytest.org/en/latest/fixture.html). ## WebDriver BiDi The wdspec tests for [WebDriver BiDi](https://w3c.github.io/webdriver-bidi) are -located in the `tests/bidi/` and `tests/interop` directories. +located in the `tests/bidi/` and `tests/interop` directories. Tests related to +external specifications (like [Permissions](https://www.w3.org/TR/permissions/) or +[Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth)) are located in +`external` subdirectories. E.g. `tests/bidi/external/permissions/`. + The `webdriver.bidi.client.BidiSession` class provides an abstraction for the BiDi client and contains properties corresponding to the [WebDriver BiDi modules](https://w3c.github.io/webdriver-bidi/#protocol-modules). It @@ -154,6 +158,5 @@ could be split into: * State: `webdriver/tests/bidi/bluetooth/simulate_adapter/state.py` * Context: `webdriver/tests/bidi/bluetooth/simulate_adapter/context.py` -In the example of [`bluetooth.simulateAdapter`](https://w3c.github.io/webdriver-bidi/#command-command-parameters), -tests can use `bidi_session.bluetooth.simulate_adapter` method to send the command -and verify its side effects. +Tests should use `bidi_session`'s modules' methods to send commands and verify its +side effects. diff --git a/webdriver/tests/bidi/bluetooth/__init__.py b/webdriver/tests/bidi/external/__init__.py similarity index 100% rename from webdriver/tests/bidi/bluetooth/__init__.py rename to webdriver/tests/bidi/external/__init__.py diff --git a/webdriver/tests/bidi/external/bluetooth/__init__.py b/webdriver/tests/bidi/external/bluetooth/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/webdriver/tests/bidi/bluetooth/simulate_adapter/__init__.py b/webdriver/tests/bidi/external/bluetooth/simulate_adapter/__init__.py similarity index 100% rename from webdriver/tests/bidi/bluetooth/simulate_adapter/__init__.py rename to webdriver/tests/bidi/external/bluetooth/simulate_adapter/__init__.py diff --git a/webdriver/tests/bidi/bluetooth/simulate_adapter/context.py b/webdriver/tests/bidi/external/bluetooth/simulate_adapter/context.py similarity index 100% rename from webdriver/tests/bidi/bluetooth/simulate_adapter/context.py rename to webdriver/tests/bidi/external/bluetooth/simulate_adapter/context.py diff --git a/webdriver/tests/bidi/bluetooth/simulate_adapter/invalid.py b/webdriver/tests/bidi/external/bluetooth/simulate_adapter/invalid.py similarity index 100% rename from webdriver/tests/bidi/bluetooth/simulate_adapter/invalid.py rename to webdriver/tests/bidi/external/bluetooth/simulate_adapter/invalid.py diff --git a/webdriver/tests/bidi/bluetooth/simulate_adapter/state.py b/webdriver/tests/bidi/external/bluetooth/simulate_adapter/state.py similarity index 100% rename from webdriver/tests/bidi/bluetooth/simulate_adapter/state.py rename to webdriver/tests/bidi/external/bluetooth/simulate_adapter/state.py From 060a0a45ef11e0be68e3bfa514e6fa7caee428fa Mon Sep 17 00:00:00 2001 From: Maksim Sadym Date: Fri, 8 Nov 2024 18:01:09 +0100 Subject: [PATCH 5/6] Rolls back doc --- docs/writing-tests/wdspec.md | 96 +----------------------------------- 1 file changed, 1 insertion(+), 95 deletions(-) diff --git a/docs/writing-tests/wdspec.md b/docs/writing-tests/wdspec.md index 861ea854aa9f49..1943fb9e943612 100644 --- a/docs/writing-tests/wdspec.md +++ b/docs/writing-tests/wdspec.md @@ -1,8 +1,7 @@ # wdspec tests The term "wdspec" describes a type of test in WPT which verifies some aspect of -[WebDriver Classic](https://w3c.github.io/webdriver/) or -[WebDriver BiDi](https://w3c.github.io/webdriver-bidi) protocols. These tests are +[the WebDriver protocol](https://w3c.github.io/webdriver/). These tests are written in [the Python programming language](https://www.python.org/) and structured with [the pytest testing framework](https://docs.pytest.org/en/latest/). @@ -67,96 +66,3 @@ a WebDriver session) are defined in terms of Pytest "fixtures" and must be loaded accordingly. For more detail on how to define and use test fixtures, please refer to [the pytest project's documentation on the topic](https://docs.pytest.org/en/latest/fixture.html). - -## WebDriver BiDi - -The wdspec tests for [WebDriver BiDi](https://w3c.github.io/webdriver-bidi) are -located in the `tests/bidi/` and `tests/interop` directories. Tests related to -external specifications (like [Permissions](https://www.w3.org/TR/permissions/) or -[Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth)) are located in -`external` subdirectories. E.g. `tests/bidi/external/permissions/`. - -The `webdriver.bidi.client.BidiSession` class provides an abstraction for the BiDi -client and contains properties corresponding to the -[WebDriver BiDi modules](https://w3c.github.io/webdriver-bidi/#protocol-modules). It -can be retrieved by fixture `bidi_session`. - -### Extending WebDriver BiDi - -This section describes how to extend the WebDriver BiDi client with an example of -adding support for [Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth). - -#### Adding a New Module - -##### Create `BidiModule` - -BiDi modules are defined in the `tools/webdriver/webdriver/bidi/modules/` directory. -To add a new module called `bluetooth`, declare a Python class -`webdriver.bidi.modules.bluetooth.Bluetooth` that inherits from `BidiModule` and -store it in `tools/webdriver/webdriver/bidi/modules/bluetooth.py`: - -```python -class Bluetooth(BidiModule): - """ - Represents the Bluetooth automation module specified in - https://webbluetoothcg.github.io/web-bluetooth/#automated-testing - """ - pass -``` - -##### Import the Module in `bidi/modules/__init__.py` - -Import this class in `tools/webdriver/webdriver/bidi/modules/__init__.py`: - -```python -from .bluetooth import Bluetooth -``` - -##### Create an Instance of the Module in `webdriver.bidi.client.BidiSession` - -Modify the `webdriver.bidi.client.BidiSession.__init__` method to create an instance -of `Bluetooth` and store it in a `bluetooth` property: - -```python -self.bluetooth = modules.Bluetooth(self) -``` - -#### Adding a New Command - -[WebDriver BiDi commands](https://w3c.github.io/webdriver-bidi/#commands) are -represented as module methods decorated with -`@command` (`webdriver.bidi.modules._module.command`). To add a new command, add -a method with the corresponding name (translated from camel case to snake case) to -the module. The method should return a dictionary that represents the -[command parameters](https://w3c.github.io/webdriver-bidi/#command-command-parameters). - -For example, to add the -[`bluetooth.simulateAdapter`](https://w3c.github.io/webdriver-bidi/#command-command-parameters) -command, add the following `simulate_adapter` method to the `Bluetooth` class: - -```python -from ._module import command -... -class Bluetooth(BidiModule): - ... - @command - def simulate_adapter(self, context: str, state: str) -> Mapping[str, Any]: - return { - "context": context, - "state": state - } -``` - -### Adding Tests - -Generally, a single test file should contain tests for a single parameter or feature -and stored in `webdriver/tests/bidi/{MODULE}/{METHOD}/{FEATURE}.py` -For example, tests for -[`bluetooth.simulateAdapter`](https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateAdapter-command) -could be split into: -* Invalid parameters: `webdriver/tests/bidi/bluetooth/simulate_adapter/invalid.py` -* State: `webdriver/tests/bidi/bluetooth/simulate_adapter/state.py` -* Context: `webdriver/tests/bidi/bluetooth/simulate_adapter/context.py` - -Tests should use `bidi_session`'s modules' methods to send commands and verify its -side effects. From 17592fe9189f7f62cb9abbb81c3025a6c1caacb0 Mon Sep 17 00:00:00 2001 From: Maksim Sadym Date: Fri, 8 Nov 2024 18:10:20 +0100 Subject: [PATCH 6/6] fix flake8 --- tools/webdriver/webdriver/bidi/modules/bluetooth.py | 2 +- .../tests/bidi/external/bluetooth/simulate_adapter/context.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/webdriver/webdriver/bidi/modules/bluetooth.py b/tools/webdriver/webdriver/bidi/modules/bluetooth.py index 1f32044f404cd9..1013d28e8c644f 100644 --- a/tools/webdriver/webdriver/bidi/modules/bluetooth.py +++ b/tools/webdriver/webdriver/bidi/modules/bluetooth.py @@ -1,4 +1,4 @@ -from typing import Any, Mapping, MutableMapping +from typing import Any, Mapping from ._module import BidiModule, command diff --git a/webdriver/tests/bidi/external/bluetooth/simulate_adapter/context.py b/webdriver/tests/bidi/external/bluetooth/simulate_adapter/context.py index dc9e9a587376f4..ef56a33219ce0e 100644 --- a/webdriver/tests/bidi/external/bluetooth/simulate_adapter/context.py +++ b/webdriver/tests/bidi/external/bluetooth/simulate_adapter/context.py @@ -14,6 +14,6 @@ async def test_contexts_are_isolated(bidi_session, top_context, test_page): await set_simulate_adapter(bidi_session, another_browsing_context, test_page, "absent") - assert await get_bluetooth_availability(bidi_session, top_context) == True + assert await get_bluetooth_availability(bidi_session, top_context) is True assert await get_bluetooth_availability(bidi_session, - another_browsing_context) == False + another_browsing_context) is False