summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/docs/writing-tests/testharness-api.md
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/docs/writing-tests/testharness-api.md')
-rw-r--r--testing/web-platform/tests/docs/writing-tests/testharness-api.md821
1 files changed, 821 insertions, 0 deletions
diff --git a/testing/web-platform/tests/docs/writing-tests/testharness-api.md b/testing/web-platform/tests/docs/writing-tests/testharness-api.md
new file mode 100644
index 0000000000..38e6813b1a
--- /dev/null
+++ b/testing/web-platform/tests/docs/writing-tests/testharness-api.md
@@ -0,0 +1,821 @@
+# testharness.js API
+
+```eval_rst
+
+.. contents:: Table of Contents
+ :depth: 3
+ :local:
+ :backlinks: none
+```
+
+testharness.js provides a framework for writing testcases. It is intended to
+provide a convenient API for making common assertions, and to work both
+for testing synchronous and asynchronous DOM features in a way that
+promotes clear, robust, tests.
+
+## Markup ##
+
+The test harness script can be used from HTML or SVG documents and workers.
+
+From an HTML or SVG document, start by importing both `testharness.js` and
+`testharnessreport.js` scripts into the document:
+
+```html
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+```
+
+Refer to the [Web Workers](#web-workers) section for details and an example on
+testing within a web worker.
+
+Within each file one may define one or more tests. Each test is atomic in the
+sense that a single test has a single status (`PASS`/`FAIL`/`TIMEOUT`/`NOTRUN`).
+Within each test one may have a number of asserts. The test fails at the first
+failing assert, and the remainder of the test is (typically) not run.
+
+**Note:** From the point of view of a test harness, each document
+using testharness.js is a single "test" and each js-defined
+[`Test`](#Test) is referred to as a "subtest".
+
+By default tests must be created before the load event fires. For ways
+to create tests after the load event, see [determining when all tests
+are complete](#determining-when-all-tests-are-complete).
+
+### Harness Timeout ###
+
+Execution of tests on a page is subject to a global timeout. By
+default this is 10s, but a test runner may set a timeout multiplier
+which alters the value according to the requirements of the test
+environment (e.g. to give a longer timeout for debug builds).
+
+Long-running tests may opt into a longer timeout by providing a
+`<meta>` element:
+
+```html
+<meta name="timeout" content="long">
+```
+
+By default this increases the timeout to 60s, again subject to the
+timeout multiplier.
+
+Tests which define a large number of subtests may need to use the
+[variant](testharness.html#specifying-test-variants) feature to break
+a single test document into several chunks that complete inside the
+timeout.
+
+Occasionally tests may have a race between the harness timing out and
+a particular test failing; typically when the test waits for some
+event that never occurs. In this case it is possible to use
+[`Test.force_timeout()`](#Test.force_timeout) in place of
+[`assert_unreached()`](#assert_unreached), to immediately fail the
+test but with a status of `TIMEOUT`. This should only be used as a
+last resort when it is not possible to make the test reliable in some
+other way.
+
+## Defining Tests ##
+
+### Synchronous Tests ###
+
+```eval_rst
+.. js:autofunction:: <anonymous>~test
+ :short-name:
+```
+A trivial test for the DOM [`hasFeature()`](https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature)
+method (which is defined to always return true) would be:
+
+```js
+test(function() {
+ assert_true(document.implementation.hasFeature());
+}, "hasFeature() with no arguments")
+```
+
+### Asynchronous Tests ###
+
+Testing asynchronous features is somewhat more complex since the
+result of a test may depend on one or more events or other
+callbacks. The API provided for testing these features is intended to
+be rather low-level but applicable to many situations.
+
+```eval_rst
+.. js:autofunction:: async_test
+
+```
+
+Create a [`Test`](#Test):
+
+```js
+var t = async_test("DOMContentLoaded")
+```
+
+Code is run as part of the test by calling the [`step`](#Test.step)
+method with a function containing the test
+[assertions](#assert-functions):
+
+```js
+document.addEventListener("DOMContentLoaded", function(e) {
+ t.step(function() {
+ assert_true(e.bubbles, "bubbles should be true");
+ });
+});
+```
+
+When all the steps are complete, the [`done`](#Test.done) method must
+be called:
+
+```js
+t.done();
+```
+
+`async_test` can also takes a function as first argument. This
+function is called with the test object as both its `this` object and
+first argument. The above example can be rewritten as:
+
+```js
+async_test(function(t) {
+ document.addEventListener("DOMContentLoaded", function(e) {
+ t.step(function() {
+ assert_true(e.bubbles, "bubbles should be true");
+ });
+ t.done();
+ });
+}, "DOMContentLoaded");
+```
+
+In many cases it is convenient to run a step in response to an event or a
+callback. A convenient method of doing this is through the `step_func` method
+which returns a function that, when called runs a test step. For example:
+
+```js
+document.addEventListener("DOMContentLoaded", t.step_func(function(e) {
+ assert_true(e.bubbles, "bubbles should be true");
+ t.done();
+}));
+```
+
+As a further convenience, the `step_func` that calls
+[`done`](#Test.done) can instead use
+[`step_func_done`](#Test.step_func_done), as follows:
+
+```js
+document.addEventListener("DOMContentLoaded", t.step_func_done(function(e) {
+ assert_true(e.bubbles, "bubbles should be true");
+}));
+```
+
+For asynchronous callbacks that should never execute,
+[`unreached_func`](#Test.unreached_func) can be used. For example:
+
+```js
+document.documentElement.addEventListener("DOMContentLoaded",
+ t.unreached_func("DOMContentLoaded should not be fired on the document element"));
+```
+
+**Note:** the `testharness.js` doesn't impose any scheduling on async
+tests; they run whenever the step functions are invoked. This means
+multiple tests in the same global can be running concurrently and must
+take care not to interfere with each other.
+
+### Promise Tests ###
+
+```eval_rst
+.. js:autofunction:: promise_test
+```
+
+`test_function` is a function that receives a new [Test](#Test) as an
+argument. It must return a promise. The test completes when the
+returned promise settles. The test fails if the returned promise
+rejects.
+
+E.g.:
+
+```js
+function foo() {
+ return Promise.resolve("foo");
+}
+
+promise_test(function() {
+ return foo()
+ .then(function(result) {
+ assert_equals(result, "foo", "foo should return 'foo'");
+ });
+}, "Simple example");
+```
+
+In the example above, `foo()` returns a Promise that resolves with the string
+"foo". The `test_function` passed into `promise_test` invokes `foo` and attaches
+a resolve reaction that verifies the returned value.
+
+Note that in the promise chain constructed in `test_function`
+assertions don't need to be wrapped in [`step`](#Test.step) or
+[`step_func`](#Test.step_func) calls.
+
+It is possible to mix promise tests with callback functions using
+[`step`](#Test.step). However this tends to produce confusing tests;
+it's recommended to convert any asynchronous behaviour into part of
+the promise chain. For example, instead of
+
+```js
+promise_test(t => {
+ return new Promise(resolve => {
+ window.addEventListener("DOMContentLoaded", t.step_func(event => {
+ assert_true(event.bubbles, "bubbles should be true");
+ resolve();
+ }));
+ });
+}, "DOMContentLoaded");
+```
+
+Try,
+
+```js
+promise_test(() => {
+ return new Promise(resolve => {
+ window.addEventListener("DOMContentLoaded", resolve);
+ }).then(event => {
+ assert_true(event.bubbles, "bubbles should be true");
+ });
+}, "DOMContentLoaded");
+```
+
+**Note:** Unlike asynchronous tests, testharness.js queues promise
+tests so the next test won't start running until after the previous
+promise test finishes. [When mixing promise-based logic and async
+steps](https://github.com/web-platform-tests/wpt/pull/17924), the next
+test may begin to execute before the returned promise has settled. Use
+[add_cleanup](#cleanup) to register any necessary cleanup actions such
+as resetting global state that need to happen consistently before the
+next test starts.
+
+To test that a promise rejects with a specified exception see [promise
+rejection].
+
+### Single Page Tests ###
+
+Sometimes, particularly when dealing with asynchronous behaviour,
+having exactly one test per page is desirable, and the overhead of
+wrapping everything in functions for isolation becomes
+burdensome. For these cases `testharness.js` support "single page
+tests".
+
+In order for a test to be interpreted as a single page test, it should set the
+`single_test` [setup option](#setup) to `true`.
+
+```html
+<!doctype html>
+<title>Basic document.body test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <script>
+ setup({ single_test: true });
+ assert_equals(document.body, document.getElementsByTagName("body")[0])
+ done()
+ </script>
+```
+
+The test title for single page tests is always taken from `document.title`.
+
+## Making assertions ##
+
+Functions for making assertions start `assert_`. The full list of
+asserts available is documented in the [asserts](#assert-functions)
+section. The general signature is:
+
+```js
+assert_something(actual, expected, description)
+```
+
+although not all assertions precisely match this pattern
+e.g. [`assert_true`](#assert_true) only takes `actual` and
+`description` as arguments.
+
+The description parameter is used to present more useful error
+messages when a test fails.
+
+When assertions are violated, they throw an
+[`AssertionError`](#AssertionError) exception. This interrupts test
+execution, so subsequent statements are not evaluated. A given test
+can only fail due to one such violation, so if you would like to
+assert multiple behaviors independently, you should use multiple
+tests.
+
+**Note:** Unless the test is a [single page test](#single-page-tests),
+assert functions must only be called in the context of a
+[`Test`](#Test).
+
+### Optional Features ###
+
+If a test depends on a specification or specification feature that is
+OPTIONAL (in the [RFC 2119
+sense](https://tools.ietf.org/html/rfc2119)),
+[`assert_implements_optional`](#assert_implements_optional) can be
+used to indicate that failing the test does not mean violating a web
+standard. For example:
+
+```js
+async_test((t) => {
+ const video = document.createElement("video");
+ assert_implements_optional(video.canPlayType("video/webm"));
+ video.src = "multitrack.webm";
+ // test something specific to multiple audio tracks in a WebM container
+ t.done();
+}, "WebM with multiple audio tracks");
+```
+
+A failing [`assert_implements_optional`](#assert_implements_optional)
+call is reported as a status of `PRECONDITION_FAILED` for the
+subtest. This unusual status code is a legacy leftover; see the [RFC
+that introduced
+`assert_implements_optional`](https://github.com/web-platform-tests/rfcs/pull/48).
+
+[`assert_implements_optional`](#assert_implements_optional) can also
+be used during [test setup](#setup). For example:
+
+```js
+setup(() => {
+ assert_implements_optional("optionalfeature" in document.body,
+ "'optionalfeature' event supported");
+});
+async_test(() => { /* test #1 waiting for "optionalfeature" event */ });
+async_test(() => { /* test #2 waiting for "optionalfeature" event */ });
+```
+
+A failing [`assert_implements_optional`](#assert_implements_optional)
+during setup is reported as a status of `PRECONDITION_FAILED` for the
+test, and the subtests will not run.
+
+See also the `.optional` [file name convention](file-names.md), which may be
+preferable if the entire test is optional.
+
+## Testing Across Globals ##
+
+### Consolidating tests from other documents ###
+
+```eval_rst
+.. js::autofunction fetch_tests_from_window
+```
+
+**Note:** By default any markup file referencing `testharness.js` will
+be detected as a test. To avoid this, it must be put in a `support`
+directory.
+
+The current test suite will not report completion until all fetched
+tests are complete, and errors in the child contexts will result in
+failures for the suite in the current context.
+
+Here's an example that uses `window.open`.
+
+`support/child.html`:
+
+```html
+<!DOCTYPE html>
+<html>
+<title>Child context test(s)</title>
+<head>
+ <script src="/resources/testharness.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script>
+ test(function(t) {
+ assert_true(true, "true is true");
+ }, "Simple test");
+ </script>
+</body>
+</html>
+```
+
+`test.html`:
+
+```html
+<!DOCTYPE html>
+<html>
+<title>Primary test context</title>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script>
+ var child_window = window.open("support/child.html");
+ fetch_tests_from_window(child_window);
+ </script>
+</body>
+</html>
+```
+
+### Web Workers ###
+
+```eval_rst
+.. js:autofunction fetch_tests_from_worker
+```
+
+The `testharness.js` script can be used from within [dedicated workers, shared
+workers](https://html.spec.whatwg.org/multipage/workers.html) and [service
+workers](https://w3c.github.io/ServiceWorker/).
+
+Testing from a worker script is different from testing from an HTML document in
+several ways:
+
+* Workers have no reporting capability since they are running in the background.
+ Hence they rely on `testharness.js` running in a companion client HTML document
+ for reporting.
+
+* Shared and service workers do not have a unique client document
+ since there could be more than one document that communicates with
+ these workers. So a client document needs to explicitly connect to a
+ worker and fetch test results from it using
+ [`fetch_tests_from_worker`](#fetch_tests_from_worker). This is true
+ even for a dedicated worker. Once connected, the individual tests
+ running in the worker (or those that have already run to completion)
+ will be automatically reflected in the client document.
+
+* The client document controls the timeout of the tests. All worker
+ scripts act as if they were started with the
+ [`explicit_timeout`](#setup) option.
+
+* Dedicated and shared workers don't have an equivalent of an `onload`
+ event. Thus the test harness has no way to know when all tests have
+ completed (see [Determining when all tests are
+ complete](#determining-when-all-tests-are-complete)). So these
+ worker tests behave as if they were started with the
+ [`explicit_done`](#setup) option. Service workers depend on the
+ [oninstall](https://w3c.github.io/ServiceWorker/#service-worker-global-scope-install-event)
+ event and don't require an explicit [`done`](#done) call.
+
+Here's an example that uses a dedicated worker.
+
+`worker.js`:
+
+```js
+importScripts("/resources/testharness.js");
+
+test(function(t) {
+ assert_true(true, "true is true");
+}, "Simple test");
+
+// done() is needed because the testharness is running as if explicit_done
+// was specified.
+done();
+```
+
+`test.html`:
+
+```html
+<!DOCTYPE html>
+<title>Simple test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+fetch_tests_from_worker(new Worker("worker.js"));
+
+</script>
+```
+
+
+`fetch_tests_from_worker` returns a promise that resolves once all the remote
+tests have completed. This is useful if you're importing tests from multiple
+workers and want to ensure they run in series:
+
+```js
+(async function() {
+ await fetch_tests_from_worker(new Worker("worker-1.js"));
+ await fetch_tests_from_worker(new Worker("worker-2.js"));
+})();
+```
+
+## Cleanup ##
+
+Occasionally tests may create state that will persist beyond the test
+itself. In order to ensure that tests are independent, such state
+should be cleaned up once the test has a result. This can be achieved
+by adding cleanup callbacks to the test. Such callbacks are registered
+using the [`add_cleanup`](#Test.add_cleanup) method. All registered
+callbacks will be run as soon as the test result is known. For
+example:
+
+```js
+ test(function() {
+ var element = document.createElement("div");
+ element.setAttribute("id", "null");
+ document.body.appendChild(element);
+ this.add_cleanup(function() { document.body.removeChild(element) });
+ assert_equals(document.getElementById(null), element);
+ }, "Calling document.getElementById with a null argument.");
+```
+
+If the test was created using the [`promise_test`](#promise_test) API,
+then cleanup functions may optionally return a Promise and delay the
+completion of the test until all cleanup promises have settled.
+
+All callbacks will be invoked synchronously; tests that require more
+complex cleanup behavior should manage execution order explicitly. If
+any of the eventual values are rejected, the test runner will report
+an error.
+
+## Timers in Tests ##
+
+In general the use of timers (i.e. `setTimeout`) in tests is
+discouraged because this is an observed source of instability on test
+running in CI. In particular if a test should fail when
+something doesn't happen, it is good practice to simply let the test
+run to the full timeout rather than trying to guess an appropriate
+shorter timeout to use.
+
+In other cases it may be necessary to use a timeout (e.g., for a test
+that only passes if some event is *not* fired). In this case it is
+*not* permitted to use the standard `setTimeout` function. Instead use
+either [`Test.step_wait()`](#Test.step_wait),
+[`Test.step_wait_func()`](#Test.step_wait_func), or
+[`Test.step_timeout()`](#Test.step_timeout). [`Test.step_wait()`](#Test.step_wait)
+and [`Test.step_wait_func()`](#Test.step_wait_func) are preferred
+when there's a specific condition that needs to be met for the test to
+proceed. [`Test.step_timeout()`](#Test.step_timeout) is preferred in other cases.
+
+Note that timeouts generally need to be a few seconds long in order to
+produce stable results in all test environments.
+
+For [single page tests](#single-page-tests),
+[step_timeout](#step_timeout) is also available as a global function.
+
+```eval_rst
+
+.. js:autofunction:: <anonymous>~step_timeout
+ :short-name:
+```
+
+## Harness Configuration ###
+
+### Setup ###
+
+<!-- sphinx-js doesn't support documenting types so we have to copy in
+ the SettingsObject documentation by hand -->
+
+```eval_rst
+.. js:autofunction:: setup
+
+.. js:autofunction:: promise_setup
+
+:SettingsObject:
+
+ :Properties:
+ - **single_test** (*bool*) - Use the single-page-test mode. In this
+ mode the Document represents a single :js:class:`Test`. Asserts may be
+ used directly without requiring :js:func:`Test.step` or similar wrappers,
+ and any exceptions set the status of the test rather than the status
+ of the harness.
+
+ - **allow_uncaught_exception** (*bool*) - don't treat an
+ uncaught exception as an error; needed when e.g. testing the
+ `window.onerror` handler.
+
+ - **explicit_done** (*bool*) - Wait for a call to :js:func:`done`
+ before declaring all tests complete (this is always true for
+ single-page tests).
+
+ - **hide_test_state** (*bool*) - hide the test state output while
+ the test is running; This is helpful when the output of the test state
+ may interfere the test results.
+
+ - **explicit_timeout** (*bool*) - disable file timeout; only
+ stop waiting for results when the :js:func:`timeout` function is
+ called. This should typically only be set for manual tests, or
+ by a test runner that provides its own timeout mechanism.
+
+ - **timeout_multiplier** (*Number*) - Multiplier to apply to
+ timeouts. This should only be set by a test runner.
+
+ - **output** (*bool*) - (default: `true`) Whether to output a table
+ containing a summary of test results. This should typically
+ only be set by a test runner, and is typically set to false
+ for performance reasons when running in CI.
+
+ - **output_document** (*Document*) output_document - The document to which
+ results should be logged. By default this is the current
+ document but could be an ancestor document in some cases e.g. a
+ SVG test loaded in an HTML wrapper
+
+ - **debug** (*bool*) - (default: `false`) Whether to output
+ additional debugging information such as a list of
+ asserts. This should typically only be set by a test runner.
+```
+
+### Output ###
+
+If the file containing the tests is a HTML file, a table containing
+the test results will be added to the document after all tests have
+run. By default this will be added to a `div` element with `id=log` if
+it exists, or a new `div` element appended to `document.body` if it
+does not. This can be suppressed by setting the [`output`](#setup)
+setting to `false`.
+
+If [`output`](#setup) is `true`, the test will, by default, report
+progress during execution. In some cases this progress report will
+invalidate the test. In this case the test should set the
+[`hide_test_state`](#setup) setting to `true`.
+
+
+### Determining when all tests are complete ###
+
+By default, tests running in a `WindowGlobalScope`, which are not
+configured as a [single page test](#single-page-tests) the test
+harness will assume there are no more results to come when:
+
+ 1. There are no `Test` objects that have been created but not completed
+ 2. The load event on the document has fired
+
+For single page tests, or when the `explicit_done` property has been
+set in the [setup](#setup), the [`done`](#done) function must be used.
+
+```eval_rst
+
+.. js:autofunction:: <anonymous>~done
+ :short-name:
+.. js:autofunction:: <anonymous>~timeout
+ :short-name:
+```
+
+Dedicated and shared workers don't have an event that corresponds to
+the `load` event in a document. Therefore these worker tests always
+behave as if the `explicit_done` property is set to true (unless they
+are defined using [the "multi-global"
+pattern](testharness.html#multi-global-tests)). Service workers depend
+on the
+[install](https://w3c.github.io/ServiceWorker/#service-worker-global-scope-install-event)
+event which is fired following the completion of [running the
+worker](https://html.spec.whatwg.org/multipage/workers.html#run-a-worker).
+
+## Reporting API ##
+
+### Callbacks ###
+
+The framework provides callbacks corresponding to 4 events:
+
+ * `start` - triggered when the first Test is created
+ * `test_state` - triggered when a test state changes
+ * `result` - triggered when a test result is received
+ * `complete` - triggered when all results are received
+
+```eval_rst
+.. js:autofunction:: add_start_callback
+.. js:autofunction:: add_test_state_callback
+.. js:autofunction:: add_result_callback
+.. js:autofunction:: add_completion_callback
+.. js:autoclass:: TestsStatus
+ :members:
+.. js:autoclass:: AssertRecord
+ :members:
+```
+
+### External API ###
+
+In order to collect the results of multiple pages containing tests, the test
+harness will, when loaded in a nested browsing context, attempt to call
+certain functions in each ancestor and opener browsing context:
+
+ * start - `start_callback`
+ * test\_state - `test_state_callback`
+ * result - `result_callback`
+ * complete - `completion_callback`
+
+These are given the same arguments as the corresponding internal callbacks
+described above.
+
+The test harness will also send messages using cross-document
+messaging to each ancestor and opener browsing context. Since it uses the
+wildcard keyword (\*), cross-origin communication is enabled and script on
+different origins can collect the results.
+
+This API follows similar conventions as those described above only slightly
+modified to accommodate message event API. Each message is sent by the harness
+is passed a single vanilla object, available as the `data` property of the event
+object. These objects are structured as follows:
+
+ * start - `{ type: "start" }`
+ * test\_state - `{ type: "test_state", test: Test }`
+ * result - `{ type: "result", test: Test }`
+ * complete - `{ type: "complete", tests: [Test, ...], status: TestsStatus }`
+
+
+## Assert Functions ##
+
+```eval_rst
+.. js:autofunction:: assert_true
+.. js:autofunction:: assert_false
+.. js:autofunction:: assert_equals
+.. js:autofunction:: assert_not_equals
+.. js:autofunction:: assert_in_array
+.. js:autofunction:: assert_array_equals
+.. js:autofunction:: assert_approx_equals
+.. js:autofunction:: assert_array_approx_equals
+.. js:autofunction:: assert_less_than
+.. js:autofunction:: assert_greater_than
+.. js:autofunction:: assert_between_exclusive
+.. js:autofunction:: assert_less_than_equal
+.. js:autofunction:: assert_greater_than_equal
+.. js:autofunction:: assert_between_inclusive
+.. js:autofunction:: assert_regexp_match
+.. js:autofunction:: assert_class_string
+.. js:autofunction:: assert_own_property
+.. js:autofunction:: assert_not_own_property
+.. js:autofunction:: assert_inherits
+.. js:autofunction:: assert_idl_attribute
+.. js:autofunction:: assert_readonly
+.. js:autofunction:: assert_throws_dom
+.. js:autofunction:: assert_throws_js
+.. js:autofunction:: assert_throws_exactly
+.. js:autofunction:: assert_implements
+.. js:autofunction:: assert_implements_optional
+.. js:autofunction:: assert_unreached
+.. js:autofunction:: assert_any
+
+```
+
+Assertions fail by throwing an `AssertionError`:
+
+```eval_rst
+.. js:autoclass:: AssertionError
+```
+
+### Promise Rejection ###
+
+```eval_rst
+.. js:autofunction:: promise_rejects_dom
+.. js:autofunction:: promise_rejects_js
+.. js:autofunction:: promise_rejects_exactly
+```
+
+`promise_rejects_dom`, `promise_rejects_js`, and `promise_rejects_exactly` can
+be used to test Promises that need to reject.
+
+Here's an example where the `bar()` function returns a Promise that rejects
+with a TypeError:
+
+```js
+function bar() {
+ return Promise.reject(new TypeError());
+}
+
+promise_test(function(t) {
+ return promise_rejects_js(t, TypeError, bar());
+}, "Another example");
+```
+
+## Test Objects ##
+
+```eval_rst
+
+.. js:autoclass:: Test
+ :members:
+```
+
+## Helpers ##
+
+### Waiting for events ###
+
+```eval_rst
+.. js:autoclass:: EventWatcher
+ :members:
+```
+
+Here's an example of how to use `EventWatcher`:
+
+```js
+var t = async_test("Event order on animation start");
+
+var animation = watchedNode.getAnimations()[0];
+var eventWatcher = new EventWatcher(t, watchedNode, ['animationstart',
+ 'animationiteration',
+ 'animationend']);
+
+eventWatcher.wait_for('animationstart').then(t.step_func(function() {
+ assertExpectedStateAtStartOfAnimation();
+ animation.currentTime = END_TIME; // skip to end
+ // We expect two animationiteration events then an animationend event on
+ // skipping to the end of the animation.
+ return eventWatcher.wait_for(['animationiteration',
+ 'animationiteration',
+ 'animationend']);
+})).then(t.step_func(function() {
+ assertExpectedStateAtEndOfAnimation();
+ t.done();
+}));
+```
+
+### Utility Functions ###
+
+```eval_rst
+.. js:autofunction:: format_value
+```
+
+## Deprecated APIs ##
+
+```eval_rst
+.. js:autofunction:: generate_tests
+.. js:autofunction:: on_event
+```
+
+