Auto merge of #12408 - servo:wpt-20160712, r=Ms2ger

Update web-platform-tests to revision 53f3408ffe1fd0e56a37aff4aaf1fa8441c41d6d

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12408)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-07-12 02:47:14 -07:00 committed by GitHub
commit f0c3543f53
59 changed files with 2247 additions and 1071 deletions

View file

@ -3,9 +3,6 @@
[URL interface: operation createFor(Blob)]
expected: FAIL
[FileReaderSync interface: existence and properties of interface object]
expected: FAIL
[FileReaderSync interface object length]
expected: FAIL

View file

@ -60,3 +60,30 @@
[FileReaderSync interface object name]
expected: FAIL
[Window interface: existence and properties of interface object]
expected: FAIL
[ArrayBuffer interface: existence and properties of interface object]
expected: FAIL
[URL interface: existence and properties of interface object]
expected: FAIL
[EventTarget interface: existence and properties of interface object]
expected: FAIL
[Event interface: existence and properties of interface object]
expected: FAIL
[Blob interface: existence and properties of interface object]
expected: FAIL
[File interface: existence and properties of interface object]
expected: FAIL
[FileList interface: existence and properties of interface object]
expected: FAIL
[FileReader interface: existence and properties of interface object]
expected: FAIL

View file

@ -97,6 +97,14 @@
"path": "XMLHttpRequest/send-authentication-prompt-manual.htm",
"url": "/XMLHttpRequest/send-authentication-prompt-manual.htm"
},
{
"path": "annotation-model/examples/example1-manual.html",
"url": "/annotation-model/examples/example1-manual.html"
},
{
"path": "annotation-model/examples/example2-manual.html",
"url": "/annotation-model/examples/example2-manual.html"
},
{
"path": "battery-status/battery-charging-manual.html",
"url": "/battery-status/battery-charging-manual.html"
@ -957,6 +965,10 @@
"path": "pointerevents/pointerevent_lostpointercapture_is_first-manual.html",
"url": "/pointerevents/pointerevent_lostpointercapture_is_first-manual.html"
},
{
"path": "pointerevents/pointerevent_multiple_primary_pointers_boundary_events-manual.html",
"url": "/pointerevents/pointerevent_multiple_primary_pointers_boundary_events-manual.html"
},
{
"path": "pointerevents/pointerevent_pointerId_scope-manual.html",
"url": "/pointerevents/pointerevent_pointerId_scope-manual.html"
@ -15825,6 +15837,14 @@
"path": "fetch/api/basic/request-headers.html",
"url": "/fetch/api/basic/request-headers.html"
},
{
"path": "fetch/api/basic/response-url-worker.html",
"url": "/fetch/api/basic/response-url-worker.html"
},
{
"path": "fetch/api/basic/response-url.html",
"url": "/fetch/api/basic/response-url.html"
},
{
"path": "fetch/api/basic/scheme-about-worker.html",
"url": "/fetch/api/basic/scheme-about-worker.html"
@ -19277,6 +19297,10 @@
"path": "html/semantics/embedded-content/the-img-element/img.complete.html",
"url": "/html/semantics/embedded-content/the-img-element/img.complete.html"
},
{
"path": "html/semantics/embedded-content/the-img-element/invalid-src.html",
"url": "/html/semantics/embedded-content/the-img-element/invalid-src.html"
},
{
"path": "html/semantics/embedded-content/the-img-element/relevant-mutations.html",
"url": "/html/semantics/embedded-content/the-img-element/relevant-mutations.html"
@ -19901,6 +19925,10 @@
"path": "html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml",
"url": "/html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml"
},
{
"path": "html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html",
"url": "/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html"
},
{
"path": "html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html",
"url": "/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html"
@ -23057,6 +23085,14 @@
"path": "pointerevents/pointerevent_pointermove-on-chorded-mouse-button.html",
"url": "/pointerevents/pointerevent_pointermove-on-chorded-mouse-button.html"
},
{
"path": "pointerevents/pointerevent_suppress_compat_events_on_click.html",
"url": "/pointerevents/pointerevent_suppress_compat_events_on_click.html"
},
{
"path": "pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html",
"url": "/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html"
},
{
"path": "pointerevents/pointerevent_touch-action-illegal.html",
"url": "/pointerevents/pointerevent_touch-action-illegal.html"
@ -29765,22 +29801,6 @@
"path": "shadow-dom/untriaged/user-interaction/editing/inheritance-of-content-editable-001.html",
"url": "/shadow-dom/untriaged/user-interaction/editing/inheritance-of-content-editable-001.html"
},
{
"path": "shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html",
"url": "/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html"
},
{
"path": "shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html",
"url": "/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html"
},
{
"path": "shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html",
"url": "/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html"
},
{
"path": "shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html",
"url": "/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html"
},
{
"path": "shadow-dom/untriaged/user-interaction/ranges-and-selections/test-001.html",
"url": "/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-001.html"
@ -37183,22 +37203,7 @@
"local_changes": {
"deleted": [],
"deleted_reftests": {},
"items": {
"testharness": {
"html/semantics/embedded-content/the-img-element/invalid-src.html": [
{
"path": "html/semantics/embedded-content/the-img-element/invalid-src.html",
"url": "/html/semantics/embedded-content/the-img-element/invalid-src.html"
}
],
"html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html": [
{
"path": "html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html",
"url": "/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html"
}
]
}
},
"items": {},
"reftest_nodes": {}
},
"reftest_nodes": {
@ -43539,7 +43544,7 @@
}
]
},
"rev": "1e42017386ce1eaeed4925fb8bc7f5417752019a",
"rev": "53f3408ffe1fd0e56a37aff4aaf1fa8441c41d6d",
"url_base": "/",
"version": 3
}

View file

@ -162,3 +162,9 @@
[SubtleCrypto interface: calling unwrapKey(KeyFormat,BufferSource,CryptoKey,AlgorithmIdentifier,AlgorithmIdentifier,boolean,[object Object\]) on crypto.subtle with too few arguments must throw TypeError]
expected: FAIL
[Window interface: existence and properties of interface object]
expected: FAIL
[ArrayBuffer interface: existence and properties of interface object]
expected: FAIL

View file

@ -6114,9 +6114,6 @@
[DedicatedWorkerGlobalScope interface: attribute onmessage]
expected: FAIL
[SharedWorkerGlobalScope interface: existence and properties of interface object]
expected: FAIL
[SharedWorkerGlobalScope interface object length]
expected: FAIL
@ -9624,3 +9621,78 @@
[HTMLElement interface: document.createElement("noscript") must inherit property "onsort" with the proper type (80)]
expected: FAIL
[TrackEvent must be primary interface of new TrackEvent("addtrack", {track:document.createElement("track").track})]
expected: FAIL
[Stringification of new TrackEvent("addtrack", {track:document.createElement("track").track})]
expected: FAIL
[TrackEvent interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "track" with the proper type (0)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "type" with the proper type (0)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "target" with the proper type (1)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "currentTarget" with the proper type (2)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "NONE" with the proper type (3)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "CAPTURING_PHASE" with the proper type (4)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "AT_TARGET" with the proper type (5)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "BUBBLING_PHASE" with the proper type (6)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "eventPhase" with the proper type (7)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "stopPropagation" with the proper type (8)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "stopImmediatePropagation" with the proper type (9)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "bubbles" with the proper type (10)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "cancelable" with the proper type (11)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "preventDefault" with the proper type (12)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "defaultPrevented" with the proper type (13)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must have own property "isTrusted"]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "timeStamp" with the proper type (15)]
expected: FAIL
[Event interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "initEvent" with the proper type (16)]
expected: FAIL
[Event interface: calling initEvent(DOMString,boolean,boolean) on new TrackEvent("addtrack", {track:document.createElement("track").track}) with too few arguments must throw TypeError]
expected: FAIL
[WorkerGlobalScope interface: existence and properties of interface object]
expected: FAIL
[DedicatedWorkerGlobalScope interface: existence and properties of interface object]
expected: FAIL
[WorkerNavigator interface: existence and properties of interface object]
expected: FAIL
[WorkerLocation interface: existence and properties of interface object]
expected: FAIL

View file

@ -1 +1 @@
87c77725279ba3f1b612e27fccf353c81eae17b8
9b01a4cc97af29b81f92a403992d0498d4290f4f

View file

@ -63,3 +63,18 @@
[WorkerNavigator interface: self.navigator must inherit property "onLine" with the proper type (8)]
expected: FAIL
[EventTarget interface: existence and properties of interface object]
expected: FAIL
[WorkerGlobalScope interface: existence and properties of interface object]
expected: FAIL
[DedicatedWorkerGlobalScope interface: existence and properties of interface object]
expected: FAIL
[WorkerNavigator interface: existence and properties of interface object]
expected: FAIL
[WorkerLocation interface: existence and properties of interface object]
expected: FAIL

View file

@ -79,3 +79,13 @@ partial interface URL {
static void revokeObjectURL(DOMString url);
};
[Constructor, Exposed=Worker]
interface FileReaderSync {
// Synchronously return strings
ArrayBuffer readAsArrayBuffer(Blob blob);
DOMString readAsText(Blob blob, optional DOMString label);
DOMString readAsDataURL(Blob blob);
};

View file

