diff options
Diffstat (limited to 'testing/web-platform/tests/docs/writing-tests/testdriver.md')
-rw-r--r-- | testing/web-platform/tests/docs/writing-tests/testdriver.md | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/testing/web-platform/tests/docs/writing-tests/testdriver.md b/testing/web-platform/tests/docs/writing-tests/testdriver.md new file mode 100644 index 0000000000..11193b147f --- /dev/null +++ b/testing/web-platform/tests/docs/writing-tests/testdriver.md @@ -0,0 +1,228 @@ +# testdriver.js Automation + +```eval_rst + +.. contents:: Table of Contents + :depth: 3 + :local: + :backlinks: none +``` + +testdriver.js provides a means to automate tests that cannot be +written purely using web platform APIs. Outside of automation +contexts, it allows human operators to provide expected input +manually (for operations which may be described in simple terms). + +It is currently supported only for [testharness.js](testharness) +tests. + +## Markup ## + +The `testdriver.js` and `testdriver-vendor.js` must both be included +in any document that uses testdriver (and in the top-level test +document when using testdriver from a different context): + +```html +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +``` + +## API ## + +testdriver.js exposes its API through the `test_driver` variable in +the global scope. + +### User Interaction ### + +```eval_rst +.. js:autofunction:: test_driver.click +.. js:autofunction:: test_driver.send_keys +.. js:autofunction:: test_driver.action_sequence +.. js:autofunction:: test_driver.bless +``` + +### Window State ### +```eval_rst +.. js:autofunction:: test_driver.minimize_window +.. js:autofunction:: test_driver.set_window_rect +``` + +### Cookies ### +```eval_rst +.. js:autofunction:: test_driver.delete_all_cookies +.. js:autofunction:: test_driver.get_all_cookies +.. js:autofunction:: test_driver.get_named_cookie +``` + +### Permissions ### +```eval_rst +.. js:autofunction:: test_driver.set_permission +``` + +### Authentication ### + +```eval_rst +.. js:autofunction:: test_driver.add_virtual_authenticator +.. js:autofunction:: test_driver.remove_virtual_authenticator +.. js:autofunction:: test_driver.add_credential +.. js:autofunction:: test_driver.get_credentials +.. js:autofunction:: test_driver.remove_credential +.. js:autofunction:: test_driver.remove_all_credentials +.. js:autofunction:: test_driver.set_user_verified +``` + +### Page Lifecycle ### +```eval_rst +.. js:autofunction:: test_driver.freeze +``` + +### Reporting Observer ### +```eval_rst +.. js:autofunction:: test_driver.generate_test_report +``` + +### Storage ### +```eval_rst +.. js:autofunction:: test_driver.set_storage_access + +``` + +### Seure Payment Confirmation ### +```eval_rst +.. js:autofunction:: test_driver.set_spc_transaction_mode +``` + +### Using test_driver in other browsing contexts ### + +Testdriver can be used in browsing contexts (i.e. windows or frames) +from which it's possible to get a reference to the top-level test +context. There are two basic approaches depending on whether the +context in which testdriver is used is same-origin with the test +context, or different origin. + +For same-origin contexts, the context can be passed directly into the +testdriver API calls. For functions that take an element argument this +is done implicitly using the owner document of the element. For +functions that don't take an element, this is done via an explicit +context argument, which takes a WindowProxy object. + +Example: +``` +let win = window.open("example.html") +win.onload = () => { + await test_driver.set_permission({ name: "background-fetch" }, "denied", win); +} +``` + +```eval_rst +.. js:autofunction:: test_driver.set_test_context +.. js:autofunction:: test_driver.message_test +``` + +For cross-origin cases, passing in the `context` doesn't work because +of limitations in the WebDriver protocol used to implement testdriver +in a cross-browser fashion. Instead one may include the testdriver +scripts directly in the relevant document, and use the +[`test_driver.set_test_context`](#test_driver.set_test_context) API to +specify the browsing context containing testharness.js. Commands are +then sent via `postMessage` to the test context. For convenience there +is also a [`test_driver.message_test`](#test_driver.message_test) +function that can be used to send arbitary messages to the test +window. For example, in an auxillary browsing context: + +```js +test_driver.set_test_context(window.opener) +await test_driver.click(document.getElementsByTagName("button")[0]) +test_driver.message_test("click complete") +``` + +The requirement to have a handle to the test window does mean it's +currently not possible to write tests where such handles can't be +obtained e.g. in the case of `rel=noopener`. + +## Actions ## + +### Markup ### + +To use the [Actions](#Actions) API `testdriver-actions.js` must be +included in the document, in addition to `testdriver.js`: + +```html +<script src="/resources/testdriver-actions.js"></script> +``` + +### API ### + +```eval_rst +.. js:autoclass:: Actions + :members: +``` + + +### Using in other browsing contexts ### + +For the actions API, the context can be set using the `setContext` +method on the builder: + +```js +let actions = new test_driver.Actions() + .setContext(frames[0]) + .keyDown("p") + .keyUp("p"); +await actions.send(); +``` + +Note that if an action uses an element reference, the context will be +derived from that element, and must match any explicitly set +context. Using elements in multiple contexts in a single action chain +is not supported. + +### send_keys + +Usage: `test_driver.send_keys(element, keys)` + * _element_: a DOM Element object + * _keys_: string to send to the element + +This function causes the string _keys_ to be sent to the target +element (an `Element` object), potentially scrolling the document to +make it possible to send keys. It returns a promise that resolves +after the keys have been sent, or rejects if the keys cannot be sent +to the element. + +This works with elements in other frames/windows as long as they are +same-origin with the test, and the test does not depend on the +window.name property remaining unset on the target window. + +Note that if the element that the keys need to be sent to does not have +a unique ID, the document must not have any DOM mutations made +between the function being called and the promise settling. + +To send special keys, one must send the respective key's codepoint. Since this uses the WebDriver protocol, you can find a [list for code points to special keys in the spec](https://w3c.github.io/webdriver/#keyboard-actions). +For example, to send the tab key you would send "\uE004". + +_Note: these special-key codepoints are not necessarily what you would expect. For example, <kbd>Esc</kbd> is the invalid Unicode character `\uE00C`, not the `\u001B` Escape character from ASCII._ + +[activation]: https://html.spec.whatwg.org/multipage/interaction.html#activation + +### set_permission + +Usage: `test_driver.set_permission(descriptor, state, context=null)` + * _descriptor_: a + [PermissionDescriptor](https://w3c.github.io/permissions/#dictdef-permissiondescriptor) + or derived object + * _state_: a + [PermissionState](https://w3c.github.io/permissions/#enumdef-permissionstate) + value + * context: a WindowProxy for the browsing context in which to perform the call + +This function causes permission requests and queries for the status of a +certain permission type (e.g. "push", or "background-fetch") to always +return _state_. It returns a promise that resolves after the permission has +been set to be overridden with _state_. + +Example: + +``` js +await test_driver.set_permission({ name: "background-fetch" }, "denied"); +await test_driver.set_permission({ name: "push", userVisibleOnly: true }, "granted"); +``` |