summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/docs/writing-tests/idlharness.md
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--testing/web-platform/tests/docs/writing-tests/idlharness.md101
1 files changed, 101 insertions, 0 deletions
diff --git a/testing/web-platform/tests/docs/writing-tests/idlharness.md b/testing/web-platform/tests/docs/writing-tests/idlharness.md
new file mode 100644
index 0000000000..e2abce0a48
--- /dev/null
+++ b/testing/web-platform/tests/docs/writing-tests/idlharness.md
@@ -0,0 +1,101 @@
+# IDL Tests (idlharness.js)
+
+## Introduction ##
+
+`idlharness.js` generates tests for Web IDL fragments, using the
+[JavaScript Tests (`testharness.js`)](testharness.md) infrastructure. You typically want to use
+`.any.js` or `.window.js` for this to avoid having to write unnessary boilerplate.
+
+## Adding IDL fragments
+
+Web IDL is automatically scraped from specifications and added to the `/interfaces/` directory. See
+the [README](https://github.com/web-platform-tests/wpt/blob/master/interfaces/README.md) there for
+details.
+
+## Testing IDL fragments
+
+For example, the Fetch API's IDL is tested in
+[`/fetch/api/idlharness.any.js`](https://github.com/web-platform-tests/wpt/blob/master/fetch/api/idlharness.any.js):
+```js
+// META: global=window,worker
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+// META: timeout=long
+
+idl_test(
+ ['fetch'],
+ ['referrer-policy', 'html', 'dom'],
+ idl_array => {
+ idl_array.add_objects({
+ Headers: ["new Headers()"],
+ Request: ["new Request('about:blank')"],
+ Response: ["new Response()"],
+ });
+ if (self.GLOBAL.isWindow()) {
+ idl_array.add_objects({ Window: ['window'] });
+ } else if (self.GLOBAL.isWorker()) {
+ idl_array.add_objects({ WorkerGlobalScope: ['self'] });
+ }
+ }
+);
+```
+Note how it includes `/resources/WebIDLParser.js` and `/resources/idlharness.js` in addition to
+`testharness.js` and `testharnessreport.js` (automatically included due to usage of `.any.js`).
+These are needed to make the `idl_test` function work.
+
+The `idl_test` function takes three arguments:
+
+* _srcs_: a list of specifications whose IDL you want to test. The names here need to match the filenames (excluding the extension) in `/interfaces/`.
+* _deps_: a list of specifications the IDL listed in _srcs_ depends upon. Be careful to list them in the order that the dependencies are revealed.
+* _setup_func_: a function or async function that takes care of creating the various objects that you want to test.
+
+## Methods of `IdlArray` ##
+
+`IdlArray` objects can be obtained through the _setup_func_ argument of `idl_test`. Anything not
+documented in this section should be considered an implementation detail, and outside callers should
+not use it.
+
+### `add_objects(dict)`
+
+_dict_ should be an object whose keys are the names of interfaces or exceptions, and whose values
+are arrays of strings. When an interface or exception is tested, every string registered for it
+with `add_objects()` will be evaluated, and tests will be run on the result to verify that it
+correctly implements that interface or exception. This is the only way to test anything about
+`[LegacyNoInterfaceObject]` interfaces, and there are many tests that can't be run on any interface
+without an object to fiddle with.
+
+The interface has to be the *primary* interface of all the objects provided. For example, don't
+pass `{Node: ["document"]}`, but rather `{Document: ["document"]}`. Assuming the `Document`
+interface was declared to inherit from `Node`, this will automatically test that document implements
+the `Node` interface too.
+
+Warning: methods will be called on any provided objects, in a manner that WebIDL requires be safe.
+For instance, if a method has mandatory arguments, the test suite will try calling it with too few
+arguments to see if it throws an exception. If an implementation incorrectly runs the function
+instead of throwing, this might have side effects, possibly even preventing the test suite from
+running correctly.
+
+### `prevent_multiple_testing(name)`
+
+This is a niche method for use in case you're testing many objects that implement the same
+interfaces, and don't want to retest the same interfaces every single time. For instance, HTML
+defines many interfaces that all inherit from `HTMLElement`, so the HTML test suite has something
+like
+
+```js
+.add_objects({
+ HTMLHtmlElement: ['document.documentElement'],
+ HTMLHeadElement: ['document.head'],
+ HTMLBodyElement: ['document.body'],
+ ...
+})
+```
+
+and so on for dozens of element types. This would mean that it would retest that each and every one
+of those elements implements `HTMLElement`, `Element`, and `Node`, which would be thousands of
+basically redundant tests. The test suite therefore calls `prevent_multiple_testing("HTMLElement")`.
+This means that once one object has been tested to implement `HTMLElement` and its ancestors, no
+other object will be. Thus in the example code above, the harness would test that
+`document.documentElement` correctly implements `HTMLHtmlElement`, `HTMLElement`, `Element`, and
+`Node`; but `document.head` would only be tested for `HTMLHeadElement`, and so on for further
+objects.