@ -18,20 +18,7 @@ request.onload = function() {
idl_array.add_untested_idls("[TreatNonCallableAsNull] callback EventHandlerNonNull = any (Event event);");
idl_array.add_untested_idls("typedef EventHandlerNonNull? EventHandler;");
var worker_idls =
'[Constructor, Exposed=Worker]\n' +
'interface FileReaderSync {\n' +
'\n' +
' // Synchronously return strings\n' +
'\n' +
' ArrayBuffer readAsArrayBuffer(Blob blob);\n' +
' DOMString readAsText(Blob blob, optional DOMString label);\n' +
' DOMString readAsDataURL(Blob blob);\n' +
'};';
idl_array.add_idls(idls);
idl_array.add_idls(worker_idls);
idl_array.add_objects({
Blob: ['new Blob(["TEST"])'],

View file

@ -108,7 +108,7 @@ function run_test() {
.then(function(result) {
assert_unreached("digest() should not have worked for " + alg + ":" + size);
}, function(err) {
assert_equals(err.message, "OperationError", "Bad algorithm name should cause OperationError")
assert_equals(err.name, "NotSupportedError", "Bad algorithm name should cause NotSupportedError")
});
return promise;

View file

@ -0,0 +1,10 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

View file

@ -0,0 +1,370 @@
Annotation-model: Guidelines for Contributing Tests
===================================================
This document describes the method people should use for authoring tests and
integrating them into the repository. Anyone is welcome to submit new tests to
this collection. If you do, please create the tests following the guidelines
below. Then submit them as a pull request so they can be evaluated
Structure
---------
Tests are organized by major section of the Annotation Model specification. The
folders associated with these are:
* annotations
* bodiesTargets
* collections
* specificResources
* selectors
* states
Within these folders, special files ending with the suffix ".test" provide the source
for the test as a set of declarative assertions about the required shape of the conforming
JSON object. These files are transformed using a test generation tool into ".html" files
that are then accessed by the Web Platform Test framework.
There are a few other folders that provide supporting materials for the tests:
* common - assertionObjects, conditionObjects, and other supporting materials
* definitions - JSON Schema definitions that can be referenced
* scripts - JavaScript that are included by tests
* tools - supporting scripts and files
NOTE: The files in the definitions folder are expected to be JSON Schema
definitions - basically commonly used concepts that are referenced by other JSON
Schema files in the system. All of these 'definitions' are preloaded by the
system before any other parts of a test are processed.
Test Cases
----------
Each test is expressed as a simple (or complex) requirement in a test file.
For each section of the document, the requirement is represented as a structure
that describes the nature of the test, and then includes or references minimal
JSON Schema that test the assertions implied by the requirement.
The structure of a test case is defined using a [JSON-LD
Context](JSONtest-v1.jsonld). That context defines the following terms:
|Keyword | Values | Meaning
|---------------|-----------------|---------
|name | string | The name of this test for display purposes
|description | string | A long self-describing paragraph that explains the purpose of the test and the expected input
|ref | URI | An optional reference to the portion of the specification to which the test relates
|testType | `automated`, `manual`, `ref` | The type of test - this informs [WPT](https://github.com/w3c/web-platform-tests) how the test should be controlled and presented
|assertions | list of URI, List @@@ATRISK@@@, or AssertionObject | The ordered collection of tests the input should be run against. See [JSON Schema Usage](#jsonSchema) for the structure of the objects. URI is relative to the top level folder of the test collection if it has a slash; relative to the current directory if it does not. @@@@ATRISK@@@@ Lists can be nested to define groups of sub-tests. Assertions / groups can be conditionally skipped. See [Assertion Lists](#assertionLists) for more details.
Each test case has a suffix of `.test` and a shape like:
<pre>
{
"@context": "https://www.w3.org/ns/JSONtest-v1.jsonld",
"name": "Verify annotation conforms to the model",
"description": "Supply an example annotation that conforms to the basic structure.",
"ref": "https://www.w3.org/TR/annotation-model/#model",
"testType": "manual",
"assertions": [
"common/has_context.json",
"common/has_id.json",
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Verify annotation has target",
"type": "object",
"expectedResult": "valid",
"errorMessage": "The object was missing a required 'target' property",
"properties": {
"target": {
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"anyOf": [
{
"type": "string"
}
]
}
],
"not": {"type": "object"}
}
},
"required": ["target"]
}
]
}
</pre>
External references are used when the "assertion" is a common one that needs to
be checked on many different test cases (e.g., that there is an @context in the
supplied annotation).
### <a id="assertionLists">Assertion Lists</a> ###
The `assertion` list is an ordered list of assertions that will be evaluated
against the submitted content. The list is *required*, and MUST have at least
one entry. Entries in the list have the following types:
* AssertionObject
An in-line Object as defined in the section [Assertion
Objects](#assertionObjects).
* URI
A relative or absolute URI that references a AssertionObject in a .json file.
If the URI is relative but contains no slashes, then it is considered to be
in the current directory. If the URI is relative, contains slashes, but
**does not start with a slash** then it is considered relative to the top of
the tree of the current test collection (e.g., `annotation-model`).
* List @@@ATRISK@@@
A nested Assertion List. While nested Assertion Lists are optional, if one
is present it MUST have at least one entry. Entries are as in this list.
Assertion Lists can be nested to any depth (but don't do that - it would be
too hard to maintain).
<a id="assertionObjects">Assertion Objects</a>
-----------------
In this collection of tests, Assertion Objects can be contained inline in the
`.test` files or contained in external files with the suffix `.json`. The
vocabularly and structure is as defined in [JSON Schema
v4](http://json-schema.org/documentation.html) augmented with some additional
properties defined in this section.
In general each JSON Schema definition provided in this test suite should be as
minimal as possible. This promotes clarity and increases the likelihood that
it is correct. While it is ---possible--- to create JSON Schema files that
enforce many different requirements on a data model, it increases the
complexity and can also reduce the atomicity of tests / sub-tests (because a
test ends up testing more than one thing). Please try to avoid creating
complex JSON Schema. (A notable exception is the situation where multiple
properties of a structure are interdependent.)
Tools such as [the JSON Schema Creator](http://jsonschema.net/) may be helpful
in creating schema snippets that can be integrated into JSONtest Assertion
Objects. Remember that the JSON Schema you create should be as permissive as
possible to address the various shapes that a give property might take (e.g., a
'foo' might be a string or an object that contains sub-properties that express
the string, or an array of 1 or more objects with those sub-properties).
In addition to the validation keys defined in JSON Schema v4, Schema files in
this collection are also permitted to use the following keywords:
|Keyword | Values | Meaning |
|---------------|-----------------|---------|
|onUnexpectedResult | `failAndContinue`, `failAndSkip`, `failAndAbort`, `passAndContinue`, `passAndSkip`, `passAndAbort` | Action to take when the result is not as expected. Default is `failAndContinue` |
|assertionType | `must`, `may`, `should` | Informs the system about the severity of a failure. The default is `must` |
|assertionFile | URI | An external file that contains an assertion SCHEMA. When this value is supplied, and local properties will override the ones loaded from the external file.
|errorMessage | string | A human readable explanation of what it means if the test fails. |
|expectedResult | `valid`, `invalid` | Tells the framework whether validating against this schema is expected to succeed or fail. The default is `valid` |
### Example Assertion Object ###
<pre>
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Verify annotation has @context",
"type": "object",
"expectedResult" : "valid",
"properties": {
"@context": {
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"anyOf": [
{
"type": "string"
}
]
}
],
"not": {"type": "object"}
}
},
"required": ["@context"]
}
</pre>
Note that in the case where a feature is *optional* the JSON Schema MUST be
crafted such that if the attribute is permitted to be missing from the content
(so that the result is `true`), but when the attribute is present in the
content it conforms to any requirements.
<a id="conditionObjects">Condition Objects</a>
-----------------
A Condition Object is a sub-class of an Assertion Object. It allows the
specification of the evaluation strategy for the assertions referenced by the
object. An object is a Condition Object IFF it has a `assertions` property. In
this case, there MUST NOT be an `assertionFile` property.
|Keyword | Values | Meaning |
|---------------|-----------------|---------|
|compareWith | `and`, `or` | How should the result of any referenced assertions be compared. Defaults to `and`. Note that this implies there is also an assertions property with a nested list of assertions to compare. |
|assertions | a list of assertions as in a Test Case above. This is required if there is a compareWith property |
An example of a test that would pass if there were an `@context` OR there were an `@id`:
<pre>
{
"@context": "https://www.w3.org/ns/JSONtest-v1.jsonld",
"name": "A test that has an 'or' clause",
"description": "A complex test that uses or-ing among a list of assertions",
"ref": "https://www.w3.org/TR/annotation-model/#model",
"testType": "manual",
"assertions": [
{ "$schema": "http://json-schema.org/draft-04/schema#",
"title": "must have context or id",
"description": "A more complex example that allows one of many options to pass",
"assertions": [
{ "title": "Condition Object",
"description": "A pseudo-test that will get a result from the aggregate of its children",
"assertionType": "must",
"expectedResult": "valid",
"errorMessage": "Error: None of the various options were present",
"compareWith": "or",
"assertions": [
"common/has_context.json",
"common/has_id.json"
]
}
]
}
]
}
</pre>
Command Line Tools
------------------
### Building the Test Files ###
The actual .html test case files are generated using the script
tools/make_tests.py. This script will search the directory heriarchy looking for
files ending on `.test` and creating `.html` files from them using the template in
the tools folder. If you want to regenerate the examples too, supply the
`--examples` option to the script.
Note that when submitting tests to the repository, the `.html` versions must be
included.
### Testing the Tests ###
### Driving Tests with Input Files ###
Complex Examples
----------------
This section is a collection of more complex examples to illustrate the
expressive power of the [Assertion List](#assertionLists) structure. These can
be used as templates for creating actual `.test` files.
### Including and Overriding an Assertion ###
Assertions can be contained in external `.json` files. It is possible for an
object in an Assertion List to include the external file and override one or
more of its properties:
<pre>
{
"@context": "https://www.w3.org/ns/JSONtest-v1.jsonld",
"name": "Permit no target property",
"description": "Ensure there is no 'target' property when there is a 'randomName' property in the Annotation",
"assertions": [
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Verify annotation has randomName",
"type": "object",
"properties": {
"randomName": {
"type": "string"
}
},
"required": ["randomName"]
},
{ "assertionFile" : "common/target.json",
"title" : "Require target to be missing",
"expectedResult" : "invalid",
"errorMessage" : "The target MUST not be present when 'randomName' is also present",
}
]
}
</pre>
### Nested Assertion Collections with Skip ###
Assertion Lists can be nested within Assertion Lists. This feature, combined
with the `onUnexpectedResult` property, makes it possible to skip a collection
of tests when an assertion in the list is not satisfied:
<pre>
{
"@context": "https://www.w3.org/ns/JSONtest-v1.jsonld",
"name": "If there is no 'target' property, skip some tests",
"description": "When 'target' is not present, other properties related to 'target' are not required",
"assertions": [
"common/context.json",
[
{ "assertionFile" : "common/target.json",
"errorMessage" : "Target was not present so skip the rest of this section",
"onUnexpectedResult" : "failAndSkip"
},
"sometest.json",
"sometest2.json",
"sometest3.json"
]
]
} ;
</pre>
### Assertion that finds a specific @context Value ###
Sometimes you want a property to be flexible, but to have one and only one of a
specific value. This is especially true with, for example, @context in JSON-LD.
One way you might do this is:
<pre>
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Verify a specific @context",
"type": "object",
"expectedResult" : "valid",
"properties": {
"@context": {
"anyOf": [
{
"type": "string"
"enum": [ "http://www.w3.org/ns/anno.jsonld" ]
},
{
"type": "array",
"minitems": "1",
"uniqueItems": true,
"additionalItems": true,
"items" : [
{ "type": "string",
"enum": [ "http://www.w3.org/ns/anno.jsonld" ]
}
]
}
],
"not": {"type": "object"}
}
},
"required": ["@context"]
}
</pre>

View file

@ -0,0 +1,2 @@
@halindrome
@bigbluehat

View file

@ -0,0 +1,81 @@
Annotation-model: Tests for the Web Annotation Data Model
=========================================================
The [Web Annotation Data Model](https://www.w3.org/TR/annotation-model)
specification presents a JSON-oriented collection of terms and structure that
permit the sharing of annotations about other content.
The purpose of these tests is to help validate that each of the structural
requirements expressed in the Data Model specification are properly supported
by implementations.
The general approach for this testing is to enable both manual and automated
testing. However, since the specification has no actual user interface
requirements, there is no general automation mechanism that can be presented
for clients. Instead, the automation mechanism is one where client
implementors could take advantage of the plumbing we provide here to push their
data into the tests and collect the results of the testing. This assumes
knowledge of the requirements of each test / collection of tests so that the
input data is relevant. Each test or test collection contains information
sufficient for the task.
Running Tests
-------------
In the case of this test collection, we will be initially creating manual
tests. These will automatically determine pass or fail and generate output for
the main WPT window. The plan is to minimize the number of such tests to
ease the burden on the testers while still exercising all the features.
The workflow for running these tests is something like:
1. Start up the test driver window and select the annotation-model tests -
click "Start"
2. A window pops up that shows a test - the description of which tells the
tester what input is expected. The window contains a textarea into which
the input can be typed / pasted, along with a button to click to start
testing that input.
3. The tester (presumably in another window) brings up their annotation client
and uses it to generate an annotation that supplies the requested structure.
They then copy / paste that into the aforementioned textarea and select the
button.
4. The test runs. Success or failure is determined and reported to the test
driver window, which then cycles to the next test in the sequence.
5. Repeat steps 2-4 until done.
6. Download the JSON format report of test results, which can then be visually
inspected, reported on using various tools, or passed on to W3C for
evaluation and collection in the Implementation Report via github.
**Remember that while these tests are written to help exercise implementations,
their other (important) purpose is to increase confidence that there are
interoperable implementations.** So, implementers are our audience, but these
tests are not meant to be a comprehensive collection of tests for a client that
might implement the Recommendation. The bulk of the tests are manual because
there are no UI requirements in the Recommendation that would make it possible
to effectively stimulate every client portably.
Having said that, because the structure of these "manual" tests is very rigid,
it is possible for an implementer who understands test automation to use an
open source tool such as [Selenium](http://www.seleniumhq.org/) to run these
"manual" tests against their implementation - exercising their implementation
against content they provide to create annotations and feed the data into our
test input field and run the test.
Capturing and Reporting Results
-------------------------------
As tests are run against implementations, if the results of testing are
submitted to [test-results](https://github.com/w3c/test-results/) then they will
be automatically included in documents generated by
[wptreport](https://www.github.com/w3c/wptreport). The same tool can be used
locally to view reports about recorded results.
Automating Test Execution
-------------------------
Writing Tests
-------------
If you are interested in writing tests for this environment, see the
associated [CONTRIBUTING](CONTRIBUTING.md) document.

View file

@ -0,0 +1,18 @@
Things still to be developed:
Script to run .jsonld files in tools/tests against .test files
Script to batch run submitted .jsonld files from an implementation against .test
files
Websocket communication to runner tests with a corresponding listener that an
implementation could use to auto-submit jsonld into the "manual" tests
Change JSONtest logic so that it loads all of the required external files during
initialization so that it can populate the list of assertions for the HTML in a
manual test. Use Promises and Promise.all() to achieve this.
Add a Skip option to tools/runner
Add a tuple mode for evaluating RDF declaratively as well.

View file

@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id" : "choiceSet.json",
"type": "object",
"properties":
{
"type":
{
"type": "string",
"enum": ["Choice", "Composite", "List", "Independents"]
},
"items" :
{
"type" : "array"
}
},
"required": [ "type", "items" ]
}

View file

@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id" : "externalWebResource.json",
"type": "object",
"properties":
{
"id":
{
"$ref": "stringUri.json#"
}
},
"required": [ "id" ]
}

View file

@ -0,0 +1,17 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id" : "specificResource.json",
"type": "object",
"properties":
{
"source":
{
"type": ["string", "object" ],
"oneOf": [
{ "$ref": "stringUri.json#" },
{ "$ref": "externalWebResource.json#"}
]
}
},
"required": ["source"]
}

View file

@ -0,0 +1,6 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id" : "stringUri.json",
"type": "string",
"format": "uri"
}

View file

@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id" : "textualBody.json",
"type": "object",
"properties":
{
"value":
{
"type": "string"
}
},
"required": [ "value" ]
}

View file

@ -0,0 +1,9 @@
Example Tests
=============
The tests in this folder are examples to show how the framework
should be used. They are NOT intended for conformance testing use, and
tools/make_tests.py will not generate the tests in this folder without the
`--examples` option.

View file

@ -0,0 +1,46 @@
<!doctype html>
<html>
<head>
<title>Verify annotation conforms to the model</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/annotation-model/scripts/ajv.min.js"></script>
<script src="/annotation-model/scripts/JSONtest.js"></script>
<script>
setup({explicit_timeout: true, explicit_done: true });
var theDefinitions=[
"definitions/specificResource.json",
"definitions/stringUri.json",
"definitions/choiceSet.json",
"definitions/externalWebResource.json",
"definitions/textualBody.json"
];
var theTestFile="example1.test";
var runningTest = new JSONtest( {
"testInput" : "annotation-input",
"runTest" : "annotation-run",
"closeWindow" : "annotation-close",
"schemaDefs" : theDefinitions,
"testFile" : theTestFile
} ) ;
</script>
</head>
<body>
<p>Fill the textarea below with JSON output from your annotation client
implementation that supports the following criteria:</p>
<div id="testDescription"></div>
<p>Specifically, the following assertions will be evaluated:</p>
<div id="assertion"></div>
<form name="annotation" id="annotation">
<textarea name="annotation-input" id="annotation-input" style="width: 90%; height: 10em" >
</textarea>
<p><input type="button" id="annotation-run" name="Loading..." value="Loading...">
<input style="display: none" type="button" id="annotation-close"
name="Close" value="Close"></p>
</form>
</body>
</html>

View file

@ -0,0 +1,10 @@
{
"@context": "https://www.w3.org/ns/JSONtest-v1.jsonld",
"name": "Verify annotation conforms to the model",
"description": "Supply an example annotation that conforms to the basic structure.",
"ref": "https://www.w3.org/TR/annotation-model/#model",
"assertions": [
"exampleContext.json",
"exampleTarget.json"
]
}

View file

@ -0,0 +1,46 @@
<!doctype html>
<html>
<head>
<title>A test that has an 'or' clause</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/annotation-model/scripts/ajv.min.js"></script>
<script src="/annotation-model/scripts/JSONtest.js"></script>
<script>
setup({explicit_timeout: true, explicit_done: true });
var theDefinitions=[
"definitions/specificResource.json",
"definitions/stringUri.json",
"definitions/choiceSet.json",
"definitions/externalWebResource.json",
"definitions/textualBody.json"
];
var theTestFile="example2.test";
var runningTest = new JSONtest( {
"testInput" : "annotation-input",
"runTest" : "annotation-run",
"closeWindow" : "annotation-close",
"schemaDefs" : theDefinitions,
"testFile" : theTestFile
} ) ;
</script>
</head>
<body>
<p>Fill the textarea below with JSON output from your annotation client
implementation that supports the following criteria:</p>
<div id="testDescription"></div>
<p>Specifically, the following assertions will be evaluated:</p>
<div id="assertion"></div>
<form name="annotation" id="annotation">
<textarea name="annotation-input" id="annotation-input" style="width: 90%; height: 10em" >
</textarea>
<p><input type="button" id="annotation-run" name="Loading..." value="Loading...">
<input style="display: none" type="button" id="annotation-close"
name="Close" value="Close"></p>
</form>
</body>
</html>

View file

@ -0,0 +1,42 @@
{
"@context": "https://www.w3.org/ns/JSONtest-v1.jsonld",
"name": "A test that has an 'or' clause",
"description": "This is a complex test that uses or-ing among a list of assertions.",
"ref": "https://www.w3.org/TR/annotation-model/#model",
"testType": "manual",
"assertions":
{ "title": "Condition Object",
"description": "A pseudo-test that will get a result from the aggregate of its children",
"assertionType": "must",
"expectedResult": "valid",
"errorMessage": "Error: None of the various options were present",
"compareWith": "or",
"assertions": [
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "'The Annotation must have 1 or more @context values' (Section 3.1)",
"assertionType": "must",
"expectedResult": "valid",
"errorMessage": "Error: Annotation does not have an @context property.",
"type": "object",
"properties": {
"@context": {}
},
"required": ["@context"]
},
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "'An Annotation should have exactly 1 id' (Section 3.1)",
"assertionType": "should",
"expectedResult": "valid",
"errorMessage": "Warning: The Annotation is not identified using the id key (Section 3.1).",
"type": "object",
"properties": {
"id": {}
},
"required": ["id"]
}
]
}
}

