Permalink
Switch branches/tags
MultipartContent annevk-navigate-to-weird-schemes annevk/EventSource-U+0000 annevk/autofocus annevk/bc-closing annevk/content-length annevk/document-domain annevk/document-open-load-event annevk/document-open-steps-readiness annevk/document-write-reloading annevk/dom-listener-order annevk/encodeInto annevk/fetch-fragments annevk/h1-message-parsing annevk/html-ancestororigins annevk/http-versioning annevk/legacy-pre-activation-behavior-phase annevk/meta-global-annevk annevk/navigate-redirect annevk/navigate-source annevk/opaque-redirect-handling annevk/origin-header annevk/simplify-license annevk/sw-redirect-fragment annevk/template-content-node-document annevk/url-host-parser annevk/window.opener annevk/www-authenticate-parsing annevk/x-frame-options annevk/xhr-h2-statusText annevk/xhr-no-headers-received annevk/xhr-responseurl-with-fragment appveyor ayg/document-named-item bburg-unidentified-keys billing-address-redactions cache-manifest canvas/getContext-second-argument chrome_experimental chromium-export-cl-532595 chromium-export-cl-558917 chromium-export-cl-660842 chromium-export-cl-670844 chromium-export-cl-676883 chromium-export-cl-728365 chromium-export-cl-738353 chromium-export-cl-741361 chromium-export-cl-766373 chromium-export-cl-773321 chromium-export-cl-775179 chromium-export-cl-778160 chromium-export-cl-854092 chromium-export-cl-881121 chromium-export-cl-882906 chromium-export-cl-899411 chromium-export-cl-930542 chromium-export-cl-961719 chromium-export-cl-985959 chromium-export-cl-986593 chromium-export-cl-993812 chromium-export-cl-1013322 chromium-export-cl-1032554 chromium-export-cl-1118750 chromium-export-cl-1128385 chromium-export-cl-1136543 chromium-export-cl-1144133 chromium-export-cl-1146644 chromium-export-cl-1154225 chromium-export-cl-1188018 chromium-export-cl-1188643 chromium-export-cl-1199810 chromium-export-cl-1200863 chromium-export-cl-1212270 chromium-export-cl-1221696 chromium-export-cl-1222913 chromium-export-cl-1249391 chromium-export-cl-1264165 chromium-export-cl-1264520 chromium-export-cl-1270699 chromium-export-cl-1272339 chromium-export-cl-1277666 chromium-export-cl-1288573 chromium-export-cl-1291229 chromium-export-cl-1293050 chromium-export-cl-1293256 chromium-export-cl-1294874 chromium-export-cl-1295618 chromium-export-cl-1306337 chromium-export-cl-1306967 chromium-export-cl-1319616 chromium-export-cl-1322260 chromium-export-cl-1338461 chromium-export-cl-1344261 chromium-export-cl-1345090 chromium-export-cl-1351490 chromium-export-cl-1355923 chromium-export-cl-1356966 chromium-export-cl-1363178 chromium-export-cl-1363971 chromium-export-cl-1365235 chromium-export-cl-1366318 chromium-export-cl-1367725 chromium-export-cl-1367910 chromium-export-cl-1368826 chromium-export-cl-1371186 chromium-export-cl-1371392 chromium-export-cl-1372556 chromium-export-cl-1373430 chromium-export-cl-1373823 chromium-export-cl-1373848 chromium-export-cl-1374113 chromium-export-cl-1374352 chromium-export-cl-1374988 chromium-export-cl-1375714 chromium-export-cl-1376317 chromium-export-cl-1376656 chromium-export-cl-1376713 chromium-export-cl-1377129 chromium-export-cl-1377142 chromium-export-cl-1378684 chromium-export-cl-1378805 chromium-export-cl-1379105 chromium-export-cl-1379752 chromium-export-cl-1379765 chromium-export-cl-1380033 chromium-export-cl-I03bf57a24da3a7479199d04a05c4487342af20ca chromium-export-cl-I53e5b576adebf65ede8ebd1dabe084713ebdf875 chromium-export-cl-I865bb06f8b879e180d4aa6de57010e2609afb8b1 chromium-export-cl-I944ea2ea69447c612c01b9e6f723f110fa28a1f5 chromium-export-cl-I44767f3f65065e9fe0d84a051d4a6b503b439b89 chromium-export-cl-I05157521c98b50fc3816932045a13f6b0eefc9f0 chromium-export-cl-I9846168be36b1de26cc2a508e134c3dd555dafa7 chromium-export-cl-Ib8e35215c5b58721a043087130c9951a56fba3c1 chromium-export-cl-Ib629d1b7e8b86faffc0ddd51888f721df9da4d22 chromium-export-cl-Id7060b7d1292654fc8f23dd72eef629f6a874ef0 chromium-export-cl-Ie2ca10581a3e28974a1eff4e589ea8b62f4cfa62 chromium-export-cl-Ieaa430d9303ab7277440d96b61327b4ec997cd04 chromium-export-cl-Ied400facf474ad18f632c650b636bbbcf725b116 code-of-conduct.md codecov copy_pasta createElement-cereactions csswg-test-pr-561 csswg-test-pr-567 csswg-test-pr-1021 currencysys document-promises drawimage_svg_image_1 dup_shipping_ops epochs/daily epochs/weekly errorfields_warn event-handler-attribute-realm eventtarget-group executorwebdriver ffs-descriptor file_is_error filter-subregion-01 fix-stp-version flaky-test-history foolip/audio-output-securecontext foolip/azure-win10 foolip/fullscreen-catch-throw foolip/getComputedStyle-border foolip/manifest-download-by-tag from-to-element fullscreen-request-vs-exit fullscreen-unloading-steps gecko/sync/upstream/open/1169290/1 gecko/sync/upstream/open/1436763/1 gecko/sync/upstream/open/1437255/1 gecko/1352355 gecko/1383454 gecko/1436763 gecko/1477117 gecko/1487295 gecko/1495601 gecko/1500001 gecko/1513570 gecko/1513920 gecko/1514241 gwhit-flex-changes-2 gwhit-flex-changes hallvors/clipboard-api-2 hallvors/window-opener idlharness-iterable idlharness-member-tostring initial-selection initial-value-selectionDirection jdm-branch-3 jdm-patch-1 jdm-patch-2 jdm-patch-7 jdm-patch-9 jdm-patch-10 jdm-patch-11 js-urls jugglinmike-master-demo jugglinmike-master-revert-switch jugglinmike-mimic-results-collection-2 jugglinmike-mimic-results-collection jugglinmike-testharness-late-tests-locate jugglinmike-wptrunner_tlbc-demo liamquin-patch-1 link-text-css-quirk lint-meta mach_wpt_serve manifest_optimise manifest_performance marcoscaceres-patch-1 marcoscaceres-patch-3-1 marcoscaceres-patch-3 master matchall-is-slow meta_global mkwst/navigation-domain nikos-svg2-marker nonce-hiding payment-request-abort-method-undefined pendingoperation py3-lint py3-make_hosts_file py3-test-handlers readme reftest_fuzzy requestBillingAddress revert-6614-support_firefox_prefixed_implementation_in_mediacapture-fromelementtests revert-9258-host_ip revert-13200-chrome-webdriver-default scripts-between-documents scroll-behavior scrolling-element show_global show_payment sideshowbarker/assert_object_equals speech-api-historical-onmark sync/upstream/open/1420672 sync/upstream/open/1436659 testfiles_space_path tokenlist updateWith-upon-fulfillment-manual user_activation_iframe valid-pmi wdspec_fixup webdriver-update-existing webdriver_script_timeout webidl-legacy-platform-object webmessaging-user-gesture window-open-optional-features woff2-binary-fonts wptreport_surrogates wptrunner-cdp-less-bad-9-demo wptrunner_testdriver wptserve_list_manifest zcorpan/allowed-to-use-snapshot zcorpan/assert-throws-no-name zcorpan/content-before-legend zcorpan/css-transitions-disabled zcorpan/fieldset-accessibility zcorpan/fieldset-border-radius-hittest zcorpan/fieldset-float-and-flex-or-grid zcorpan/fieldset-replaced-element zcorpan/fieldset-translatez-fixup zcorpan/fieldset-webkit-appearance zcorpan/heading-pseudo zcorpan/joint-session-history-timeout zcorpan/single-opt-in zcorpan/update-mediasource-duration zcorpan/webcrypto-any-js zcorpan/window-open-top-vs-screeny
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
139 lines (119 sloc) 6 KB
layout title order
page
idlharness.js API
6

