Switch branches/tags
merge_pr_14056 merge_pr_14053 merge_pr_14052 merge_pr_14051 merge_pr_14050 merge_pr_14049 merge_pr_14045 merge_pr_14042 merge_pr_14040 merge_pr_14039 merge_pr_14038 merge_pr_14035 merge_pr_14032 merge_pr_14031 merge_pr_14027 merge_pr_14024 merge_pr_14023 merge_pr_14021 merge_pr_14020 merge_pr_14019 merge_pr_14018 merge_pr_14017 merge_pr_14016 merge_pr_14015 merge_pr_14011 merge_pr_14010 merge_pr_14009 merge_pr_14008 merge_pr_14007 merge_pr_14006 merge_pr_14005 merge_pr_14004 merge_pr_14001 merge_pr_14000 merge_pr_13997 merge_pr_13996 merge_pr_13995 merge_pr_13994 merge_pr_13993 merge_pr_13992 merge_pr_13991 merge_pr_13988 merge_pr_13987 merge_pr_13986 merge_pr_13985 merge_pr_13983 merge_pr_13981 merge_pr_13980 merge_pr_13979 merge_pr_13978 merge_pr_13977 merge_pr_13974 merge_pr_13969 merge_pr_13968 merge_pr_13967 merge_pr_13962 merge_pr_13961 merge_pr_13960 merge_pr_13959 merge_pr_13958 merge_pr_13957 merge_pr_13955 merge_pr_13954 merge_pr_13953 merge_pr_13952 merge_pr_13951 merge_pr_13950 merge_pr_13949 merge_pr_13948 merge_pr_13947 merge_pr_13946 merge_pr_13945 merge_pr_13944 merge_pr_13943 merge_pr_13942 merge_pr_13941 merge_pr_13940 merge_pr_13939 merge_pr_13938 merge_pr_13935 merge_pr_13934 merge_pr_13933 merge_pr_13932 merge_pr_13931 merge_pr_13930 merge_pr_13929 merge_pr_13927 merge_pr_13925 merge_pr_13921 merge_pr_13920 merge_pr_13919 merge_pr_13918 merge_pr_13917 merge_pr_13916 merge_pr_13915 merge_pr_13914 merge_pr_13912 merge_pr_13911 merge_pr_13910 merge_pr_13908
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
206 lines (159 sloc) 6.96 KB
layout title order
testharness.js Tests

testharness.js 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. It is documented in two sections:

  • [testharness.js Documentation][testharness-api] — An introduction to the library and a detailed API reference.

  • [idlharness.js Documentation][idlharness] — A library for testing IDL interfaces using testharness.js.

See [server features][] for advanced testing features that are commonly used with testharness.js. See also the [general guidelines][] for all test types.


A test file can have multiple variants by including meta elements, for example:

<meta name="variant" content="">
<meta name="variant" content="?wss">

The test can then do different things based on the URL.

There are two utility scripts in that work well together with variants, /common /subset-tests.js and /common/subset-tests-by- key.js, where a test that would otherwise have too many tests to be useful can be split up in ranges of subtests. For example:

<!doctype html>
<title>Testing variants</title>
<meta name="variant" content="?1-1000">
<meta name="variant" content="?1001-2000">
<meta name="variant" content="?2001-last">
<script src="/resources/testharness.js">
<script src="/resources/testharnessreport.js">
<script src="/common/subset-tests.js">
 const tests = [
                 { fn: t => { ... }, name: "..." },
                 ... lots of tests ...
 for (const test of tests) {
   subsetTest(async_test, test.fn,;

With subsetTestByKey, the key is given as the first argument, and the query string can include or exclude a key (will be matched as a regular expression).

<!doctype html>
<title>Testing variants by key</title>
<meta name="variant" content="?include=Foo">
<meta name="variant" content="?include=Bar">
<meta name="variant" content="?exclude=(Foo|Bar)">
<script src="/resources/testharness.js">
<script src="/resources/testharnessreport.js">
<script src="/common/subset-tests-by-key.js">
   subsetTestByKey("Foo", async_test, () => { ... }, "Testing foo");

Auto-generated test boilerplate

While most JavaScript tests require a certain amount of HTML boilerplate to include the test library, etc., tests which are expressible purely in script (e.g. tests for workers) can have all the needed HTML and script boilerplate auto-generated.

Standalone window tests

Tests that only require a script file running in window scope can use standalone window tests. In this case the test is a javascript file with the extension .window.js. This is sourced from a generated document which sources testharness.js, testharnessreport.js and the test script. For a source script with the name example.window.js, the corresponding test resource will be example.window.html.

Standalone workers tests

Tests that only require assertions in a dedicated worker scope can use standalone workers tests. In this case, the test is a JavaScript file with extension .worker.js that imports testharness.js. The test can then use all the usual APIs, and can be run from the path to the JavaScript file with the .js removed.

For example, one could write a test for the FileReaderSync API by creating a FileAPI/FileReaderSync.worker.js as follows:

test(function () {
    var blob = new Blob(["Hello"]);
    var fr = new FileReaderSync();
    assert_equals(fr.readAsText(blob), "Hello");
}, "FileReaderSync#readAsText.");

This test could then be run from FileAPI/FileReaderSync.worker.html.

Multi-global tests

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:

test(function () {
    var blob = new Blob();
    assert_equals(blob.size, 0);
    assert_equals(blob.type, "");
}, "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 default window and dedicated worker scopes,
//           as well as the shared worker scope
// META: global=!default,serviceworker
//       ==> would only run in the service worker scope
// META: global=!window
//       ==> would run in the default dedicated worker scope, but not the
//           window scope
// META: global=worker
//       ==> would run in the default window scope, as well as 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
  • serviceworker: to be run at x.https.any.serviceworker.html
  • sharedworker: to be run at x.any.sharedworker.html
  • default: shorthand for the default scopes
  • worker: shorthand for the dedicated, shared and service worker scopes

To check if your test is run from a window or worker you can use the following two methods that will be made available by the framework:


Specifying a test title in auto-generated boilerplate tests

Use // META: title=This is the title of the test at the beginning of the resource.

Including other JavaScript resources in auto-generated boilerplate tests

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.

Specifying a timeout of long in auto-generated boilerplate tests

Use // META: timeout=long at the beginning of the resource.

Specifying test variants in auto-generated boilerplate tests

Use // META: variant=url-suffix at the beginning of the resource. For example,

// META: variant=
// META: variant=?wss

[general guidelines]: {{ site.baseurl }}{% link _writing-tests/ %} [testharness-api]: {{ site.baseurl }}{% link _writing-tests/ %} [idlharness]: {{ site.baseurl }}{% link _writing-tests/ %} [server features]: {{ site.baseurl }}{% link _writing-tests/ %}