View file

@ -0,0 +1,31 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Check @context value",
"description": "'http://www.w3.org/ns/anno.jsonld must be' an @context value (Section 3.1)",
"assertionType": "must",
"expectedResult": "valid",
"errorMessage": "Error: 'http://www.w3.org/ns/anno.jsonld' is not an @context value.",
"type": "object",
"properties": {
"@context": {
"oneOf": [
{ "type": "string",
"$ref": "#/definitions/contextValue" },
{ "type": "array",
"$ref": "#/definitions/contextArray" }
]
}
},
"definitions": {
"contextValue":
{ "enum": [ "http://www.w3.org/ns/anno.jsonld" ] },
"contextArray":
{ "not":
{ "items":
{ "not":
{ "type": "string",
"$ref": "#/definitions/contextValue" } }
}
}
}
}

View file

@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Check if target feature implemented",
"description": "'There must be 1 or more target relationships associated with an Annotation.' (Section 3.1)",
"assertionType": "must",
"expectedResult": "valid",
"errorMessage": "Error: Annotation has no target relationships - at least 1 is required. (Section 3.1)",
"type": "object",
"properties": {
"target": { "type": ["string", "array", "object"] }
},
"required": ["target"]
}

View file

@ -0,0 +1,686 @@
/* globals add_completion_callback, Promise, done, assert_true, Ajv, on_event */
/**
* Creates a JSONtest object. If the parameters are supplied
* it also loads a referenced testFile, processes that file, loads any
* referenced external assertions, and sets up event listeners to process the
* user's test data. The loading is done asynchronously via Promises. The test
* button's text is changed to Loading while it is processing, and to "Check
* JSON" once the data is loaded.
*
* @constructor
* @param {object} params
* @param {string} [params.test] - object containing JSON test definition
* @param {string} [params.testFile] - URI of a file with JSON test definition
* @param {string} params.runTest - IDREF of an element that when clicked will run the test
* @param {string} params.testInput - IDREF of an element that contains the JSON(-LD) to evaluate against the assertions in the test / testFile
* @event DOMContentLoaded Calls init once DOM is fully loaded
* @returns {object} Reference to the new object
*/
function JSONtest(params) {
'use strict';
this.Assertions = []; // object that will contain the assertions to process
this.AssertionText = ""; // string that holds the titles of all the assertions in use
this.DescriptionText = "";
this.Base = null; // URI "base" for the tests being run
this.Params = null; // paramaters passed in
this.Properties = null; // testharness_properties from the opening window
this.Test = null; // test being run
this.AssertionCounter = 0;// keeps track of which assertion is being processed
this._assertionText = []; // Array of text or nested arrays of assertions
this._assertionCache = [];// Array to put loaded assertions into
this._loading = true;
var pending = [] ;
// set up in case DOM finishes loading early
pending.push(new Promise(function(resolve) {
on_event(document, "DOMContentLoaded", function() {
resolve(true);
}.bind(this));
}.bind(this)));
// create an ajv object that will stay around so that caching
// of schema that are compiled just works
this.ajv = new Ajv({allErrors: true, validateSchema: false}) ;
// determine the base URI for the test collection. This is
// the top level folder in the test "document.location"
var l = document.location;
var p = l.pathname;
this.Base = p.substr(0, 1+p.indexOf('/', 1));
// if we are under runner, then there are props in the parent window
//
// if "output" is set in that, then pause at the end of running so the output
// can be analyzed. @@@TODO@@@
if (window && window.opener && window.opener.testharness_properties) {
this.Properties = window.opener.testharness_properties;
}
this.Params = params;
// if there is a list of definitions in the params,
// include them
if (this.Params.schemaDefs) {
var defPromise = new Promise(function(resolve, reject) {
var promisedSchema = this.Params.schemaDefs.map(function(item) {
return this.loadDefinition(item);
}.bind(this));
// Once all the loadAssertion promises resolve...
Promise.all(promisedSchema)
.then(function (schemaContents) {
this.ajv.addSchema(schemaContents);
resolve(true);
}.bind(this))
.catch(function(err) {
reject(err);
}.bind(this));
}.bind(this));
// these schema need to load up too
pending.push(defPromise) ;
}
// start by loading the test (it might be inline, but
// loadTest deals with that
pending.push(this.loadTest(params)
.then(function(test) {
// if the test is NOT an object, turn it into one
if (typeof test === 'string') {
test = JSON.parse(test) ;
}
this.Test = test;
// Test should have information that we can put in the template
if (test.description) {
this.DescriptionText = test.description;
}
return new Promise(function(resolve, reject) {
if (test.assertions &&
typeof test.assertions === "object") {
// we have at least one assertion
// get the inline contents and the references to external files
var assertFiles = this._assertionRefs(test.assertions);
var promisedAsserts = assertFiles.map(function(item) {
return this.loadAssertion(item);
}.bind(this));
// Once all the loadAssertion promises resolve...
Promise.all(promisedAsserts)
.then(function (assertContents) {
// assertContents has assertions in document order
var assertIdx = 0;
// populate the display of assertions that are being exercised
// returns the list of top level assertions to walk through
var buildList = function(assertions, level) {
if (level === undefined) {
level = 1;
}
// accumulate the assertions - but only when level is 0
var list = [] ;
if (assertions) {
if (typeof assertions === "object" && assertions.hasOwnProperty('assertions')) {
// this is a conditionObject
if (level === 0) {
list.push(assertContents[assertIdx]);
}
this.AssertionText += "<li>" + assertContents[assertIdx++].title;
this.AssertionText += "<ol>";
buildList(assertions.assertions, level+1) ;
this.AssertionText += "</ol></li>\n";
} else {
// it is NOT a conditionObject - must be an array
assertions.forEach( function(assert) {
if (typeof assert === "object" && Array.isArray(assert)) {
this.AssertionText += "<ol>";
// it is a nested list - recurse
buildList(assert, level+1) ;
this.AssertionText += "</ol>\n";
} else if (typeof assert === "object" && !Array.isArray(assert) && assert.hasOwnProperty('assertions')) {
if (level === 0) {
list.push(assertContents[assertIdx]);
}
// there is a condition object in the array
this.AssertionText += "<li>" + assertContents[assertIdx++].title;
this.AssertionText += "<ol>";
buildList(assert, level+1) ; // capture the children too
this.AssertionText += "</ol></li>\n";
} else {
if (level === 0) {
list.push(assertContents[assertIdx]);
}
this.AssertionText += "<li>" + assertContents[assertIdx++].title + "</li>\n";
}
}.bind(this));
}
}
return list;
}.bind(this);
// Assertions will ONLY contain the top level assertions
this.Assertions = buildList(test.assertions, 0);
resolve(true);
}.bind(this))
.catch(function(err) {
reject(err);
}.bind(this));
} else {
if (!test.assertions) {
reject("Test has no assertion property");
} else {
reject("Test assertion property is not an Array");
}
}
}.bind(this));
}.bind(this)));
// once the DOM and the test / assertions are loaded... set us up
Promise.all(pending)
.then(function() {
this.loading = false;
this.init();
}.bind(this))
.catch(function(err) {
// loading the components failed somehow - report the errors and mark the test failed
test( function() {
assert_true(false, "Loading of test components failed: " +JSON.stringify(err)) ;
}, "Loading test components");
done() ;
return ;
}.bind(this));
return this;
}
JSONtest.prototype = {
/**
* @listens click
*/
init: function() {
'use strict';
// set up a handler
var runButton = document.getElementById(this.Params.runTest) ;
var closeButton = document.getElementById(this.Params.closeWindow) ;
var testInput = document.getElementById(this.Params.testInput) ;
var assertion = document.getElementById("assertion") ;
var desc = document.getElementById("testDescription") ;
if (!this.loading) {
runButton.disabled = false;
runButton.value = "Check JSON";
if (desc) {
desc.innerHTML = this.DescriptionText;
}
if (assertion) {
assertion.innerHTML = "<ol>" + this.AssertionText + "</ol>\n";
}
} else {
window.alert("Loading did not finish before init handler was called!");
}
// @@@TODO@@@ implement the output showing handler
if (0 && this.Properties && this.Properties.output && closeButton) {
// set up a callback
add_completion_callback( function() {
var p = new Promise(function(resolve) {
closeButton.style.display = "inline";
closeButton.disabled = false;
on_event(closeButton, "click", function() {
resolve(true);
});
}.bind(this));
p.then();
}.bind(this));
}
on_event(runButton, "click", function() {
// user clicked
var content = testInput.value;
runButton.disabled = true;
// make sure content is an object
if (typeof content === "string") {
try {
content = JSON.parse(content) ;
} catch(err) {
// if the parsing failed, create a special test and mark it failed
test( function() {
assert_true(false, "Parse of JSON failed: " + err) ;
}, "Parsing submitted input");
// and just give up
done();
return ;
}
}
// iterate over all of the tests for this instance
this.runTests(this.Assertions, content);
// explicitly tell the test framework we are done
done();
}.bind(this));
},
// runTests - process tests
/**
* @param {object} assertions - List of assertions to process
* @param {string} content - JSON(-LD) to be evaluated
* @param {string} [testAction='continue'] - state of test processing (in parent when recursing)
* @param {integer} [level=0] - depth of recursion since assertion lists can nest
* @param {string} [compareWith='and'] - the way the results of the referenced assertions should be compared
* @returns {string} - the testAction resulting from evaluating all of the assertions
*/
runTests: function(assertions, content, testAction, level, compareWith) {
'use strict';
// level
if (level === undefined) {
level = 1;
}
// testAction
if (testAction === undefined) {
testAction = 'continue';
}
// compareWith
if (compareWith === undefined) {
compareWith = 'and';
}
// for each assertion (in order) load the external json schema if
// one is referenced, or use the inline schema if supplied
// validate content against the referenced schema
var theResults = [] ;
if (assertions) {
assertions.forEach( function(assert, num) {
var expected = assert.hasOwnProperty('expectedResult') ? assert.expectedResult : 'valid' ;
var message = assert.hasOwnProperty('message') ? assert.message : "Result was not " + expected;
// first - what is the type of the assert
if (typeof assert === "object" && !Array.isArray(assert)) {
if (assert.hasOwnProperty("compareWith") && assert.hasOwnProperty("assertions") && Array.isArray(assert.assertions) ) {
// this is a comparisonObject
var r = this.runTests(assert.assertions, content, testAction, level+1, assert.compareWith);
// r is an object that contains, among other things, an array of results from the child assertions
testAction = r.action;
// evaluate the results against the compareWith setting
var result = true;
var data = r.results ;
var i;
if (assert.compareWith === "or") {
result = false;
for(i = 0; i < data.length; i++) {
if (data[i]) {
result = true;
}
}
} else {
for(i = 0; i < data.length; i++) {
if (!data[i]) {
result = false;
}
}
}
// create a test and push the result
test(function() {
var newAction = this.determineAction(assert, result) ;
// next time around we will use this action
testAction = newAction;
var err = ";";
if (testAction === 'abort') {
err += "; Aborting execution of remaining assertions;";
} else if (testAction === 'skip') {
err += "; Skipping execution of remaining assertions at level " + level + ";";
}
if (result === false) {
// test result was unexpected; use message
assert_true(result, message + err);
} else {
assert_true(result, err) ;
}
}.bind(this), assert.title);
// we are going to return out of this
return;
}
} else if (typeof assert === "object" && Array.isArray(assert)) {
// it is a nested list - recurse
var o = this.runTests(assert, content, testAction, level+1);
if (o.result && o.result === 'abort') {
// we are bailing out
testAction = 'abort';
}
}
if (testAction === 'abort') {
return {action: 'abort' };
}
var schemaName = "inline " + level + ":" + (num+1);
if (assert.assertionFile) {
schemaName = "external file " + assert.assertionFile + " " + level + ":" + (num+1);
}
var validate = null;
try {
validate = this.ajv.compile(assert);
}
catch(err) {
test( function() {
assert_true(false, "Compilation of schema " + level + ":" + (num+1) + " failed: " + err) ;
}, "Compiling " + schemaName);
return ;
}
if (testAction !== 'continue') {
// a previous test told us to not run this test; skip it
test(function() { }, "SKIPPED: " + assert.title);
} else {
// start an actual sub-test
test(function() {
var valid = validate(content) ;
var result = this.determineResult(assert, valid) ;
// remember the result
theResults.push(result);
var newAction = this.determineAction(assert, result) ;
// next time around we will use this action
testAction = newAction;
var err = ";";
if (validate.errors !== null) {
err = "; Errors: " + this.ajv.errorsText(validate.errors) + ";" ;
}
if (testAction === 'abort') {
err += "; Aborting execution of remaining assertions;";
} else if (testAction === 'skip') {
err += "; Skipping execution of remaining assertions at level " + level + ";";
}
if (result === false) {
// test result was unexpected; use message
assert_true(result, message + err);
} else {
assert_true(result, err) ;
}
}.bind(this), assert.title);
}
}.bind(this));
}
return { action: testAction, results: theResults} ;
},
determineResult: function(schema, valid) {
'use strict';
var r = 'valid' ;
if (schema.hasOwnProperty('expectedResult')) {
r = schema.expectedResult;
}
if (r === 'valid' && valid || r === 'invalid' && !valid) {
return true;
} else {
return false;
}
},
determineAction: function(schema, result) {
'use strict';
// mapping from results to actions
var mapping = {
'failAndContinue' : 'continue',
'failAndSkip' : 'skip',
'failAndAbort' : 'abort',
'passAndContinue': 'continue',
'passAndSkip' : 'skip',
'passAndAbort' : 'abort'
};
// if the result was as expected, then just keep going
if (result) {
return 'continue';
}
var a = 'failAndContinue';
if (schema.hasOwnProperty('onUnexpectedResult')) {
a = schema.onUnexpectedResult;
}
if (mapping[a]) {
return mapping[a];
} else {
return 'continue';
}
},
// loadAssertion - load an Assertion from an external JSON file
//
// returns a promise that resolves with the contents of the assertion file
loadAssertion: function(afile) {
'use strict';
if (typeof(afile) === 'string') {
var theFile = this._parseURI(afile);
// it is a file reference - load it
return new Promise(function(resolve, reject) {
this._loadFile("GET", theFile, true)
.then(function(data) {
data.assertionFile = afile;
resolve(data);
}.bind(this))
.catch(function(err) {
if (typeof err === "object") {
err.theFile = theFile;
}
reject(err);
});
}.bind(this));
}
else if (afile.hasOwnProperty("assertionFile")) {
// this object is referecing an external assertion
return new Promise(function(resolve, reject) {
var theFile = this._parseURI(afile.assertionFile);
this._loadFile("GET", theFile, true)
.then(function(external) {
// okay - we have an external object
Object.keys(afile).forEach(function(key) {
if (key !== 'assertionFile') {
external[key] = afile[key];
}
});
resolve(external);
}.bind(this))
.catch(function(err) {
if (typeof err === "object") {
err.theFile = theFile;
}
reject(err);
});
}.bind(this));
} else {
// it is already a loaded assertion - just use it
return new Promise(function(resolve) {
resolve(afile);
});
}
},
// loadDefinition - load a JSON Schema definition from an external JSON file
//
// returns a promise that resolves with the contents of the definition file
loadDefinition: function(dfile) {
'use strict';
return new Promise(function(resolve, reject) {
this._loadFile("GET", this._parseURI(dfile), true)
.then(function(data) {
resolve(data);
}.bind(this))
.catch(function(err) {
reject(err);
});
}.bind(this));
},
// loadTest - load a test from an external JSON file
//
// returns a promise that resolves with the contents of the
// test
loadTest: function(params) {
'use strict';
if (params.hasOwnProperty('testFile')) {
// the test is referred to by a file name
return this._loadFile("GET", params.testFile);
} // else
return new Promise(function(resolve, reject) {
if (params.hasOwnProperty('test')) {
resolve(params.test);
} else {
reject("Must supply a 'test' or 'testFile' parameter");
}
});
},
_parseURI: function(theURI) {
'use strict';
// determine what the top level URI should be
if (theURI.indexOf('/') === -1) {
// no slash - it's relative to where we are
// so just use it
return theURI;
} else if (theURI.indexOf('/') === 0 || theURI.indexOf('http:') === 0 || theURI.indexOf('https:') === 0) {
// it is an absolute URI so just use it
return theURI;
} else {
// it is relative and contains a slash.
// make it relative to the current test root
return this.Base + theURI;
}
},
/**
* return a list of all inline assertions or references
*
* @param {array} assertions list of assertions to examine
*/
_assertionRefs: function(assertions) {
'use strict';
var ret = [] ;
// when the reference is to an object that has an array of assertions in it (a conditionObject)
// then remember that one and loop over its embedded assertions
if (typeof(assertions) === "object" && !Array.isArray(assertions) && assertions.hasOwnProperty('assertions')) {
ret.push(assertions) ;
assertions = assertions.assertions;
}
if (typeof(assertions) === "object" && Array.isArray(assertions)) {
assertions.forEach( function(assert) {
// first - what is the type of the assert
if (typeof assert === "object" && Array.isArray(assert)) {
// it is a nested list - recurse
this._assertionRefs(assert).forEach( function(item) {
ret.push(item);
}.bind(this));
} else if (typeof assert === "object") {
ret.push(assert) ;
if (assert.hasOwnProperty("assertions")) {
ret.push(this._assertionRefs(assert.assertions));
}
} else {
// it is a file name
ret.push(assert) ;
}
}.bind(this));
}
return ret;
},
// _loadFile - return a promise loading a file
//
_loadFile: function(method, url, parse) {
'use strict';
if (parse === undefined) {
parse = true;
}
return new Promise(function (resolve, reject) {
if (document.location.search) {
var s = document.location.search;
s = s.replace(/^\?/, '');
if (url.indexOf('?') !== -1) {
url += "&" + s;
} else {
url += "?" + s;
}
}
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
var d = xhr.response;
if (parse) {
try {
d = JSON.parse(d);
resolve(d);
}
catch(err) {
reject({ status: this.status,
statusText: "Parsing of " + url + " failed: " + err }
);
}
} else {
resolve(d);
}
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
},
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,87 @@
# Copyright (c) 2016 W3C
# Released under the W3C Test Suite License: see LICENSE.txt
# This tool creates .html test files for the WPT harness from corresponding .text
# files that it finds in the tree for this test collection.
import re
import time
import json
import fnmatch
import os
import shutil
import sys
import argparse
TESTTREE = '..'
DEFDIR = '../definitions'
TEMPLATE = 'template'
parser = argparse.ArgumentParser()
parser.add_argument('--examples', action="store_const", const=1)
args = parser.parse_args()
# pull in the template
template = open(TEMPLATE).read()
defList = []
defnames = ""
# find all of the definitions
for curdir, subdirList, fileList in os.walk(DEFDIR, topdown=True):
for file in fnmatch.filter(fileList, "*.json"):
theFile = os.path.join(curdir, file)
try:
testJSON = json.load(open(theFile))
except ValueError as e:
print "parse of " + theFile + " failed: " + e[0]
else:
theFile = re.sub("\.\./", "", theFile)
defList.append(theFile)
if (len(defList)):
defNames = '"' + '",\n "'.join(defList) + '"'
# iterate over the folders looking for .test files
for curdir, subdirList, fileList in os.walk(TESTTREE, topdown=True):
# sjip the definitions directory
subdirList[:] = [d for d in subdirList if d != "definitions"]
# skip the examples directory
if args.examples != 1:
subdirList[:] = [d for d in subdirList if d != "examples"]
for file in fnmatch.filter(fileList, "*.test"):
# for each .test file, create a corresponding .html file using template
theFile = os.path.join(curdir, file)
try:
testJSON = json.load(open(theFile))
except ValueError as e:
print "parse of " + theFile + " failed: " + e[0]
else:
rfile = re.sub("\.\./", "", file)
# interesting pattern is {{TESTFILE}}
tcopy = re.sub("{{TESTFILE}}", rfile, template)
tcopy = re.sub("{{SCHEMADEFS}}", defNames, tcopy)
if testJSON['name']:
tcopy = re.sub("{{TESTTITLE}}", testJSON['name'], tcopy)
# target file is basename of theFile + '-manual.html'
target = re.sub("\.test","-manual.html", theFile)
try:
out = open(target, "w")
out.write(tcopy)
out.close()
except:
print("Failed to create "+target)
else:
print("Created " + target)

View file

@ -0,0 +1,42 @@
<!doctype html>
<html>
<head>
<title>{{TESTTITLE}}</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/annotation-model/scripts/ajv.min.js"></script>
<script src="/annotation-model/scripts/JSONtest.js"></script>
<script>
setup({explicit_timeout: true, explicit_done: true });
var theDefinitions=[
{{SCHEMADEFS}}
];
var theTestFile="{{TESTFILE}}";
var runningTest = new JSONtest( {
"testInput" : "annotation-input",
"runTest" : "annotation-run",
"closeWindow" : "annotation-close",
"schemaDefs" : theDefinitions,
"testFile" : theTestFile
} ) ;
</script>
</head>
<body>
<p>Fill the textarea below with JSON output from your annotation client
implementation that supports the following criteria:</p>
<div id="testDescription"></div>
<p>Specifically, the following assertions will be evaluated:</p>
<div id="assertion"></div>
<form name="annotation" id="annotation">
<textarea name="annotation-input" id="annotation-input" style="width: 90%; height: 10em" >
</textarea>
<p><input type="button" id="annotation-run" name="Loading..." value="Loading...">
<input style="display: none" type="button" id="annotation-close"
name="Close" value="Close"></p>
</form>
</body>
</html>

View file

@ -0,0 +1,10 @@
Tree to Test the Tests
======================
This folder is meant to contain a collection of .jsonld files that mirror the
structure of the top level folders and subfolders with .test files. A script
(@@@TODO@@@) will walk this tree, taking each folder and running it through the
corresponding .test file to ensure that the test is working as expected. An
argument to that script will report on any .jsonld files that do not have a
corresponding .test file, and vice versa.

View file

@ -0,0 +1 @@
@halindrome

View file

@ -50,6 +50,10 @@ test(function() {
'The document must have a URL value equal to the URL of the active document.');
}, 'URL value');
test(function() {
assert_equals(doc.baseURI, document.URL);
}, 'baseURI value');
test(function() {
assert_equals(doc.location, null,
'The document must have a location value of null.');

View file

@ -9,6 +9,7 @@ function checkMetadata(doc, contentType) {
assert_true(doc instanceof Document, "Should be Document");
assert_equals(doc.URL, document.URL, "URL");
assert_equals(doc.documentURI, document.URL, "documentURI");
assert_equals(doc.baseURI, document.URL, "baseURI");
assert_equals(doc.characterSet, "UTF-8", "characterSet");
assert_equals(doc.charset, "UTF-8", "charset");
assert_equals(doc.inputEncoding, "UTF-8", "inputEncoding");

View file

@ -0,0 +1,15 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Fetch in worker: response url getter</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#response-class">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
fetch_tests_from_worker(new Worker("response-url.js?pipe=sub"));
</script>
</body>
</html>

View file

@ -0,0 +1,13 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Fetch: response url getter</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#response-class">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script src="response-url.js?pipe=sub"></script>
</body>
</html>

View file

@ -0,0 +1,21 @@
if (this.document === undefined) {
importScripts("/resources/testharness.js");
}
function checkResponseURL(fetchedURL, expectedURL)
{
promise_test(function() {
return fetch(fetchedURL).then(function(response) {
assert_equals(response.url, expectedURL);
});
}, "Testing response url getter with " +fetchedURL);
}
var baseURL = "http://{{host}}:{{ports[http][0]}}";
checkResponseURL(baseURL + "/ada", baseURL + "/ada");
checkResponseURL(baseURL + "/#", baseURL + "/");
checkResponseURL(baseURL + "/#ada", baseURL + "/");
checkResponseURL(baseURL + "#ada", baseURL + "/");
done();

View file

@ -66,16 +66,16 @@
test(function() {
var url = "http://url.test:1234/path/subpath?query=true";
expectedDefault["url"] = url;
url += "#fragment";
expectedDefault["url"] = url;
var requestToCheck = new Request(url);
checkRequest(requestToCheck, expectedDefault);
}, "Check request values when initialized from url string");
test(function() {
var url = "http://url.test:1234/path/subpath?query=true";
expectedInitialized["url"] = url;
url += "#fragment";
expectedInitialized["url"] = url;
var requestToCheck = new Request(url , initValuesDict);
checkRequest(requestToCheck, expectedInitialized);
}, "Check request values when initialized from url and init values");

View file

@ -2353,7 +2353,7 @@ interface BeforeUnloadEvent : Event {
attribute DOMString returnValue;
};
[Exposed=Window,SharedWorker]
[Exposed=(Window,SharedWorker)]
interface ApplicationCache : EventTarget {
// update status
@ -2762,13 +2762,13 @@ interface WorkerGlobalScope : EventTarget {
// also has additional members in a partial interface
};
[Global=Worker,DedicatedWorker]
[Global=(Worker,DedicatedWorker),Exposed=DedicatedWorker]
/*sealed*/ interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
void postMessage(any message, optional sequence<Transferable> transfer);
attribute EventHandler onmessage;
};
[Global=Worker,SharedWorker]
[Global=(Worker,SharedWorker),Exposed=SharedWorker]
/*sealed*/ interface SharedWorkerGlobalScope : WorkerGlobalScope {
readonly attribute DOMString name;
readonly attribute ApplicationCache applicationCache;
@ -2795,7 +2795,6 @@ interface SharedWorker : EventTarget {
};
SharedWorker implements AbstractWorker;
[Exposed=Worker]
partial interface WorkerGlobalScope { // not obsolete
void importScripts(DOMString... urls);
readonly attribute WorkerNavigator navigator;
@ -3246,7 +3245,7 @@ window.onload = function() {
TextTrackCue: [],
DataCue: [],
TimeRanges: ['document.createElement("video").buffered'],
TrackEvent: ['new TrackEvent("addtrack"; {track:document.createElement("track").track})'],
TrackEvent: ['new TrackEvent("addtrack", {track:document.createElement("track").track})'],
HTMLTemplateElement: ['document.createElement("template")'],
HTMLSlotElement: ['document.createElement("slot")'],
HTMLCanvasElement: ['document.createElement("canvas")'],

View file

@ -109,6 +109,10 @@ CONSOLE:service-workers/service-worker/resources/navigation-redirect-other-origi
CONSOLE:service-workers/service-worker/navigation-redirect.https.html
CONSOLE:service-workers/service-worker/resources/clients-get-other-origin.html
# use of console in a public library - annotation-model ensures
# it is not actually used
CONSOLE:annotation-model/scripts/ajv.min.js
# Lint doesn't know about sub.svg I guess
PARSE-FAILED:content-security-policy/svg/including.sub.svg

View file

@ -0,0 +1,145 @@
<!doctype html>
<html>
<head>
<title>Pointer Event: Boundary compatibility events for multiple primary pointers</title>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<link rel="author" title="Google" href="http://www.google.com "/>
<meta name="assert" content="When more than one primary pointers are active, each will have an independent sequence of pointer boundary events but the compatibilty mouse boundary events have their own sequence."/>
<link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript" src="pointerevent_support.js"></script>
<script type="text/javascript">
var test_pointerEvent = async_test("Multi-pointer boundary compat events");
add_completion_callback(end_of_test);
var detected_pointertypes = {};
var event_log = [];
// These two ids help us detect two different pointing devices.
var first_entry_pointer_id = -1;
var second_entry_pointer_id = -1;
// Current node for each pointer id
var current_node_for_id = {};
function end_of_test() {
showLoggedEvents();
showPointerTypes();
}
function end_of_interaction() {
test(function () {
assert_equals(event_log.join(", "),
"mouseover@target0, mouseenter@target0, mouseout@target0, mouseleave@target0, " +
"mouseover@target1, mouseenter@target1, mouseout@target1, mouseleave@target1, " +
"mouseover@target0, mouseenter@target0, mouseout@target0, mouseleave@target0"
);
}, "Event log");
test_pointerEvent.done(); // complete test
}
function log_event(label) {
event_log.push(label);
}
function run() {
on_event(document.getElementById("done"), "click", end_of_interaction);
var target_list = ["target0", "target1"];
var pointer_event_list = ["pointerenter", "pointerleave", "pointerover", "pointerout", "pointerdown"];
var mouse_event_list = ["mouseenter", "mouseleave", "mouseover", "mouseout"];
target_list.forEach(function(targetId) {
var target = document.getElementById(targetId);
pointer_event_list.forEach(function(eventName) {
on_event(target, eventName, function (event) {
var label = event.type + "@" + targetId;
detected_pointertypes[event.pointerType] = true;
if (!event.isPrimary) {
test(function () {
assert_unreached("Non-primary pointer " + label);
}, "Non-primary pointer " + label);
}
if (event.type === "pointerenter") {
var pointer_id = event.pointerId;
if (current_node_for_id[pointer_id] !== undefined) {
test(function () {
assert_unreached("Double entry " + label);
}, "Double entry " + label);
}
current_node_for_id[pointer_id] = event.target;
// Test that two different pointing devices are used
if (first_entry_pointer_id === -1) {
first_entry_pointer_id = pointer_id;
} else if (second_entry_pointer_id === -1) {
second_entry_pointer_id = pointer_id;
test(function () {
assert_true(first_entry_pointer_id !== second_entry_pointer_id);
}, "Different pointing devices");
}
} else if (event.type === "pointerleave") {
var pointer_id = event.pointerId;
if (current_node_for_id[pointer_id] !== event.target) {
test(function () {
assert_unreached("Double exit " + label);
}, "Double exit " + label);
}
current_node_for_id[pointer_id] = undefined;
}
});
});
mouse_event_list.forEach(function(eventName) {
on_event(target, eventName, function (event) {
log_event(event.type + "@" + targetId);
});
});
});
}
</script>
<style>
#target0, #target1 {
margin: 20px;
}
#done {
margin: 20px;
border: 2px solid black;
}
</style>
</head>
<body onload="run()">
<h1>Pointer Event: Boundary compatibility events for multiple primary pointers</h1>
<h4>
When more than one primary pointers are active, each will have an independent sequence of pointer boundary events but the compatibilty mouse boundary events have their own sequence.
</h4>
Instruction:
<ol>
<li>Move the mouse directly into Target0 (without going through Target1), and then leave the mouse there unmoved.</li>
<li>Tap directly on Target1 with a finger or a stylus, and then lift the finger/stylus off the screen/digitizer without crossing Target1 boundary.</li>
<li>Move the mouse into Target0 (if not there already) and move inside it.</li>
<li>Click Done (without passing over Target1).</li>
</ol>
<div id="done">
Done
</div>
<div id="target0">
Target0
</div>
<div id="target1">
Target1
</div>
<div id="complete-notice">
<p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
<p>The following events were logged: <span id="event-log"></span>.</p>
</div>
<div id="log"></div>
</body>
</html>

View file

@ -77,6 +77,10 @@ display: none;
font-weight: bold;
}
#event-log {
font-weight: bold;
}
#listener {
background: orange;
border: 1px solid orange;

View file

@ -105,6 +105,14 @@ function showPointerTypes() {
complete_notice.style.display = "block";
}
function showLoggedEvents() {
var event_log_elem = document.getElementById("event-log");
event_log_elem.innerHTML = event_log.length ? event_log.join(", ") : "(none)";
var complete_notice = document.getElementById("complete-notice");
complete_notice.style.display = "block";
}
function log(msg, el) {
if (++count > 10){
count = 0;
@ -167,4 +175,4 @@ function rPointerCapture(e) {
}
catch(e) {
}
}
}

View file

@ -0,0 +1,101 @@
<!doctype html>
<html>
<head>
<title>Pointer Event: Suppress compatibility mouse events on click</title>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<link rel="author" title="Google" href="http://www.google.com "/>
<meta name="assert" content="When a pointerdown is canceled, a click/tap shouldn't fire any compatibility mouse events."/>
<link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript" src="pointerevent_support.js"></script>
<script type="text/javascript">
var test_pointerEvent = async_test("Suppress compat mouse events on click");
add_completion_callback(end_of_test);
var detected_pointertypes = {};
var event_log = [];
function end_of_test() {
showLoggedEvents();
showPointerTypes();
}
function end_of_interaction() {
test(function () {
assert_equals(event_log.join(", "),
"mousedown@target1, mouseup@target1");
}, "Event log");
test_pointerEvent.done(); // complete test
}
function run() {
on_event(document.getElementById("done"), "click", end_of_interaction);
var target_list = ["target0", "target1"];
var pointer_event_list = ["pointerdown"];
var mouse_event_list = ["mousedown", "mouseup"];
target_list.forEach(function(targetId) {
var target = document.getElementById(targetId);
pointer_event_list.forEach(function(eventName) {
on_event(target, eventName, function (event) {
detected_pointertypes[event.pointerType] = true;
var label = event.type + "@" + targetId;
test(function () {
assert_true(event.isPrimary);
}, "primary pointer " + label);
if (label === "pointerdown@target0")
event.preventDefault();
});
});
mouse_event_list.forEach(function(eventName) {
on_event(target, eventName, function (event) {
event_log.push(event.type + "@" + targetId);
});
});
});
}
</script>
<style>
#target0, #target1 {
margin: 20px;
}
#done {
margin: 20px;
border: 2px solid black;
}
</style>
</head>
<body onload="run()">
<h1>Pointer Event: Suppress compatibility mouse events on click</h1>
<h4>
When a pointerdown is canceled, a click/tap shouldn't fire any compatibility mouse events.
</h4>
<ol>
<li> Click or tap on Target0.</li>
<li> Click or tap on Target1.</li>
<li> Click Done.</li>
</ol>
<div id="target0">
Target0
</div>
<div id="target1">
Target1
</div>
<div id="done">
Done
</div>
<div id="complete-notice">
<p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
<p>The following events were logged: <span id="event-log"></span>.</p>
</div>
<div id="log"></div>
</body>
</html>

View file

@ -0,0 +1,114 @@
<!doctype html>
<html>
<head>
<title>Pointer Event: Suppress compatibility mouse events on drag</title>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<link rel="author" title="Google" href="http://www.google.com "/>
<meta name="assert" content="When a pointerdown is canceled, a mouse drag shouldn't fire any compatibility mouse events."/>
<link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript" src="pointerevent_support.js"></script>
<script type="text/javascript">
var test_pointerEvent = async_test("Suppress compat mouse events on drag");
add_completion_callback(end_of_test);
var detected_pointertypes = {};
var event_log = [];
function end_of_test() {
showLoggedEvents();
showPointerTypes();
}
var include_next_mousemove = false;
// Limits logging/testing of mousemove.
function drop_event(event_type) {
return (event_type == "mousemove" && !include_next_mousemove);
}
function end_of_interaction() {
test(function () {
assert_equals(event_log.join(", "),
"mousedown@target1, mousemove@target1, mouseup@target1");
}, "Event log");
test_pointerEvent.done(); // complete test
}
function run() {
on_event(document.getElementById("done"), "click", end_of_interaction);
var target_list = ["target0", "target1"];
var pointer_event_list = ["pointerdown"];
var mouse_event_list = ["mousedown", "mouseup", "mousemove"];
target_list.forEach(function(targetId) {
var target = document.getElementById(targetId);
pointer_event_list.forEach(function(eventName) {
on_event(target, eventName, function (event) {
detected_pointertypes[event.pointerType] = true;
var label = event.type + "@" + targetId;
test(function () {
assert_true(event.isPrimary);
}, "primary pointer " + label);
if (label === "pointerdown@target0")
event.preventDefault();
});
});
mouse_event_list.forEach(function(eventName) {
on_event(target, eventName, function (event) {
if (drop_event(event.type))
return;
event_log.push(event.type + "@" + targetId);
include_next_mousemove = (event.type == "mousedown");
});
});
});
}
</script>
<style>
#target0, #target1 {
margin: 20px;
touch-action: none;
}
#done {
margin: 20px;
border: 2px solid black;
}
</style>
</head>
<body onload="run()">
<h1>Pointer Event: Suppress compatibility mouse events on drag</h1>
<h4>
When a pointerdown is canceled, a mouse drag shouldn't fire any compatibility mouse events.
</h4>
<ol>
<li> Drag mouse within Target0 &amp; release.</li>
<li> Drag mouse within Target1 &amp; release.</li>
<li> Click Done.</li>
</ol>
<div id="target0">
Target0
</div>
<div id="target1">
Target1
</div>
<div id="done">
Done
</div>
<div id="complete-notice">
<p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
<p>The following events were logged: <span id="event-log"></span>.</p>
</div>
<div id="log"></div>
</body>
</html>