Introduction

idlharness.js automatically generates browser tests for WebIDL interfaces, using the testharness.js framework. To use, first include the following:

<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/WebIDLParser.js></script>
<script src=/resources/idlharness.js></script>

Then you'll need some type of IDLs. Here's some script that can be run on a spec written in HTML, which will grab all the elements with class="idl", concatenate them, and replace the body so you can copy-paste:

var s = "";
[].forEach.call(document.getElementsByClassName("idl"), function(idl) {
  //https://www.w3.org/Bugs/Public/show_bug.cgi?id=14914
  if (!idl.classList.contains("extract"))
  {
    if (s !== "")
    {
      s += "\n\n";
    }
    s += idl.textContent.replace(/ +$/mg, "");
  }
});
document.body.innerHTML = '<pre></pre>';
document.body.firstChild.textContent = s;

Once you have that, put it in your script somehow. The easiest way is to embed it literally in an HTML file with <script type=text/plain> or similar, so that you don't have to do any escaping. Another possibility is to put it in a separate .idl file that's fetched via XHR or similar. Sample usage:

var idl_array = new IdlArray();
idl_array.add_untested_idls("interface Node { readonly attribute DOMString nodeName; };");
idl_array.add_idls("interface Document : Node { readonly attribute DOMString URL; };");
idl_array.add_objects({Document: ["document"]});
idl_array.test();

This tests that window.Document exists and meets all the requirements of WebIDL. It also tests that window.document (the result of evaluating the string "document") has URL and nodeName properties that behave as they should, and otherwise meets WebIDL's requirements for an object whose primary interface is Document. It does not test that window.Node exists, which is what you want if the Node interface is already tested in some other specification's suite and your specification only extends or refers to it. Of course, each IDL string can define many different things, and calls to add_objects() can register many different objects for different interfaces: this is a very simple example.

Public methods of IdlArray

IdlArray objects can be obtained with new IdlArray(). Anything not documented in this section should be considered an implementation detail, and outside callers should not use it.

add_idls(idl_string)

Parses idl_string (throwing on parse error) and adds the results to the IdlArray. All the definitions will be tested when you run test(). If some of the definitions refer to other definitions, those must be present too. For instance, if idl_string says that Document inherits from Node, the Node interface must also have been provided in some call to add_idls() or add_untested_idls().

add_untested_idls(idl_string)

Like add_idls(), but the definitions will not be tested. If an untested interface is added and then extended with a tested partial interface, the members of the partial interface will still be tested. Also, all the members will still be tested for objects added with add_objects(), because you probably want to test that (for instance) window.document has all the properties from Node, not just Document, even if the Node interface itself is tested in a different test suite.

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 [NoInterfaceObject] 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

.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.

test()

Run all tests. This should be called after you've called all other methods to add IDLs and objects.