1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
|
# 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](#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.
### AbortSignal support ###
[`Test.get_signal`](#Test.get_signal) gives an AbortSignal that is aborted when
the test finishes. This can be useful when dealing with AbortSignal-supported
APIs.
```js
promise_test(t => {
// Throws when the user agent does not support AbortSignal
const signal = t.get_signal();
const event = await new Promise(resolve => {
document.body.addEventListener(resolve, { once: true, signal });
document.body.click();
});
assert_equals(event.type, "click");
}, "");
```
## 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();
}));
```
### Loading test data from JSON files ###
```eval_rst
.. js:autofunction:: fetch_json
```
Loading test data from a JSON file would normally be accomplished by
something like this:
```js
promise_test(() => fetch('resources/my_data.json').then((res) => res.json()).then(runTests));
function runTests(myData) {
/// ...
}
```
However, `fetch()` is not exposed inside ShadowRealm scopes, so if the
test is to be run inside a ShadowRealm, use `fetch_json()` instead:
```js
promise_test(() => fetch_json('resources/my_data.json').then(runTests));
```
### Utility Functions ###
```eval_rst
.. js:autofunction:: format_value
```
## Deprecated APIs ##
```eval_rst
.. js:autofunction:: generate_tests
.. js:autofunction:: on_event
```
|