View file

@ -307,6 +307,28 @@ IdlArray.prototype.recursively_get_implements = function(interface_name)
return ret;
};
function exposed_in(globals) {
if ('document' in self) {
return globals.indexOf("Window") >= 0;
}
if ('DedicatedWorkerGlobalScope' in self &&
self instanceof DedicatedWorkerGlobalScope) {
return globals.indexOf("Worker") >= 0 ||
globals.indexOf("DedicatedWorker") >= 0;
}
if ('SharedWorkerGlobalScope' in self &&
self instanceof SharedWorkerGlobalScope) {
return globals.indexOf("Worker") >= 0 ||
globals.indexOf("SharedWorker") >= 0;
}
if ('ServiceWorkerGlobalScope' in self &&
self instanceof ServiceWorkerGlobalScope) {
return globals.indexOf("Worker") >= 0 ||
globals.indexOf("ServiceWorker") >= 0;
}
throw "Unexpected global object";
}
//@}
IdlArray.prototype.test = function()
//@{
@ -353,6 +375,23 @@ IdlArray.prototype.test = function()
}
this["implements"] = {};
Object.getOwnPropertyNames(this.members).forEach(function(memberName) {
var member = this.members[memberName];
if (!(member instanceof IdlInterface)) {
return;
}
var exposed = member.extAttrs.filter(function(a) { return a.name == "Exposed" });
if (exposed.length > 1) {
throw "Unexpected Exposed extended attributes on " + memberName + ": " + exposed;
}
var globals = exposed.length === 1
? exposed[0].rhs.value
: ["Window"];
member.exposed = exposed_in(globals);
}.bind(this));
// Now run test() on every member, and test_object() for every object.
for (var name in this.members)
{
@ -678,6 +717,13 @@ IdlInterface.prototype.test = function()
return;
}
if (!this.exposed) {
test(function() {
assert_false(this.name in self);
}.bind(this), this.name + " interface: existence and properties of interface object");
return;
}
if (!this.untested)
{
// First test things to do with the exception/interface object and
@ -701,7 +747,6 @@ IdlInterface.prototype.test_self = function()
test(function()
{
// This function tests WebIDL as of 2015-01-13.
// TODO: Consider [Exposed].
// "For every interface that is exposed in a given ECMAScript global
// environment and:

View file

@ -471,6 +471,11 @@ policies and contribution forms [3].
self instanceof ServiceWorkerGlobalScope) {
return new ServiceWorkerTestEnvironment();
}
if ('WorkerGlobalScope' in self &&
self instanceof WorkerGlobalScope) {
return new DedicatedWorkerTestEnvironment();
}
throw new Error("Unsupported test environment");
}

View file

@ -11,7 +11,6 @@
<template id='collection-template'>
<img>
<embed></embed>
<plugin></plugin>
<applet></applet>
<object type='application/x-java-applet'></object>
<a href='http://example.com'></a>

View file

@ -1,86 +0,0 @@
<!DOCTYPE html>
<!--
Distributed under both the W3C Test Suite License [1] and the W3C
3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
policies and contribution forms [3].
[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
[3] http://www.w3.org/2004/10/27-testcases
-->
<html>
<head>
<title>Shadow DOM Test: A_07_02_01</title>
<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
<meta name="assert" content="User Interaction: The navigation order within a shadow tree must be computed as a list of focusable elements in tree order as-rendered">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../../../html/resources/common.js"></script>
<script src="../../../resources/shadow-dom-utils.js"></script>
</head>
<body>
<div id="log"></div>
<script>
var A_07_02_01_T01 = async_test('A_07_02_01_T01');
A_07_02_01_T01.step(unit(function (ctx) {
var counter = 0;
var d = newRenderedHTMLDocument(ctx);
var chb1 = d.createElement('input');
chb1.setAttribute('type', 'checkbox');
chb1.setAttribute('id', 'chb1');
chb1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
}), false);
d.body.appendChild(chb1);
var host = d.createElement('div');
d.body.appendChild(host);
var s = host.attachShadow({mode: 'open'});
var inp1 = d.createElement('input');
inp1.setAttribute('type', 'text');
inp1.setAttribute('id', 'shInp1');
inp1.setAttribute('value', 'Input 1');
inp1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
}), false);
s.appendChild(inp1);
var inp2 = d.createElement('input');
inp2.setAttribute('type', 'text');
inp2.setAttribute('id', 'shInp2');
inp2.setAttribute('value', 'Input 2');
inp2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
}), false);
s.appendChild(inp2);
var chb2 = d.createElement('input');
chb2.setAttribute('type', 'checkbox');
chb2.setAttribute('id', 'chb2');
chb2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
}), false);
d.body.appendChild(chb2);
chb1.focus();
//simulate TAB clicks
fireKeyboardEvent(d, chb1, 'U+0009');
fireKeyboardEvent(d, inp1, 'U+0009');
fireKeyboardEvent(d, inp2, 'U+0009');
fireKeyboardEvent(d, chb2, 'U+0009');
A_07_02_01_T01.done();
}));
</script>
</body>
</html>

