# JavaScript Tests (testharness.js) JavaScript tests are the correct type of test to write in any situation where you are not specifically interested in the rendering of a page, and where human interaction isn't required; these tests are written in JavaScript using a framework called `testharness.js`. A high-level overview is provided below and more information can be found here: * [testharness.js Documentation](testharness-api.md) — An introduction to the library and a detailed API reference. [The tutorial on writing a testharness.js test](testharness-tutorial) provides a concise guide to writing a test — a good place to start for newcomers to the project. * [testdriver.js Automation](testdriver.md) — Automating end user actions, such as moving or clicking a mouse. See also the [testdriver.js extension tutorial](testdriver-extension-tutorial.md) for adding new commands. * [idlharness.js](idlharness.md) — A library for testing IDL interfaces using `testharness.js`. * [Message Channels](channels.md) - A way to communicate between different globals, including window globals not in the same browsing context group. * [Server features](server-features.md) - Advanced testing features that are commonly used with JavaScript tests. See also the [general guidelines](general-guidelines.md) for all test types. ## Window tests ### Without HTML boilerplate (`.window.js`) Create a JavaScript file whose filename ends in `.window.js` to have the necessary HTML boilerplate generated for you at `.window.html`. I.e., for `test.window.js` the server will ensure `test.window.html` is available. In this JavaScript file you can place one or more tests, as follows: ```js test(() => { // Place assertions and logic here assert_equals(document.characterSet, "UTF-8"); }, "Ensure HTML boilerplate uses UTF-8"); // This is the title of the test ``` If you only need to test a [single thing](testharness-api.html#single-page-tests), you could also use: ```js // META: title=Ensure HTML boilerplate uses UTF-8 setup({ single_test: true }); assert_equals(document.characterSet, "UTF-8"); done(); ``` See [asynchronous (`async_test()`)](testharness-api.html#asynchronous-tests) and [promise tests (`promise_test()`)](testharness-api.html#promise-tests) for more involved setups. ### With HTML boilerplate You need to be a bit more explicit and include the `testharness.js` framework directly as well as an additional file used by implementations: ```html ``` Here too you could avoid the wrapper `test()` function: ```html Ensure UTF-8 declaration is observed ``` In this case the test title is taken from the `title` element. ## Dedicated worker tests (`.worker.js`) Create a JavaScript file that imports `testharness.js` and whose filename ends in `.worker.js` to have the necessary HTML boilerplate generated for you at `.worker.html`. For example, one could write a test for the `FileReaderSync` API by creating a `FileAPI/FileReaderSync.worker.js` as follows: ```js importScripts("/resources/testharness.js"); test(function () { const blob = new Blob(["Hello"]); const fr = new FileReaderSync(); assert_equals(fr.readAsText(blob), "Hello"); }, "FileReaderSync#readAsText."); done(); ``` This test could then be run from `FileAPI/FileReaderSync.worker.html`. (Removing the need for `importScripts()` and `done()` is tracked in [issue #11529](https://github.com/web-platform-tests/wpt/issues/11529).) ## Tests for other or multiple globals (`.any.js`) Tests for features that exist in multiple global scopes can be written in a way that they are automatically run in several scopes. In this case, the test is a JavaScript file with extension `.any.js`, which can use all the usual APIs. By default, the test runs in a window scope and a dedicated worker scope. For example, one could write a test for the `Blob` constructor by creating a `FileAPI/Blob-constructor.any.js` as follows: ```js test(function () { const blob = new Blob(); assert_equals(blob.size, 0); assert_equals(blob.type, ""); assert_false(blob.isClosed); }, "The Blob constructor."); ``` This test could then be run from `FileAPI/Blob-constructor.any.worker.html` as well as `FileAPI/Blob-constructor.any.html`. It is possible to customize the set of scopes with a metadata comment, such as ``` // META: global=sharedworker // ==> would run in the shared worker scope // META: global=window,serviceworker // ==> would only run in the window and service worker scope // META: global=dedicatedworker // ==> would run in the default dedicated worker scope // META: global=dedicatedworker-module // ==> would run in the dedicated worker scope as a module // META: global=worker // ==> would run in the dedicated, shared, and service worker scopes ``` For a test file x.any.js, the available scope keywords are: * `window` (default): to be run at x.any.html * `dedicatedworker` (default): to be run at x.any.worker.html * `dedicatedworker-module` to be run at x.any.worker-module.html * `serviceworker`: to be run at x.any.serviceworker.html (`.https` is implied) * `serviceworker-module`: to be run at x.any.serviceworker-module.html (`.https` is implied) * `sharedworker`: to be run at x.any.sharedworker.html * `sharedworker-module`: to be run at x.any.sharedworker-module.html * `jsshell`: to be run in a JavaScript shell, without access to the DOM (currently only supported in SpiderMonkey, and skipped in wptrunner) * `worker`: shorthand for the dedicated, shared, and service worker scopes * `shadowrealm`: runs the test code in a [ShadowRealm](https://github.com/tc39/proposal-shadowrealm) context hosted in an ordinary Window context; to be run at x.any.shadowrealm.html To check what scope your test is run from, you can use the following methods that will be made available by the framework: self.GLOBAL.isWindow() self.GLOBAL.isWorker() self.GLOBAL.isShadowRealm() Although [the global `done()` function must be explicitly invoked for most dedicated worker tests and shared worker tests](testharness-api.html#determining-when-all-tests-are-complete), it is automatically invoked for tests defined using the "multi-global" pattern. ## Other features of `.window.js`, `.worker.js` and `.any.js` ### Specifying a test title Use `// META: title=This is the title of the test` at the beginning of the resource. ### Including other JavaScript files Use `// META: script=link/to/resource.js` at the beginning of the resource. For example, ``` // META: script=/common/utils.js // META: script=resources/utils.js ``` can be used to include both the global and a local `utils.js` in a test. In window environments, the script will be included using a classic ` ``` With `subsetTestByKey`, the key is given as the first argument, and the query string can include or exclude a key (which will be matched as a regular expression). ```html Testing variants by key ``` ## Table of Contents ```eval_rst .. toctree:: :maxdepth: 1 testharness-api testdriver testdriver-extension-tutorial idlharness ```