View file

@ -1,238 +0,0 @@
<!DOCTYPE html>
<!--
Distributed under both the W3C Test Suite License [1] and the W3C
3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
policies and contribution forms [3].
[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
[3] http://www.w3.org/2004/10/27-testcases
-->
<html>
<head>
<title>Shadow DOM Test: A_07_02_02</title>
<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
<meta name="assert" content="User Interaction: The navigation order within a shadow tree must be computed as a list of focusable elements in tree order as-rendered with the exception of any elements, distributed its insertion points, and is called shadow DOM navigation order.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../../../html/resources/common.js"></script>
<script src="../../../resources/shadow-dom-utils.js"></script>
</head>
<body>
<div id="log"></div>
<script>
var A_07_02_02_T01 = async_test('A_07_02_02_T01');
var A_07_02_02_T02 = async_test('A_07_02_02_T02');
A_07_02_02_T01.step(unit(function (ctx) {
var counter = 0;
var expectations = [];
var d = newRenderedHTMLDocument(ctx);
var host = d.createElement('div');
d.body.appendChild(host);
var chb1 = d.createElement('input');
chb1.setAttribute('type', 'checkbox');
chb1.setAttribute('id', 'chb1');
chb1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
assert_true(false, 'Element shouldn\'t be rendered');
}), false);
host.appendChild(chb1);
var chb2 = d.createElement('input');
chb2.setAttribute('type', 'checkbox');
chb2.setAttribute('id', 'chb2');
chb2.setAttribute('slot', 'shadow');
chb2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
expectations[1] = true;
}), false);
expectations[1] = false;
host.appendChild(chb2);
var chb3 = d.createElement('input');
chb3.setAttribute('type', 'checkbox');
chb3.setAttribute('id', 'chb3');
chb3.setAttribute('slot', 'shadow');
chb3.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
expectations[2] = true;
}), false);
expectations[2] = false;
host.appendChild(chb3);
var s = host.attachShadow({mode: 'open'});
var div = d.createElement('div');
div.innerHTML = '<slot name="shadow"></slot>';
s.appendChild(div);
var inp1 = d.createElement('input');
inp1.setAttribute('type', 'text');
inp1.setAttribute('id', 'shInp1');
inp1.setAttribute('value', 'Input 1');
inp1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
expectations[3] = false;
}), false);
expectations[3] = true;
s.appendChild(inp1);
var inp2 = d.createElement('input');
inp2.setAttribute('type', 'text');
inp2.setAttribute('id', 'shInp2');
inp2.setAttribute('value', 'Input 2');
inp2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
expectations[4] = false;
}), false);
expectations[4] = true;
s.appendChild(inp2);
var chb4 = d.createElement('input');
chb4.setAttribute('type', 'checkbox');
chb4.setAttribute('id', 'chb4');
chb4.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
assert_equals(counter++, 2, 'Point 5: wrong focus navigation order');
expectations[5] = true;
}), false);
expectations[5] = false;
d.body.appendChild(chb4);
chb2.focus();
//simulate TAB clicks
fireKeyboardEvent(d, chb2, 'U+0009');
fireKeyboardEvent(d, chb3, 'U+0009');
fireKeyboardEvent(d, inp1, 'U+0009');
fireKeyboardEvent(d, inp2, 'U+0009');
fireKeyboardEvent(d, chb4, 'U+0009');
for (var i = 1; i < expectations.length; i++) {
if (!expectations[i]) {
assert_true(false, 'Point ' + i + ' event listener was not invoked');
}
}
A_07_02_02_T01.done();
}));
A_07_02_02_T02.step(unit(function (ctx) {
var counter = 0;
var expectations = [];
var d = newRenderedHTMLDocument(ctx);
var chb0 = d.createElement('input');
chb0.setAttribute('type', 'checkbox');
chb0.setAttribute('id', 'chb0');
d.body.appendChild(chb0);
var host = d.createElement('div');
d.body.appendChild(host);
var chb1 = d.createElement('input');
chb1.setAttribute('type', 'checkbox');
chb1.setAttribute('id', 'chb1');
chb1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
assert_true(false, 'Element shouldn\'t be rendered');
}), false);
host.appendChild(chb1);
var chb2 = d.createElement('input');
chb2.setAttribute('type', 'checkbox');
chb2.setAttribute('id', 'chb2');
chb2.setAttribute('slot', 'shadow');
chb2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
expectations[1] = true;
}), false);
expectations[1] = false;
host.appendChild(chb2);
var chb3 = d.createElement('input');
chb3.setAttribute('type', 'checkbox');
chb3.setAttribute('id', 'chb3');
chb3.setAttribute('slot', 'shadow');
chb3.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
expectations[2] = true;
}), false);
expectations[2] = false;
host.appendChild(chb3);
var s = host.attachShadow({mode: 'open'});
var div = d.createElement('div');
div.innerHTML = '<slot name="shadow"></slot>';
s.appendChild(div);
var inp1 = d.createElement('input');
inp1.setAttribute('type', 'text');
inp1.setAttribute('id', 'shInp1');
inp1.setAttribute('value', 'Input 1');
inp1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
expectations[3] = true;
}), false);
expectations[3] = false;
s.appendChild(inp1);
var inp2 = d.createElement('input');
inp2.setAttribute('type', 'text');
inp2.setAttribute('id', 'shInp2');
inp2.setAttribute('value', 'Input 2');
inp2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
expectations[4] = true;
}), false);
expectations[4] = false;
s.appendChild(inp2);
var chb4 = d.createElement('input');
chb4.setAttribute('type', 'checkbox');
chb4.setAttribute('id', 'chb4');
chb4.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
assert_equals(counter++, 4, 'Point 5: wrong focus navigation order');
expectations[5] = true;
}), false);
expectations[5] = false;
d.body.appendChild(chb4);
chb0.focus();
//simulate TAB clicks
fireKeyboardEvent(d, inp1, 'U+0009');
fireKeyboardEvent(d, inp2, 'U+0009');
fireKeyboardEvent(d, chb2, 'U+0009');
fireKeyboardEvent(d, chb3, 'U+0009');
fireKeyboardEvent(d, chb4, 'U+0009');
for (var i = 1; i < expectations.length; i++) {
if (!expectations[i]) {
assert_true(false, 'Point ' + i + ' event listener was not invoked');
}
}
A_07_02_02_T02.done();
}));
</script>
</body>
</html>

View file

@ -1,237 +0,0 @@
<!DOCTYPE html>
<!--
Distributed under both the W3C Test Suite License [1] and the W3C
3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
policies and contribution forms [3].
[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
[3] http://www.w3.org/2004/10/27-testcases
-->
<html>
<head>
<title>Shadow DOM Test: A_07_02_03</title>
<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
<meta name="assert" content="User Interaction: For sequential focus navigation, the shadow DOM navigation order sequence must be inserted into the document navigation order in place of the shadow host as if the shadow host were assigned the value of auto for determining its position and shadow host is not focusable">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../../../html/resources/common.js"></script>
<script src="../../../resources/shadow-dom-utils.js"></script>
</head>
<body>
<div id="log"></div>
<script>
var A_07_02_03_T01 = async_test('A_07_02_03_T01');
A_07_02_03_T01.step(unit(function (ctx) {
var counter = 0;
var invoked = [];
var d = newRenderedHTMLDocument(ctx);
var chb1 = d.createElement('input');
chb1.setAttribute('type', 'checkbox');
// TODO according CSS3 nav-index is a replacement for tabindex
//chb1.setAttribute('nav-index', '4');
chb1.setAttribute('tabindex', '4');
chb1.setAttribute('id', 'chb1');
chb1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
assert_equals(counter++, 1, 'Point 1: wrong focus navigation order');
invoked[1] = true;
}), false);
invoked[1] = false;
d.body.appendChild(chb1);
var host = d.createElement('div');
d.body.appendChild(host);
var s = host.attachShadow({mode: 'open'});
var inp1 = d.createElement('input');
inp1.setAttribute('type', 'text');
inp1.setAttribute('id', 'shInp1');
//inp1.setAttribute('nav-index', '3');
inp1.setAttribute('tabindex', '3');
inp1.setAttribute('value', 'Input 1');
inp1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
assert_equals(counter++, 4, 'Point 2: wrong focus navigation order');
invoked[2] = true;
}), false);
invoked[2] = false;
s.appendChild(inp1);
var inp2 = d.createElement('input');
inp2.setAttribute('type', 'text');
inp2.setAttribute('id', 'shInp2');
//inp2.setAttribute('nav-index', '2');
inp2.setAttribute('tabindex', '2');
inp2.setAttribute('value', 'Input 2');
inp2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
assert_equals(counter++, 3, 'Point 3: wrong focus navigation order');
invoked[3] = true;
}), false);
invoked[3] = false;
s.appendChild(inp2);
var chb2 = d.createElement('input');
chb2.setAttribute('type', 'checkbox');
chb2.setAttribute('id', 'chb2');
//chb2.setAttribute('nav-index', '1');
chb2.setAttribute('tabindex', '1');
chb2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
assert_equals(counter++, 0, 'Point 4: wrong focus navigation order');
invoked[4] = true;
}), false);
invoked[4] = false;
d.body.appendChild(chb2);
var chb3 = d.createElement('input');
chb3.setAttribute('type', 'checkbox');
chb3.setAttribute('id', 'chb3');
//chb3.setAttribute('nav-index', '5');
chb3.setAttribute('tabindex', '5');
chb3.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
assert_equals(counter++, 2, 'Point 5: wrong focus navigation order');
invoked[5] = true;
}), false);
invoked[5] = false;
d.body.appendChild(chb3);
chb2.focus();
//simulate TAB clicks. Expected order: chb2, chb1, chb3, inp2, inp1
fireKeyboardEvent(d, chb2, 'U+0009');
fireKeyboardEvent(d, chb1, 'U+0009');
fireKeyboardEvent(d, chb3, 'U+0009');
fireKeyboardEvent(d, inp2, 'U+0009');
fireKeyboardEvent(d, inp1, 'U+0009');
for (var i = 1; i < invoked.length; i++) {
if (!invoked[i]) {
assert_true(false, 'Piont ' + i + ' event listener was not invoked');
}
}
A_07_02_03_T01.done();
}));
// test nodes, distributed into insertion points
var A_07_02_03_T02 = async_test('A_07_02_03_T02');
A_07_02_03_T02.step(unit(function (ctx) {
var counter = 0;
var invoked = [];
var d = newRenderedHTMLDocument(ctx);
var host = d.createElement('div');
d.body.appendChild(host);
var chb1 = d.createElement('input');
chb1.setAttribute('type', 'checkbox');
chb1.setAttribute('id', 'chb1');
chb1.setAttribute('tabindex', '1');
chb1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
invoked[1] = true;
}), false);
invoked[1] = false;
d.body.appendChild(chb1);
var chb2 = d.createElement('input');
chb2.setAttribute('type', 'checkbox');
chb2.setAttribute('id', 'chb2');
chb2.setAttribute('slot', 'shadow');
chb2.setAttribute('tabindex', '3');
chb2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
assert_equals(counter++, 2, 'Point 2: wrong focus navigation order');
invoked[2] = true;
}), false);
invoked[2] = false;
host.appendChild(chb2);
var chb3 = d.createElement('input');
chb3.setAttribute('type', 'checkbox');
chb3.setAttribute('id', 'chb3');
chb3.setAttribute('slot', 'shadow');
chb3.setAttribute('tabindex', '2');
chb3.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
assert_equals(counter++, 1, 'Point 3: wrong focus navigation order');
invoked[3] = true;
}), false);
invoked[3] = false;
host.appendChild(chb3);
var s = host.attachShadow({mode: 'open'});
var div = d.createElement('div');
div.innerHTML = '<slot name="shadow"></slot>';
s.appendChild(div);
var inp1 = d.createElement('input');
inp1.setAttribute('type', 'text');
inp1.setAttribute('id', 'shInp1');
inp1.setAttribute('value', 'Input 1');
inp1.setAttribute('tabindex', '4');
inp1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
assert_equals(counter++, 4, 'Point 4: wrong focus navigation order');
invoked[4] = true;
}), false);
invoked[4] = false;
s.appendChild(inp1);
var inp2 = d.createElement('input');
inp2.setAttribute('type', 'text');
inp2.setAttribute('id', 'shInp2');
inp2.setAttribute('value', 'Input 2');
inp2.setAttribute('tabindex', '5');
inp2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
assert_equals(counter++, 5, 'Point 5: wrong focus navigation order');
invoked[5] = true;
}), false);
invoked[5] = false;
s.appendChild(inp2);
var chb4 = d.createElement('input');
chb4.setAttribute('type', 'checkbox');
chb4.setAttribute('id', 'chb4');
chb4.setAttribute('tabindex', '6');
chb4.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
assert_equals(counter++, 3, 'Point 6: wrong focus navigation order');
invoked[6] = true;
}), false);
invoked[6] = false;
d.body.appendChild(chb4);
chb1.focus();
//simulate TAB clicks
//Expected order: chb1, chb3, chb2, chb4, inp1, inp2
fireKeyboardEvent(d, chb1, 'U+0009');
fireKeyboardEvent(d, chb3, 'U+0009');
fireKeyboardEvent(d, chb2, 'U+0009');
fireKeyboardEvent(d, chb4, 'U+0009');
fireKeyboardEvent(d, inp1, 'U+0009');
fireKeyboardEvent(d, inp2, 'U+0009');
for (var i = 1; i < invoked.length; i++) {
if (!invoked[i]) {
assert_true(false, 'Piont ' + i + ' event listener was not invoked');
}
}
A_07_02_03_T02.done();
}));
</script>
</body>
</html>

View file

@ -1,427 +0,0 @@
<!DOCTYPE html>
<!--
Distributed under both the W3C Test Suite License [1] and the W3C
3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
policies and contribution forms [3].
[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
[3] http://www.w3.org/2004/10/27-testcases
-->
<html>
<head>
<title>Shadow DOM Test: A_07_02_04</title>
<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
<meta name="assert" content="User Interaction: For sequential focus navigation, the shadow DOM navigation order sequence must be inserted into the document navigation order immediately after the shadow host, if the shadow host is focusable;">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../../../html/resources/common.js"></script>
<script src="../../../resources/shadow-dom-utils.js"></script>
</head>
<body>
<div id="log"></div>
<script>
var A_07_02_04_T01 = async_test('A_07_02_04_T01');
A_07_02_04_T01.step(unit(function (ctx) {
var counter = 0;
var invoked = [];
var d = newRenderedHTMLDocument(ctx);
var chb1 = d.createElement('input');
chb1.setAttribute('type', 'checkbox');
// TODO according CSS3 nav-index is a replacement for tabindex
//chb1.setAttribute('nav-index', '4');
chb1.setAttribute('tabindex', '1');
chb1.setAttribute('id', 'chb1');
chb1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
invoked[1] = true;
}), false);
invoked[1] = false;
d.body.appendChild(chb1);
var host = d.createElement('div');
//make shadow host focusable
host.setAttribute('tabindex', '3');
d.body.appendChild(host);
var s = host.attachShadow({mode: 'open'});
var inp1 = d.createElement('input');
inp1.setAttribute('type', 'text');
inp1.setAttribute('id', 'shInp1');
//inp1.setAttribute('nav-index', '3');
inp1.setAttribute('tabindex', '2');
inp1.setAttribute('value', 'Input 1');
inp1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
assert_equals(counter++, 3, 'Point 2: wrong focus navigation order');
invoked[2] = true;
}), false);
invoked[2] = false;
s.appendChild(inp1);
var inp2 = d.createElement('input');
inp2.setAttribute('type', 'text');
inp2.setAttribute('id', 'shInp2');
//inp2.setAttribute('nav-index', '2');
inp2.setAttribute('tabindex', '1');
inp2.setAttribute('value', 'Input 2');
inp2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
invoked[3] = true;
}), false);
invoked[3] = false;
s.appendChild(inp2);
var chb2 = d.createElement('input');
chb2.setAttribute('type', 'checkbox');
chb2.setAttribute('id', 'chb2');
//chb2.setAttribute('nav-index', '1');
chb2.setAttribute('tabindex', '2');
chb2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
assert_equals(counter++, 1, 'Point 4: wrong focus navigation order');
invoked[4] = true;
}), false);
invoked[4] = false;
d.body.appendChild(chb2);
var chb3 = d.createElement('input');
chb3.setAttribute('type', 'checkbox');
chb3.setAttribute('id', 'chb3');
//chb3.setAttribute('nav-index', '5');
chb3.setAttribute('tabindex', '4');
chb3.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
assert_equals(counter++, 4, 'Point 5: wrong focus navigation order');
invoked[5] = true;
}), false);
invoked[5] = false;
d.body.appendChild(chb3);
chb1.focus();
//simulate TAB clicks. Expected order: chb1, chb2, inp2, inp1, chb3
fireKeyboardEvent(d, chb1, 'U+0009');
fireKeyboardEvent(d, chb2, 'U+0009');
fireKeyboardEvent(d, inp2, 'U+0009');
fireKeyboardEvent(d, inp1, 'U+0009');
fireKeyboardEvent(d, chb3, 'U+0009');
for (var i = 1; i < invoked.length; i++) {
if (!invoked[i]) {
assert_true(false, 'Piont ' + i + ' event listener was not invoked');
}
}
A_07_02_04_T01.done();
}));
// test nodes, distributed into insertion points
var A_07_02_04_T02 = async_test('A_07_02_04_T02');
A_07_02_04_T02.step(unit(function (ctx) {
var counter = 0;
var invoked = [];
var d = newRenderedHTMLDocument(ctx);
var host = d.createElement('div');
host.setAttribute('tabindex', '3');
d.body.appendChild(host);
var chb1 = d.createElement('input');
chb1.setAttribute('type', 'checkbox');
chb1.setAttribute('id', 'chb1');
chb1.setAttribute('tabindex', '1');
chb1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
invoked[1] = true;
}), false);
invoked[1] = false;
d.body.appendChild(chb1);
var chb2 = d.createElement('input');
chb2.setAttribute('type', 'checkbox');
chb2.setAttribute('id', 'chb2');
chb2.setAttribute('slot', 'shadow');
chb2.setAttribute('tabindex', '3');
chb2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
assert_equals(counter++, 4, 'Point 2: wrong focus navigation order');
invoked[2] = true;
}), false);
invoked[2] = false;
host.appendChild(chb2);
var chb3 = d.createElement('input');
chb3.setAttribute('type', 'checkbox');
chb3.setAttribute('id', 'chb3');
chb3.setAttribute('slot', 'shadow');
chb3.setAttribute('tabindex', '2');
chb3.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
assert_equals(counter++, 1, 'Point 3: wrong focus navigation order');
invoked[3] = true;
}), false);
invoked[3] = false;
host.appendChild(chb3);
var s = host.attachShadow({mode: 'open'});
var div = d.createElement('div');
div.innerHTML = '<slot name="shadow"></slot>';
s.appendChild(div);
var inp1 = d.createElement('input');
inp1.setAttribute('type', 'text');
inp1.setAttribute('id', 'shInp1');
inp1.setAttribute('value', 'Input 1');
inp1.setAttribute('tabindex', '4');
inp1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
invoked[4] = true;
}), false);
invoked[4] = false;
s.appendChild(inp1);
var inp2 = d.createElement('input');
inp2.setAttribute('type', 'text');
inp2.setAttribute('id', 'shInp2');
inp2.setAttribute('value', 'Input 2');
inp2.setAttribute('tabindex', '4');
inp2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
assert_equals(counter++, 5, 'Point 5: wrong focus navigation order');
invoked[5] = true;
}), false);
invoked[5] = false;
d.body.appendChild(inp2);
var chb4 = d.createElement('input');
chb4.setAttribute('type', 'checkbox');
chb4.setAttribute('id', 'chb4');
chb4.setAttribute('tabindex', '2');
chb4.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
assert_equals(counter++, 2, 'Point 6: wrong focus navigation order');
invoked[6] = true;
}), false);
invoked[6] = false;
d.body.appendChild(chb4);
chb1.focus();
//simulate TAB clicks
//Expected order: chb1, chb3, chb4, chb2, inp1, inp2
fireKeyboardEvent(d, chb1, 'U+0009');
fireKeyboardEvent(d, chb3, 'U+0009');
fireKeyboardEvent(d, chb4, 'U+0009');
fireKeyboardEvent(d, chb2, 'U+0009');
fireKeyboardEvent(d, inp1, 'U+0009');
fireKeyboardEvent(d, inp2, 'U+0009');
for (var i = 1; i < invoked.length; i++) {
if (!invoked[i]) {
assert_true(false, 'Point ' + i + ' event listener was not invoked');
}
}
A_07_02_04_T02.done();
}));
// Shadow root is the first in nav order
var A_07_02_04_T03 = async_test('A_07_02_04_T03');
A_07_02_04_T03.step(unit(function (ctx) {
var counter = 0;
var invoked = [];
var d = newRenderedHTMLDocument(ctx);
var chb1 = d.createElement('input');
chb1.setAttribute('type', 'checkbox');
chb1.setAttribute('tabindex', '3');
chb1.setAttribute('id', 'chb1');
chb1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
assert_equals(counter++, 4, 'Point 1: wrong focus navigation order');
invoked[1] = true;
}), false);
invoked[1] = false;
d.body.appendChild(chb1);
var host = d.createElement('div');
host.setAttribute('tabindex', '1');
d.body.appendChild(host);
var s = host.attachShadow({mode: 'open'});
var inp1 = d.createElement('input');
inp1.setAttribute('type', 'text');
inp1.setAttribute('id', 'shInp1');
inp1.setAttribute('tabindex', '2');
inp1.setAttribute('value', 'Input 1');
inp1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
invoked[2] = true;
}), false);
invoked[2] = false;
s.appendChild(inp1);
var inp2 = d.createElement('input');
inp2.setAttribute('type', 'text');
inp2.setAttribute('id', 'shInp2');
inp2.setAttribute('tabindex', '1');
inp2.setAttribute('value', 'Input 2');
inp2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
assert_equals(counter++, 0, 'Point 3: wrong focus navigation order');
invoked[3] = true;
}), false);
invoked[3] = false;
s.appendChild(inp2);
var chb2 = d.createElement('input');
chb2.setAttribute('type', 'checkbox');
chb2.setAttribute('id', 'chb2');
chb2.setAttribute('tabindex', '3');
chb2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
assert_equals(counter++, 2, 'Point 4: wrong focus navigation order');
invoked[4] = true;
}), false);
invoked[4] = false;
s.appendChild(chb2);
var chb3 = d.createElement('input');
chb3.setAttribute('type', 'checkbox');
chb3.setAttribute('id', 'chb3');
chb3.setAttribute('tabindex', '2');
chb3.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
assert_equals(counter++, 3, 'Point 5: wrong focus navigation order');
invoked[5] = true;
}), false);
invoked[5] = false;
d.body.appendChild(chb3);
host.focus();
//simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1
fireKeyboardEvent(d, inp2, 'U+0009');
fireKeyboardEvent(d, inp1, 'U+0009');
fireKeyboardEvent(d, chb2, 'U+0009');
fireKeyboardEvent(d, chb3, 'U+0009');
fireKeyboardEvent(d, chb1, 'U+0009');
for (var i = 1; i < invoked.length; i++) {
if (!invoked[i]) {
assert_true(false, 'Piont ' + i + ' event listener was not invoked');
}
}
A_07_02_04_T03.done();
}));
//Shadow root is the last in nav order
var A_07_02_04_T04 = async_test('A_07_02_04_T04');
A_07_02_04_T04.step(unit(function (ctx) {
var counter = 0;
var invoked = [];
var d = newRenderedHTMLDocument(ctx);
var chb1 = d.createElement('input');
chb1.setAttribute('type', 'checkbox');
chb1.setAttribute('tabindex', '1');
chb1.setAttribute('id', 'chb1');
chb1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
invoked[1] = true;
}), false);
invoked[1] = false;
d.body.appendChild(chb1);
var host = d.createElement('div');
host.setAttribute('tabindex', '3');
d.body.appendChild(host);
var s = host.attachShadow({mode: 'open'});
var inp1 = d.createElement('input');
inp1.setAttribute('type', 'text');
inp1.setAttribute('id', 'shInp1');
inp1.setAttribute('tabindex', '2');
inp1.setAttribute('value', 'Input 1');
inp1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
assert_equals(counter++, 3, 'Point 2: wrong focus navigation order');
invoked[2] = true;
}), false);
invoked[2] = false;
s.appendChild(inp1);
var inp2 = d.createElement('input');
inp2.setAttribute('type', 'text');
inp2.setAttribute('id', 'shInp2');
inp2.setAttribute('tabindex', '1');
inp2.setAttribute('value', 'Input 2');
inp2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
invoked[3] = true;
}), false);
invoked[3] = false;
s.appendChild(inp2);
var chb2 = d.createElement('input');
chb2.setAttribute('type', 'checkbox');
chb2.setAttribute('id', 'chb2');
chb2.setAttribute('tabindex', '3');
chb2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
assert_equals(counter++, 4, 'Point 4: wrong focus navigation order');
invoked[4] = true;
}), false);
invoked[4] = false;
s.appendChild(chb2);
var chb3 = d.createElement('input');
chb3.setAttribute('type', 'checkbox');
chb3.setAttribute('id', 'chb3');
chb3.setAttribute('tabindex', '2');
chb3.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
assert_equals(counter++, 1, 'Point 5: wrong focus navigation order');
invoked[5] = true;
}), false);
invoked[5] = false;
d.body.appendChild(chb3);
chb1.focus();
//simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1
fireKeyboardEvent(d, chb1, 'U+0009');
fireKeyboardEvent(d, chb3, 'U+0009');
fireKeyboardEvent(d, inp2, 'U+0009');
fireKeyboardEvent(d, inp1, 'U+0009');
fireKeyboardEvent(d, chb2, 'U+0009');
for (var i = 1; i < invoked.length; i++) {
if (!invoked[i]) {
assert_true(false, 'Piont ' + i + ' event listener was not invoked');
}
}
A_07_02_04_T04.done();
}));
</script>
</body>
</html>

View file

@ -114,7 +114,7 @@ test(() => {
test(() => {
for (const highWaterMark of [-1, -Infinity]) {
for (const highWaterMark of [-1, -Infinity, NaN, 'foo', {}]) {
assert_throws(new RangeError(), () => {
new ReadableStream({}, {
size() {
@ -125,17 +125,6 @@ test(() => {
}, 'construction should throw a RangeError for ' + highWaterMark);
}
for (const highWaterMark of [NaN, 'foo', {}]) {
assert_throws(new TypeError(), () => {
new ReadableStream({}, {
size() {
return 1;
},
highWaterMark
});
}, 'construction should throw a TypeError for ' + highWaterMark);
}
}, 'Readable stream: invalid strategy.highWaterMark');
promise_test(() => {

View file

@ -252,7 +252,7 @@ class OpenSSLEnvironment(object):
with open(path("index.txt"), "w"):
pass
with open(path("serial"), "w") as f:
serial = str(random.randint(0, 1000000))
serial = "%x" % random.randint(0, 1000000)
if len(serial) % 2:
serial = "0" + serial
f.write(serial)

View file

@ -12,17 +12,17 @@ Guidelines for writing tests
For example, if you want to test setting the start time, you might be
tempted to put all the tests in:
> `/web-animations/Animation/startTime.html`
> `/web-animations/interfaces/Animation/startTime.html`
However, in the spec most of the logic is in the &ldquo;Set the animation
start time&ldquo; procedure in the &ldquo;Timing model&rdquo; section.
Instead, try something like:
> * `/web-animations/timing-model/animation/set-the-animation-start-time.html`<br>
> * `/web-animations/timing-model/animations/set-the-animation-start-time.html`<br>
> Tests all the branches and inputs to the procedure as defined in the
> spec (using the `Animation.startTime` API).
> * `/web-animations/Animation/startTime.html`<br>
> * `/web-animations/interfaces/Animation/startTime.html`<br>
> Tests API-layer specific issues like mapping unresolved values to
> null, etc.

View file

@ -13,7 +13,7 @@
promise_test(function(t) {
var div = createDiv(t);
var animation = div.animate({transform: ['none', 'translate(100px)']},
var animation = div.animate({transform: ['translate(100px)', 'translate(100px)']},
100 * MS_PER_SEC);
return animation.ready.then(function() {
assert_not_equals(getComputedStyle(div).transform, 'none',
@ -26,7 +26,7 @@ promise_test(function(t) {
test(function(t) {
var div = createDiv(t);
var animation = div.animate({marginLeft: ['0px', '100px']},
var animation = div.animate({marginLeft: ['100px', '200px']},
100 * MS_PER_SEC);
animation.effect.timing.easing = 'linear';
animation.cancel();
@ -34,7 +34,7 @@ test(function(t) {
'margin-left style is not animated after cancelling');
animation.currentTime = 50 * MS_PER_SEC;
assert_equals(getComputedStyle(div).marginLeft, '50px',
assert_equals(getComputedStyle(div).marginLeft, '150px',
'margin-left style is updated when cancelled animation is'
+ ' seeked');
}, 'After cancelling an animation, it can still be seeked');