Update web-platform-tests to revision 95aad3bd9b82b5c65d84d53517b65ba084de9394

This commit is contained in:
Ms2ger 2016-02-11 17:10:01 +01:00
parent 5942e9e3cb
commit e8ed816728
145 changed files with 2024 additions and 578 deletions

View file

@ -0,0 +1,3 @@
@jdm
@zqzhang
@Ms2ger

View file

@ -0,0 +1,6 @@
@inexorabletash
@plehegar
@zqzhang
@zcorpan
@jdm
@Ms2ger

View file

@ -0,0 +1,8 @@
@Velmont
@inexorabletash
@chunywang
@dumbmatter
@zqzhang
@yunxiaoxie
@zhaozihao
@foolip

View file

@ -17,13 +17,16 @@
var store = db.createObjectStore("store", { keyPath: "key" });
var index = store.createIndex("index", "indexedProperty");
store.add({ key: 1, indexedProperty: "data" });
}
open_rq.onsuccess = function(e) {
db = e.target.result;
var tx = db.transaction('store');
var index = tx.objectStore('store').index('index');
tx.abort();
e.target.transaction.abort();
assert_throws("InvalidStateError", function(){
assert_throws("TransactionInactiveError", function(){
index.get("data");
});
t.done();
}
</script>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>IDBIndex.get() - throw InvalidStateError on index deleted by aborted upgrade</title>
<link rel="help" href="https://w3c.github.io/IndexedDB/#dom-idb">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=support.js></script>
<div id="log"></div>
<script>
var db,
t = async_test();
var open_rq = createdb(t);
open_rq.onupgradeneeded = function(e) {
db = e.target.result;
var store = db.createObjectStore("store", { keyPath: "key" });
var index = store.createIndex("index", "indexedProperty");
store.add({ key: 1, indexedProperty: "data" });
e.target.transaction.abort();
assert_throws("InvalidStateError", function(){
index.get("data");
});
t.done();
}
</script>

View file

@ -17,13 +17,16 @@
var store = db.createObjectStore("store", { keyPath: "key" });
var index = store.createIndex("index", "indexedProperty");
store.add({ key: 1, indexedProperty: "data" });
}
open_rq.onsuccess = function(e) {
db = e.target.result;
var tx = db.transaction('store');
var index = tx.objectStore('store').index('index');
tx.abort();
e.target.transaction.abort();
assert_throws("InvalidStateError", function(){
assert_throws("TransactionInactiveError", function(){
index.getKey("data");
});
t.done();
}
</script>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>IDBIndex.getKey() - throw InvalidStateError on index deleted by aborted upgrade</title>
<link rel="help" href="https://w3c.github.io/IndexedDB/#dom-idbindex-getkey">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=support.js></script>
<div id="log"></div>
<script>
var db,
t = async_test();
var open_rq = createdb(t);
open_rq.onupgradeneeded = function(e) {
db = e.target.result;
var store = db.createObjectStore("store", { keyPath: "key" });
var index = store.createIndex("index", "indexedProperty");
store.add({ key: 1, indexedProperty: "data" });
e.target.transaction.abort();
assert_throws("InvalidStateError", function(){
index.getKey("data");
});
t.done();
}
</script>

View file

@ -17,8 +17,12 @@
var store = db.createObjectStore("store", { keyPath: "key" });
var index = store.createIndex("index", "indexedProperty");
store.add({ key: 1, indexedProperty: "data" });
e.target.transaction.abort();
}
open_rq.onsuccess = function(e) {
db = e.target.result;
var tx = db.transaction('store');
var index = tx.objectStore('store').index('index');
tx.abort();
assert_throws("TransactionInactiveError", function(){
index.openCursor();
@ -26,4 +30,3 @@
t.done();
}
</script>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>IDBIndex.openCursor() - throw InvalidStateError on index deleted by aborted upgrade</title>
<link rel="help" href="https://w3c.github.io/IndexedDB/#dom-idbindex-opencursor">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=support.js></script>
<div id="log"></div>
<script>
var db,
t = async_test();
var open_rq = createdb(t);
open_rq.onupgradeneeded = function(e) {
db = e.target.result;
var store = db.createObjectStore("store", { keyPath: "key" });
var index = store.createIndex("index", "indexedProperty");
store.add({ key: 1, indexedProperty: "data" });
e.target.transaction.abort();
assert_throws("InvalidStateError", function(){
index.openCursor();
});
t.done();
}
</script>

View file

@ -17,8 +17,12 @@
var store = db.createObjectStore("store", { keyPath: "key" });
var index = store.createIndex("index", "indexedProperty");
store.add({ key: 1, indexedProperty: "data" });
e.target.transaction.abort();
}
open_rq.onsuccess = function(e) {
db = e.target.result;
var tx = db.transaction('store');
var index = tx.objectStore('store').index('index');
tx.abort();
assert_throws("TransactionInactiveError", function(){
index.openKeyCursor();
@ -26,4 +30,3 @@
t.done();
}
</script>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>IDBIndex.openKeyCursor() - throw InvalidStateError on index deleted by aborted upgrade</title>
<link rel="help" href="https://w3c.github.io/IndexedDB/#dom-idbindex-openkeycursor">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=support.js></script>
<div id="log"></div>
<script>
var db,
t = async_test();
var open_rq = createdb(t);
open_rq.onupgradeneeded = function(e) {
db = e.target.result;
var store = db.createObjectStore("store", { keyPath: "key" });
var index = store.createIndex("index", "indexedProperty");
store.add({ key: 1, indexedProperty: "data" });
e.target.transaction.abort();
assert_throws("InvalidStateError", function(){
index.openKeyCursor();
});
t.done();
}
</script>

View file

@ -0,0 +1,2 @@
@Wafflespeanut
@Ms2ger

View file

@ -0,0 +1,13 @@
@ecoal95
@hallvors
@kangxu
@caitp
@Manishearth
@plehegar
@foolip
@jungkees
@ibelem
@mathiasbynens
@ronkorving
@jdm
@Ms2ger

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<title>XMLHttpRequest: open() call fires sync readystate event</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[13]/ol[1]/li[2]" />
</head>
<body>
<div id="log"></div>
<script>
test(function() {
var client = new XMLHttpRequest()
var eventsFired = []
client.onreadystatechange = function(){
eventsFired.push(client.readyState)
}
client.open('GET', "...", false)
assert_array_equals(eventsFired, [1])
}, document.title + ' (sync)')
test(function() {
var client = new XMLHttpRequest()
var eventsFired = []
client.onreadystatechange = function(){
eventsFired.push(client.readyState)
}
client.open('GET', "...", true)
assert_array_equals(eventsFired, [1])
}, document.title + ' (async)')
</script>
</body>
</html>

View file

@ -4,7 +4,7 @@
<title>XMLHttpRequest: open() sync request not allowed if responseType is set</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[4]" />
<link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[10]" />
</head>
<body>
@ -15,6 +15,9 @@
function request(type) {
test(function() {
var client = new XMLHttpRequest()
client.onreadystatechange = this.step_func(function(){
assert_unreached('No events should fire here')
})
client.responseType = type
assert_throws("InvalidAccessError", function() { client.open('GET', "...", false) })
}, document.title + " (" + type + ")")

View file

@ -43,7 +43,7 @@
}
test(function() {
assert_true((new Date(client.getResponseHeader('Last-Modified'))).getTime() == (new Date(client.responseXML.lastModified)).getTime(), 'responseXML.lastModified time shoud be equal to time in response Last-Modified header')
assert_true((new Date(client.getResponseHeader('Last-Modified'))).getTime() == (new Date(client.responseXML.lastModified)).getTime(), 'responseXML.lastModified time should be equal to time in response Last-Modified header')
}, 'lastModified set according to HTTP header')
test(function() {

View file

@ -0,0 +1,3 @@
@zqzhang
@Volker-E
@dontcallmedom

View file

@ -0,0 +1 @@
@happyoungj

View file

@ -0,0 +1,4 @@
@zqzhang
@foolip
@dontcallmedom
@deniak

View file

@ -0,0 +1 @@
@sideshowbarker

View file

@ -0,0 +1,2 @@
@sideshowbarker
@hillbrad

View file

@ -0,0 +1,5 @@
@sideshowbarker
@zqzhang
@Velmont
@hillbrad
@jdm

View file

@ -0,0 +1 @@
@AutomatedTester

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>cssom-view - elementFromPoint and elementsFromPoint dealing with negative margins</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<div id="outer" style="background:yellow">
<div id="inner" style="width:100px; height:100px; margin-bottom:-100px; background:lime;"></div>
Hello
</div>
<script>
setup({explicit_done:true});
window.onload = function () {
var outer = document.getElementById('outer');
var inner = document.getElementById('inner');
var outerRect = outer.getBoundingClientRect();
test(function () {
assert_equals(document.elementFromPoint(outerRect.left + 1,
outerRect.top + 1),
outer,
"elementFromPoint should get outer element");
});
test(function () {
assert_array_equals(document.elementsFromPoint(outerRect.left + 1,
outerRect.top + 1),
[inner, outer, document.body, document.querySelector('html')],
"elementsFromPoint should get sequence [inner, outer, body, html]");
});
done();
};
</script>
</body>

View file

@ -0,0 +1,3 @@
@deepak-sa
@sgrekhov
@alsemenov

View file

@ -0,0 +1,4 @@
@sideshowbarker
@dontcallmedom
@zcorpan
@Ms2ger

View file

@ -0,0 +1,6 @@
@ayg
@jdm
@Ms2ger
@plehegar
@zcorpan
@zqzhang

View file

@ -18,6 +18,7 @@ var nukedInterfaces = [
"DOMImplementationSource",
"DOMLocator",
"DOMObject",
"DOMSettableTokenList",
"DOMUserData",
"Entity",
"EntityReference",

View file

@ -31,8 +31,7 @@ var interfaces = [
"NodeFilter",
"NodeList",
"HTMLCollection",
"DOMTokenList",
"DOMSettableTokenList"
"DOMTokenList"
];
test(function() {
for (var p in window) {

View file

@ -283,7 +283,7 @@ interface Element : Node {
attribute DOMString id;
attribute DOMString className;
[SameObject] readonly attribute DOMTokenList classList;
[SameObject, PutForwards=value] readonly attribute DOMTokenList classList;
boolean hasAttributes();
[SameObject] readonly attribute NamedNodeMap attributes;
@ -460,13 +460,12 @@ interface DOMTokenList {
void add(DOMString... tokens);
void remove(DOMString... tokens);
boolean toggle(DOMString token, optional boolean force);
void replace(DOMString token, DOMString newToken);
boolean supports(DOMString token);
attribute DOMString value;
stringifier;
// iterable<DOMString>;
};
interface DOMSettableTokenList : DOMTokenList {
attribute DOMString value;
};
</script>
<script>
"use strict";

View file

@ -290,15 +290,13 @@ test(function () {
assert_false(failed,'an error was thrown');
}, 'classList.length must be read-only');
test(function () {
var failed = false, realList = secondelem.classList;
try {
secondelem.classList = '';
} catch(e) {
failed = e;
}
var realList = secondelem.classList;
secondelem.classList = 'foo bar';
assert_equals(secondelem.classList,realList);
assert_false(failed,'an error was thrown');
}, 'classList must be read-only');
assert_equals(secondelem.classList.length,2);
assert_equals(secondelem.classList[0],'foo');
assert_equals(secondelem.classList[1],'bar');
}, 'classList must have [PutForwards=value]');
</script>
</head>
<body>

View file

@ -0,0 +1,161 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Node.prototype.isEqualNode</title>
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-isequalnode">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
"use strict";
test(function() {
var doctype1 = document.implementation.createDocumentType("qualifiedName", "publicId", "systemId");
var doctype2 = document.implementation.createDocumentType("qualifiedName", "publicId", "systemId");
var doctype3 = document.implementation.createDocumentType("qualifiedName2", "publicId", "systemId");
var doctype4 = document.implementation.createDocumentType("qualifiedName", "publicId2", "systemId");
var doctype5 = document.implementation.createDocumentType("qualifiedName", "publicId", "systemId3");
assert_true(doctype1.isEqualNode(doctype1), "self-comparison");
assert_true(doctype1.isEqualNode(doctype2), "same properties");
assert_false(doctype1.isEqualNode(doctype3), "different name");
assert_false(doctype1.isEqualNode(doctype4), "different public ID");
assert_false(doctype1.isEqualNode(doctype5), "different system ID");
}, "doctypes should be compared on name, public ID, and system ID");
test(function() {
var element1 = document.createElementNS("namespace", "prefix:localName");
var element2 = document.createElementNS("namespace", "prefix:localName");
var element3 = document.createElementNS("namespace2", "prefix:localName");
var element4 = document.createElementNS("namespace", "prefix2:localName");
var element5 = document.createElementNS("namespace", "prefix:localName2");
var element6 = document.createElementNS("namespace", "prefix:localName");
element6.setAttribute("foo", "bar");
assert_true(element1.isEqualNode(element1), "self-comparison");
assert_true(element1.isEqualNode(element2), "same properties");
assert_false(element1.isEqualNode(element3), "different namespace");
assert_false(element1.isEqualNode(element4), "different prefix");
assert_false(element1.isEqualNode(element5), "different local name");
assert_false(element1.isEqualNode(element6), "different number of attributes");
}, "elements should be compared on namespace, namespace prefix, local name, and number of attributes");
test(function() {
var element1 = document.createElement("element");
element1.setAttributeNS("namespace", "prefix:localName", "value");
var element2 = document.createElement("element");
element2.setAttributeNS("namespace", "prefix:localName", "value");
var element3 = document.createElement("element");
element3.setAttributeNS("namespace2", "prefix:localName", "value");
var element4 = document.createElement("element");
element4.setAttributeNS("namespace", "prefix2:localName", "value");
var element5 = document.createElement("element");
element5.setAttributeNS("namespace", "prefix:localName2", "value");
var element6 = document.createElement("element");
element6.setAttributeNS("namespace", "prefix:localName", "value2");
assert_true(element1.isEqualNode(element1), "self-comparison");
assert_true(element1.isEqualNode(element2), "attribute with same properties");
assert_false(element1.isEqualNode(element3), "attribute with different namespace");
assert_true(element1.isEqualNode(element4), "attribute with different prefix");
assert_false(element1.isEqualNode(element5), "attribute with different local name");
assert_false(element1.isEqualNode(element6), "attribute with different value");
}, "elements should be compared on attribute namespace, local name, and value");
test(function() {
var pi1 = document.createProcessingInstruction("target", "data");
var pi2 = document.createProcessingInstruction("target", "data");
var pi3 = document.createProcessingInstruction("target2", "data");
var pi4 = document.createProcessingInstruction("target", "data2");
assert_true(pi1.isEqualNode(pi1), "self-comparison");
assert_true(pi1.isEqualNode(pi2), "same properties");
assert_false(pi1.isEqualNode(pi3), "different target");
assert_false(pi1.isEqualNode(pi4), "different data");
}, "processing instructions should be compared on target and data");
test(function() {
var text1 = document.createTextNode("data");
var text2 = document.createTextNode("data");
var text3 = document.createTextNode("data2");
assert_true(text1.isEqualNode(text1), "self-comparison");
assert_true(text1.isEqualNode(text2), "same properties");
assert_false(text1.isEqualNode(text3), "different data");
}, "text nodes should be compared on data");
test(function() {
var comment1 = document.createComment("data");
var comment2 = document.createComment("data");
var comment3 = document.createComment("data2");
assert_true(comment1.isEqualNode(comment1), "self-comparison");
assert_true(comment1.isEqualNode(comment2), "same properties");
assert_false(comment1.isEqualNode(comment3), "different data");
}, "comments should be compared on data");
test(function() {
var documentFragment1 = document.createDocumentFragment();
var documentFragment2 = document.createDocumentFragment();
assert_true(documentFragment1.isEqualNode(documentFragment1), "self-comparison");
assert_true(documentFragment1.isEqualNode(documentFragment2), "same properties");
}, "document fragments should not be compared based on properties");
test(function() {
var document1 = document.implementation.createDocument("", "");
var document2 = document.implementation.createDocument("", "");
assert_true(document1.isEqualNode(document1), "self-comparison");
assert_true(document1.isEqualNode(document2), "another empty XML document");
var htmlDoctype = document.implementation.createDocumentType("html", "", "");
var document3 = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", htmlDoctype);
document3.documentElement.appendChild(document3.createElement("head"));
document3.documentElement.appendChild(document3.createElement("body"));
var document4 = document.implementation.createHTMLDocument();
assert_true(document3.isEqualNode(document4), "default HTML documents, created different ways");
}, "documents should not be compared based on properties");
test(function() {
testDeepEquality(function() { return document.createElement("foo") });
testDeepEquality(function() { return document.createDocumentFragment() });
testDeepEquality(function() { return document.implementation.createDocument("", "") });
testDeepEquality(function() { return document.implementation.createHTMLDocument() });
function testDeepEquality(parentFactory) {
// Some ad-hoc tests of deep equality
var parentA = parentFactory();
var parentB = parentFactory();
parentA.appendChild(document.createComment("data"));
assert_false(parentA.isEqualNode(parentB));
parentB.appendChild(document.createComment("data"));
assert_true(parentA.isEqualNode(parentB));
}
}, "node equality testing should test descendant equality too");
</script>

View file

@ -0,0 +1,5 @@
@sideshowbarker
@ChrisParis
@deniak
@jdm
@Ms2ger

View file

@ -0,0 +1,3 @@
@gsnedders
@zqzhang
@deniak

View file

@ -0,0 +1 @@
@ayg

View file

@ -0,0 +1,2 @@
@inexorabletash
@sideshowbarker

View file

@ -0,0 +1,5 @@
@zqzhang
@sideshowbarker
@deniak
@Velmont
@Yaffle

View file

@ -0,0 +1,2 @@
@jdm
@youennf

View file

@ -11,7 +11,7 @@
</head>
<body>
<script>
var headers = new Headers( {"name":"value"} );
var headers = new Headers({"name" : "value"});
var emptyHeaders = new Headers();
var initValuesDict = {"method" : "POST",
@ -43,6 +43,21 @@
var requestToCheck = RequestInitialized.clone();
checkRequest(requestToCheck, expectedInitialized);
}, "Check cloning a request");
test(function() {
var initialRequest = new Request("", {"headers" : new Headers({"a": "1", "b" : "2"})});
var request = initialRequest.clone();
assert_equals(request.headers.get("a"), "1", "cloned request should have header 'a'");
assert_equals(request.headers.get("b"), "2", "cloned request should have header 'b'");
initialRequest.headers.delete("a");
assert_equals(request.headers.get("a"), "1", "cloned request should still have header 'a'");
request.headers.delete("a");
assert_equals(initialRequest.headers.get("b"), "2", "initial request should have header 'b'");
}, "Check cloning a request copies the headers");
</script>
</body>
</html>

View file

@ -84,6 +84,24 @@
checkRequestBody("This is request's body", "arrayBuffer", checkBodyArrayBuffer);
checkRequestBody(JSON.stringify("This is request's body"), "json", checkBodyJSON);
checkRequestBody(formData, "formData", checkBodyFormData);
var goodJSONValues = ["null", "1", "true", "\"string\""];
goodJSONValues.forEach(function(value) {
promise_test(function(test) {
var request = new Request("", {"method": "POST", "body": value});
return request.json().then(function(v) {
assert_equals(v, JSON.parse(value));
});
}, "Consume JSON from text: '" + JSON.stringify(value) + "'");
});
var badJSONValues = ["undefined", "{", "a", "["];
badJSONValues.forEach(function(value) {
promise_test(function(test) {
var request = new Request("", {"method": "POST", "body": value});
return promise_rejects(test, new SyntaxError(), request.json());
}, "Trying to consume bad JSON text as JSON: '" + value + "'");
});
</script>
</body>
</html>

View file

@ -29,6 +29,9 @@
assert_throws(new TypeError(),
function() { new Request("", {"method": "GET", "body": body}); }
);
assert_throws(new TypeError(),
function() { new Request("", {"method": "HEAD", "body": body}); }
);
var reqHeaders = request.headers;
var mime = reqHeaders.get("Content-Type");
assert_true(mime && mime.search(bodyType) > -1, "Content-Type header should be \"" + bodyType + "\", not \"" + mime + "\"");
@ -36,7 +39,7 @@
//not equals: cannot guess formData exact value
assert_true( bodyAsText.search(expectedTextBody) > -1, "Retrieve and verify request body");
});
}, "Initialize Response's body with " + bodyType);
}, "Initialize Request's body with " + bodyType);
}
var blob = new Blob(["This is a blob"], {type: "application/octet-binary"});
@ -55,7 +58,7 @@
} else {
promise_test(function(test) {
return Promise.reject("URLSearchParams not supported");
}, "Initialize Response's body with application/x-www-form-urlencoded;charset=UTF-8");
}, "Initialize Request's body with application/x-www-form-urlencoded;charset=UTF-8");
}
</script>
</body>

View file

@ -51,7 +51,7 @@
break;
case "headers":
request.headers = new Headers ( {"name":"value"} );
request.headers = new Headers ({"name":"value"});
assert_false(request.headers.has("name"), "Headers attribute is read only");
return;
break;
@ -117,16 +117,18 @@
"Attribute " + attributeToCheck + " is read only. Default value is " + defaultValue);
}
for (var idx in methods)
for (var idx in methods) {
test(function() {
assert_true(methods[idx] in request, "request has " + methods[idx] + " method");
}, "Request has " + methods[idx] + " method");
}
for (var idx in attributes)
for (var idx in attributes) {
test(function() {
assert_true(attributes[idx] in request, "request has " + attributes[idx] + " attribute");
IsreadOnly(request, attributes[idx]);
}, "Check " + attributes[idx] + " attribute");
}
</script>
</body>
</html>

View file

@ -0,0 +1 @@
@luser

View file

@ -0,0 +1,2 @@
@zqzhang
@jdm

View file

@ -0,0 +1,2 @@
@plehegar
@foolip

View file

@ -0,0 +1 @@
@omo

View file

@ -0,0 +1,2 @@
@chaals
@cptvitamin

View file

@ -0,0 +1,2 @@
@haoxli
@zqzhang

View file

@ -1,5 +1,6 @@
@Ms2ger
@gsnedders
@jdm
@jgraham
@plehegar
@sideshowbarker

View file

@ -0,0 +1,8 @@
<!DOCTYPE html>
<style>
body {
height: 2000px;
width: 2000px;
}
</style>
<body> Blank 1 </body>

View file

@ -0,0 +1,8 @@
<!DOCTYPE html>
<style>
body {
height: 2000px;
width: 2000px;
}
</style>
<body> Blank 2 </body>

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<style>
body {
height: 2000px;
width: 2000px;
}
#fragment {
position: absolute;
top: 800px;
background-color: #faa;
display: block;
height: 100px;
width: 100px;
}
</style>
<body>
Page with fragment
<a id="fragment" name="fragment" class='box'></a>
</body>

View file

@ -0,0 +1,34 @@
<!doctype html>
<title>Verify existence and basic read/write function of history.scrollRestoration</title>
<style>
body {
height: 2000px;
width: 2000px;
}
</style>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript">
'use strict';
test(function() {
assert_equals(history.scrollRestoration, 'auto');
}, 'Default value is "auto"');
test(function() {
history.scrollRestoration = 'manual';
assert_equals(history.scrollRestoration, 'manual', 'should be able to set "manual"');
history.scrollRestoration = 'auto';
assert_equals(history.scrollRestoration, 'auto', 'should be able to set "auto"');
}, 'It is writable');
test(function() {
history.scrollRestoration = 'auto';
for (var v of [3.1415, {}, 'bogus']) {
history.scrollRestoration = v;
assert_equals(history.scrollRestoration, 'auto', `setting to invalid value (${v}) should be ignored`);
}
}, 'Invalid values are ignored');
</script>

View file

@ -0,0 +1,67 @@
<!DOCTYPE html>
<meta name=timeout content=long>
<title>Precedence of scroll restoration mode over fragment scrolling in cross-origin history traversal</title>
<style>
iframe {
height: 300px;
width: 300px;
}
</style>
<body>
<iframe></iframe>
</body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript">
'use strict';
// The test does the following navigation steps for iframe
// 1. load page-with-fragment.html#fragment
// 2. load blank1
// 3. go back to page-with-fragment.html
async_test(function(t) {
var iframe = document.querySelector('iframe');
var baseURL = location.href.substring(0, location.href.lastIndexOf('/'));
var steps = [
function() {
iframe.src = 'resources/page-with-fragment.html#fragment';
}, function() {
assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/page-with-fragment.html#fragment', 'should be on page-with-fragment page');
// wait one animation frame to ensure layout is run and fragment scrolling is complete
iframe.contentWindow.requestAnimationFrame(function() {
assert_equals(iframe.contentWindow.scrollY, 800, 'should scroll to fragment');
iframe.contentWindow.history.scrollRestoration = 'manual';
assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual');
setTimeout(next, 0);
});
}, function() {
// navigate to a new page from a different origin
iframe.src = iframe.src.replace("http://", "http://www.").replace("page-with-fragment.html#fragment", "blank1.html");
}, function() {
// going back causes the iframe to traverse back
history.back();
}, function() {
// coming back from history, scrollRestoration should be set to manual and respected
assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/page-with-fragment.html#fragment', 'should be back on page-with-fragment page');
iframe.contentWindow.requestAnimationFrame(function() {
assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual', 'navigating back should retain scrollRestoration value');
assert_equals(iframe.contentWindow.scrollX, 0, 'should not scroll to fragment');
assert_equals(iframe.contentWindow.scrollY, 0, 'should not scroll to fragment');
t.done();
});
}
];
var stepCount = 0;
var next = t.step_func(function() {
steps[stepCount++]();
});
iframe.onload = next;
next();
}, 'Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation');
</script>

View file

@ -0,0 +1,54 @@
<!DOCTYPE html>
<style>
body {
height: 2000px;
width: 2000px;
}
#fragment {
position: absolute;
top: 800px;
background-color: #faa;
display: block;
height: 100px;
width: 100px;
}
</style>
<body>
<a id="fragment" name="fragment" class='box'></a>
</body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript">
'use strict';
async_test(function(t) {
history.scrollRestoration = 'manual';
assert_equals(history.scrollRestoration, 'manual');
location.hash = '#fragment';
assert_equals(window.scrollY, 800, 'new navigations should scroll to fragment');
// create a new entry and reset the scroll before verification
history.pushState(null, null, '#done');
window.scrollTo(0, 0);
assert_equals(window.scrollY, 0, 'should reset scroll before verification');
setTimeout(function() {
// setup verification
window.addEventListener('hashchange', t.step_func(function() {
assert_equals(location.hash, '#fragment');
assert_equals(history.scrollRestoration, 'manual');
// navigating back should give precedent to history restoration which is 'manual'
assert_equals(window.scrollX, 0, 'should not scroll to fragment');
assert_equals(window.scrollY, 0, 'should not scroll to fragment');
t.done();
}));
// kick off verification
window.history.back();
}, 0);
}, 'Manual scroll restoration should take precedent over scrolling to fragment in cross doc navigation');
</script>

View file

@ -0,0 +1,71 @@
<!DOCTYPE html>
<meta name=timeout content=long>
<title>Correct behaviour of scroll restoration mode is cross origin history traversal</title>
<style>
iframe {
height: 300px;
width: 300px;
}
</style>
<body>
<iframe></iframe>
</body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript">
'use strict';
// The test does the following navigation steps for iframe
// 1. load blank1
// 2. load blank2
// 3. go back to blank1
async_test(function(t) {
var iframe = document.querySelector('iframe');
var baseURL = location.href.substring(0, location.href.lastIndexOf('/'));
var steps = [
function() {
iframe.src = 'resources/blank1.html';
},
function() {
assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/blank1.html', 'should be on first blank page');
iframe.contentWindow.history.scrollRestoration = 'manual';
assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual');
iframe.contentWindow.scrollTo(500, 500);
assert_equals(iframe.contentWindow.scrollX, 500, 'scripted scrolling should take effect');
assert_equals(iframe.contentWindow.scrollY, 500, 'scripted scrolling should take effect');
setTimeout(next, 0);
},
function() {
// navigate to new page
iframe.src = 'resources/blank2.html';
},
function() {
assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/blank2.html', 'should be on second blank page');
assert_equals(iframe.contentWindow.history.scrollRestoration, 'auto', 'new page loads should set scrollRestoration to "auto"');
setTimeout(next, 0);
}, function() {
iframe.contentWindow.history.back();
}, function() {
// coming back scrollRestoration should be restored to 'manual' and respected
assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/blank1.html', 'should be back on first blank page');
assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual', 'navigating back should retain scrollRestoration value');
assert_equals(iframe.contentWindow.scrollX, 0, 'horizontal scroll offset should not be restored');
assert_equals(iframe.contentWindow.scrollY, 0, 'vertical scroll offset should not be restored');
t.done();
}
];
var stepCount = 0;
var next = t.step_func(function() {
steps[stepCount++]();
});
iframe.onload = next;
next();
}, 'Navigating to new page should reset to "auto" and navigating back should restore and respect scroll restoration mode');
</script>

View file

@ -0,0 +1,81 @@
<!DOCTYPE html>
<title>Correct behaviour of scroll restoration mode in same document history traversals</title>
<style>
body {
height: 10000px;
width: 10000px;
}
</style>
<body></body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript">
'use strict';
async_test(function(t) {
history.scrollRestoration = 'auto';
window.scrollTo(0, 0);
// create history entries and then verify the impact of scrollRestoration
// when they are popped
var entries = {
/* For scroll restoration mode 'auto', the spec does not require scroll
position to be restored at any particular value. */
'#1': {type: 'push', expectedScroll: null, scrollRestoration: 'auto'},
'#2': {type: 'replace', expectedScroll: null, scrollRestoration: 'auto'},
/* For scroll restoration mode 'manual', the spec requires scroll position
not to be restored. So we expect [555,555] which is the latest position
before navigation. */
'#3': {type: 'push', expectedScroll: [555, 555], scrollRestoration: 'manual'},
'#4': {type: 'replace', expectedScroll: [555, 555], scrollRestoration: 'manual'}
};
// setup entries
for (var key in entries) {
var entry = entries[key],
beforeValue = history.scrollRestoration,
newValue = entry.scrollRestoration;
var args = [{key: key}, '', key];
if (entry.type == 'push') {
history.pushState.apply(history, args);
} else {
history.pushState(null, '', key);
history.replaceState.apply(history, args);
}
assert_equals(history.scrollRestoration, beforeValue, `history.scrollRestoration value is retained after pushing new state`);
history.scrollRestoration = newValue;
assert_equals(history.scrollRestoration, newValue, `Setting scrollRestoration to ${newValue} works as expected`);
window.scrollBy(50, 100);
}
// setup verification
window.addEventListener('hashchange', t.step_func(function() {
var key = location.hash,
entry = entries[key];
if (key === '') {
t.done();
return;
}
assert_equals(history.state.key, key, `state should have key: ${key}`);
assert_equals(history.scrollRestoration, entry.scrollRestoration, 'scrollRestoration is updated correctly');
if (entry.expectedScroll) {
assert_equals(window.scrollX, entry.expectedScroll[0], `scrollX is correct for ${key}`);
assert_equals(window.scrollY, entry.expectedScroll[1], `scrollY is correct for ${key}`);
}
window.history.back();
}));
// reset the scroll and kick off the verification
setTimeout(function() {
history.pushState(null, null, '#done');
window.scrollTo(555, 555);
window.history.back();
}, 0);
}, 'history.{push,replace}State retain scroll restoration mode and navigation in the same document respects it');
</script>

View file

@ -285,7 +285,7 @@ interface Element : Node {
attribute DOMString id;
attribute DOMString className;
[SameObject] readonly attribute DOMTokenList classList;
[SameObject, PutForwards=value] readonly attribute DOMTokenList classList;
boolean hasAttributes();
[SameObject] readonly attribute NamedNodeMap attributes;
@ -462,14 +462,12 @@ interface DOMTokenList {
void add(DOMString... tokens);
void remove(DOMString... tokens);
boolean toggle(DOMString token, optional boolean force);
void replace(DOMString token, DOMString newToken);
boolean supports(DOMString token);
attribute DOMString value;
stringifier;
// iterable<DOMString>;
};
interface DOMSettableTokenList : DOMTokenList {
attribute DOMString value;
};
</script>
};</script>
<!-- UI Events IDLs -->
<script type=text/plain class=untested>
[Constructor(DOMString type, optional UIEventInit eventInitDict)]
@ -998,10 +996,10 @@ interface HTMLElement : Element {
// microdata
attribute boolean itemScope;
[PutForwards=value] readonly attribute DOMSettableTokenList itemType;
[PutForwards=value] readonly attribute DOMTokenList itemType;
attribute DOMString itemId;
[PutForwards=value] readonly attribute DOMSettableTokenList itemRef;
[PutForwards=value] readonly attribute DOMSettableTokenList itemProp;
[PutForwards=value] readonly attribute DOMTokenList itemRef;
[PutForwards=value] readonly attribute DOMTokenList itemProp;
readonly attribute HTMLPropertiesCollection properties;
attribute any itemValue; // acts as DOMString on setting
@ -1014,7 +1012,7 @@ interface HTMLElement : Element {
attribute DOMString accessKey;
readonly attribute DOMString accessKeyLabel;
attribute boolean draggable;
[PutForwards=value] readonly attribute DOMSettableTokenList dropzone;
[PutForwards=value] readonly attribute DOMTokenList dropzone;
attribute DOMString contentEditable;
readonly attribute boolean isContentEditable;
attribute HTMLMenuElement? contextMenu;
@ -1052,11 +1050,11 @@ interface HTMLLinkElement : HTMLElement {
attribute DOMString href;
attribute DOMString crossOrigin;
attribute DOMString rel;
readonly attribute DOMTokenList relList;
[PutForwards=value] readonly attribute DOMTokenList relList;
attribute DOMString media;
attribute DOMString hreflang;
attribute DOMString type;
[PutForwards=value] readonly attribute DOMSettableTokenList sizes;
[PutForwards=value] readonly attribute DOMTokenList sizes;
// also has obsolete members
};
@ -1132,9 +1130,9 @@ interface HTMLDivElement : HTMLElement {
interface HTMLAnchorElement : HTMLElement {
attribute DOMString target;
attribute DOMString download;
[PutForwards=value] readonly attribute DOMSettableTokenList ping;
[PutForwards=value] readonly attribute DOMTokenList ping;
attribute DOMString rel;
readonly attribute DOMTokenList relList;
[PutForwards=value] readonly attribute DOMTokenList relList;
attribute DOMString hreflang;
attribute DOMString type;
@ -1192,7 +1190,7 @@ interface HTMLIFrameElement : HTMLElement {
attribute DOMString src;
attribute DOMString srcdoc;
attribute DOMString name;
[PutForwards=value] readonly attribute DOMSettableTokenList sandbox;
[PutForwards=value] readonly attribute DOMTokenList sandbox;
attribute boolean seamless;
attribute boolean allowFullscreen;
attribute DOMString width;
@ -1502,9 +1500,9 @@ interface HTMLAreaElement : HTMLElement {
attribute DOMString shape;
attribute DOMString target;
attribute DOMString download;
[PutForwards=value] readonly attribute DOMSettableTokenList ping;
[PutForwards=value] readonly attribute DOMTokenList ping;
attribute DOMString rel;
readonly attribute DOMTokenList relList;
[PutForwards=value] readonly attribute DOMTokenList relList;
// hreflang and type are not reflected
};
HTMLAreaElement implements HTMLHyperlinkElementUtils;
@ -1572,7 +1570,7 @@ interface HTMLTableHeaderCellElement : HTMLTableCellElement {
interface HTMLTableCellElement : HTMLElement {
attribute unsigned long colSpan;
attribute unsigned long rowSpan;
[PutForwards=value] readonly attribute DOMSettableTokenList headers;
[PutForwards=value] readonly attribute DOMTokenList headers;
readonly attribute long cellIndex;
// also has obsolete members
@ -1816,7 +1814,7 @@ interface HTMLKeygenElement : HTMLElement {
};
interface HTMLOutputElement : HTMLElement {
[PutForwards=value] readonly attribute DOMSettableTokenList htmlFor;
[PutForwards=value] readonly attribute DOMTokenList htmlFor;
readonly attribute HTMLFormElement? form;
attribute DOMString name;
@ -2309,8 +2307,11 @@ interface BarProp {
attribute boolean visible;
};
enum ScrollRestoration { "auto", "manual" };
interface History {
readonly attribute long length;
attribute ScrollRestoration scrollRestoration;
readonly attribute any state;
void go(optional long delta);
void back();

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Focus events fire at correct targets in correct order in simple case</title>
<link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
<link rel="help" href="https://html.spec.whatwg.org/#focus-update-steps">
<link rel="help" href="https://html.spec.whatwg.org/#focus-chain">
<meta name="flags" content="dom">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<input type="text" id="a">
<script>
// Record all the focus event targets in an array.
// Modulo special cases in the "focus update steps" algorithm,
// this should be the same as the new focus chain, except in reverse order.
var newFocusChainReversedNotQuite = [];
var pushTarget = function (e) {
newFocusChainReversedNotQuite.push(e.target);
};
// Window is the root node for event dispatch per https://html.spec.whatwg.org/multipage/webappapis.html#events-and-the-window-object
window.addEventListener('focus', pushTarget, true);// Use event capturing since focus event doesn't bubble
var input = document.getElementById('a');
input.focus();
window.removeEventListener('focus', pushTarget, true);
test(function() {
assert_array_equals(newFocusChainReversedNotQuite, [input], "Exactly 1 focus event should fire and its target should be the input");
}, "Focus events fire at correct targets in correct order in simple case");
</script>
</body>
</html>

View file

@ -19,7 +19,7 @@
<li class="upper-roman">fifth item</li>
<li class="disc">sixth item</li>
<li class="circle">seventh item</li>
<li class="square">eigth item</li>
<li class="square">eighth item</li>
<li class="none">ninth item</li>
<ol>
<li class="decimal">first ordered item</li>
@ -29,7 +29,7 @@
<li class="upper-roman">fifth ordered item</li>
<li class="disc">sixth ordered item</li>
<li class="circle">seventh ordered item</li>
<li class="square">eigth ordered item</li>
<li class="square">eighth ordered item</li>
<li class="none">ninth ordered item</li>
</ol>
<ul>
@ -40,6 +40,6 @@
<li class="upper-roman">fifth unordered item</li>
<li class="disc">sixth unordered item</li>
<li class="circle">seventh unordered item</li>
<li class="square">eigth unordered item</li>
<li class="square">eighth unordered item</li>
<li class="none">ninth unordered item</li>
</ul>

View file

@ -9,7 +9,7 @@
<li type=I>fifth item</li>
<li type=disc>sixth item</li>
<li type=circle>seventh item</li>
<li type=square>eigth item</li>
<li type=square>eighth item</li>
<li type=none>ninth item</li>
<ol>
<li type=1>first ordered item</li>
@ -19,7 +19,7 @@
<li type=I>fifth ordered item</li>
<li type=disc>sixth ordered item</li>
<li type=circle>seventh ordered item</li>
<li type=square>eigth ordered item</li>
<li type=square>eighth ordered item</li>
<li type=none>ninth ordered item</li>
</ol>
<ul>
@ -30,6 +30,6 @@
<li type=I>fifth unordered item</li>
<li type=disc>sixth unordered item</li>
<li type=circle>seventh unordered item</li>
<li type=square>eigth unordered item</li>
<li type=square>eighth unordered item</li>
<li type=none>ninth unordered item</li>
</ul>

View file

@ -12,7 +12,7 @@
<li type="I">fifth item</li>
<li type="disc">sixth item</li>
<li type="circle">seventh item</li>
<li type="square">eigth item</li>
<li type="square">eighth item</li>
<li type="none">ninth item</li>
<ol>
<li type="1">first ordered item</li>
@ -22,7 +22,7 @@
<li type="I">fifth ordered item</li>
<li type="disc">sixth ordered item</li>
<li type="circle">seventh ordered item</li>
<li type="square">eigth ordered item</li>
<li type="square">eighth ordered item</li>
<li type="none">ninth ordered item</li>
</ol>
<ul>
@ -33,7 +33,7 @@
<li type="I">fifth unordered item</li>
<li type="disc">sixth unordered item</li>
<li type="circle">seventh unordered item</li>
<li type="square">eigth unordered item</li>
<li type="square">eighth unordered item</li>
<li type="none">ninth unordered item</li>
</ul>
</body>

View file

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<html>
<head>
<title>HTML5 Media Elements: 'media' attribute</title>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/html5/video.html#the-source-element" />
<meta name="assert" content="'media' attribute is 'all' by default." />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript" src="/common/media.js"></script>
<script type="text/javascript">
var videotest = async_test();
function do_play(event)
{
videotest.step(function() {
var vid = document.getElementById("video0");
assert_true(vid.currentSrc.indexOf("movie_300") > 0);
});
videotest.done();
}
</script>
</head>
<body>
<div id='log'></div>
<video id="video0" autoplay onplay="do_play(event);">
<script type="text/javascript">
document.write(
"<source media='not all' src='" + getVideoURI("/media/movie_300") + "'" +
" />"
);
document.write(
"<source src='" + getVideoURI("/media/movie_5") + "'" +
" media='all' />"
);
</script>
Your browser does not support media elements.
</video>
</body>
</html>

View file

@ -22,7 +22,6 @@ t('loopCount'); // added in r692, replaced with playCount in r1105.
t('currentLoop'); // added in r692, removed in r2401.
t('addCuePoint'); // added in r721, replaced with addCueRange in r1106.
t('removeCuePoint'); // added in r721, replaced with removeCueRanges in r1106.
t('media', 'source'); // added in r724, removed in r8472.
t('playCount'); // added in r1105, removed in r2401.
t('addCueRange'); // added in r1106, removed in r5070.
t('removeCueRanges'); // added in r1106, removed in r5070.

View file

@ -3,13 +3,15 @@
<title>HTML Test: The embed element represents a document</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="stylesheet" href="/resources/testharness.css">
<meta name="assert" content="Check if the embed element represents a document when a text/html resource source is used">
<body>
<script type="application/javascript">
var childLoaded = false;
t = async_test("Test document type embedding");
addEventListener("load", t.step_func_done(function() { assert_true(childLoaded); }));
window.childLoaded = false;
async_test(function() {
addEventListener("load", this.step_func_done(function() {
assert_true(window.childLoaded);
}));
}, "Test document type embedding");
</script>
<embed src="embed-iframe.html">
</body>

View file

@ -23,25 +23,25 @@ var btn = document.getElementById("btn"),
document.forms.fm1.onsubmit = t1.step_func(function (evt) {
evt.preventDefault();
assert_true(evt.isTrusted, "The isTrusted attribute of the submit event shoud be true.");
assert_true(evt.bubbles, "The bubbles attribute of the submit event shoud be true.");
assert_true(evt.cancelable, "The cancelable attribute of the submit event shoud be true.");
assert_true(evt.isTrusted, "The isTrusted attribute of the submit event should be true.");
assert_true(evt.bubbles, "The bubbles attribute of the submit event should be true.");
assert_true(evt.cancelable, "The cancelable attribute of the submit event should be true.");
assert_true(evt instanceof Event, "The submit event is an instance of Event interface.");
t1.done();
});
document.forms.fm1.onreset = t2.step_func(function (evt) {
assert_true(evt.isTrusted, "The isTrusted attribute of the reset event shoud be true.");
assert_true(evt.bubbles, "The bubbles attribute of the reset event shoud be true.");
assert_true(evt.cancelable, "The cancelable attribute of the reset event shoud be true.");
assert_true(evt.isTrusted, "The isTrusted attribute of the reset event should be true.");
assert_true(evt.bubbles, "The bubbles attribute of the reset event should be true.");
assert_true(evt.cancelable, "The cancelable attribute of the reset event should be true.");
assert_true(evt instanceof Event, "The reset event is an instance of Event interface.");
t2.done();
});
document.getElementById("menu").onshow = t3.step_func(function (evt) {
assert_true(evt.isTrusted, "The isTrusted attribute of the show event shoud be true.");
assert_true(evt.isTrusted, "The isTrusted attribute of the show event should be true.");
assert_equals(evt.relatedTarget, menu_btn, "The relatedTarget attribute should be initialized to the related button element.");
assert_true(evt.cancelable, "The cancelable attribute of the show event shoud be true.");
assert_true(evt.cancelable, "The cancelable attribute of the show event should be true.");
assert_true(evt instanceof RelatedEvent, "The show event is an instance of RelatedEvent interface.");
t3.done();
});

View file

@ -2,7 +2,8 @@
<meta charset=utf-8>
<title>input type checkbox</title>
<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
<link rel=help href="https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox)">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox)">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
@ -19,28 +20,39 @@
checkbox4 = document.getElementById('checkbox4'),
checkbox5 = document.getElementById('checkbox5'),
checkbox6 = document.getElementById('checkbox6'),
c1_input_fired = false, c1_change_fired = false,
t1 = async_test("click on mutable checkbox fires the input and change events"),
c1_click_fired = false,
c1_input_fired = false,
c1_change_fired = false,
t1 = async_test("click on mutable checkbox fires a click event, then an input event, then a change event"),
t2 = async_test("click on non-mutable checkbox doesn't fire the input or change event"),
t3 = async_test("pre-activation steps on unchecked checkbox"),
t4 = async_test("pre-activation steps on checked checkbox"),
t5 = async_test("canceled activation steps on unchecked checkbox"),
t6 = async_test("canceled activation steps on unchecked checkbox (indeterminate=true in onclick)");
checkbox1.oninput= t1.step_func(function(e) {
checkbox1.onclick = t1.step_func(function () {
c1_click_fired = true;
assert_false(c1_input_fired, "click event should fire before input event");
assert_false(c1_change_fired, "click event should fire before change event");
});
checkbox1.oninput = t1.step_func(function(e) {
c1_input_fired = true;
assert_true(c1_click_fired, "input event should fire after click event");
assert_false(c1_change_fired, "input event should fire before change event");
assert_true(e.bubbles, "event should bubble");
assert_true(e.isTrusted, "event should be trusted");
assert_false(e.cancelable, "event shoud not be cancelable");
assert_false(e.isTrusted, "click()-initiated event should be trusted");
assert_false(e.cancelable, "event should not be cancelable");
assert_true(checkbox1.checked, "checkbox is checked");
assert_false(checkbox1.indeterminate, "checkbox is not indeterminate");
});
checkbox1.onchange = t1.step_func(function(e) {
c1_change_fired = true;
assert_true(c1_click_fired, "change event should fire after click event");
assert_true(c1_input_fired, "change event should fire after input event");
assert_true(e.bubbles, "event should bubble")
assert_true(e.isTrusted, "event should be trusted");
assert_false(e.cancelable, "event shoud not be cancelable");
assert_false(e.isTrusted, "click()-initiated event should be trusted");
assert_false(e.cancelable, "event should not be cancelable");
assert_true(checkbox1.checked, "checkbox is checked");
assert_false(checkbox1.indeterminate, "checkbox is not indeterminate");
});

View file

@ -18,12 +18,12 @@
document.getElementById('file').oninput = t1.step_func_done(function(e) {
assert_true(e.bubbles, "input event bubbles");
assert_true(e.isTrusted, "input event should be trusted");
assert_false(e.cancelable, "input event shoud not be cancelable");
assert_false(e.cancelable, "input event should not be cancelable");
})
document.getElementById('file').onchange = t2.step_func_done(function(e) {
assert_true(e.bubbles, "change event bubbles");
assert_true(e.isTrusted, "change event should be trusted");
assert_false(e.cancelable, "change event shoud not be cancelable");
assert_false(e.cancelable, "change event should not be cancelable");
assert_true(input.files instanceof FileList);
assert_equals(input.value, "C:\\fakepath\\" + input.files[0].name);
})

View file

@ -15,8 +15,8 @@
<input type=radio id=radio5>
<input type=radio id=radio6 disabled>
<input type=radio id=radio71 checked>
<input type=radio id=radio72>
<input type=radio name="group5" id=radio71 checked>
<input type=radio name="group5" id=radio72>
<input type=radio name=group3 id=radio8 checked>
<input type=radio name=group3 id=radio9>
@ -37,8 +37,7 @@
radio9 = document.getElementById('radio9'),
radio10 = document.getElementById('radio10'),
radio11 = document.getElementById('radio11'),
t1 = async_test("click on mutable radio fires the input event"),
t2 = async_test("click on mutable radio fires the change event"),
t1 = async_test("click on mutable radio fires click event, then input event, then change event"),
t3 = async_test("click on non-mutable radio doesn't fire the input event"),
t4 = async_test("click on non-mutable radio doesn't fire the change event"),
t5 = async_test("canceled activation steps on unchecked radio"),
@ -80,18 +79,28 @@
assert_false(radio11.checked);
}, "changing the name of a radio input element and setting its checkedness to true makes all the other elements' checkedness in the same radio button group be set to false");
radio5.oninput= t1.step_func(function(e) {
input_fired = true;
assert_true(e.bubbles, "event should bubble")
assert_true(e.isTrusted, "event should be trusted");
assert_false(e.cancelable, "event shoud not be cancelable");
radio5.onclick = t1.step_func(function(e) {
click_fired = true;
assert_false(input_fired, "click event should fire before input event");
assert_false(change_fired, "click event should fire before change event");
});
radio5.onchange = t2.step_func(function(e) {
radio5.oninput = t1.step_func(function(e) {
input_fired = true;
assert_true(click_fired, "input event should fire after click event");
assert_false(change_fired, "input event should fire before change event");
assert_true(e.bubbles, "input event should bubble")
assert_false(e.isTrusted, "click()-initiated input event shouldn't be trusted");
assert_false(e.cancelable, "input event should not be cancelable");
});
radio5.onchange = t1.step_func(function(e) {
change_fired = true;
assert_true(e.bubbles, "event should bubble")
assert_true(e.isTrusted, "event should be trusted");
assert_false(e.cancelable, "event shoud not be cancelable");
assert_true(click_fired, "change event should fire after click event");
assert_true(input_fired, "change event should fire after input event");
assert_true(e.bubbles, "change event should bubble")
assert_false(e.isTrusted, "click()-initiated change event shouldn't be trusted");
assert_false(e.cancelable, "change event should not be cancelable");
});
radio6.oninput= t3.step_func_done(function(e) {
@ -108,11 +117,6 @@
t1.done();
});
t2.step(function() {
assert_true(change_fired);
t2.done();
})
t3.step(function(){
radio6.click();
t3.done();
@ -120,18 +124,20 @@
});
radio72.onclick = t5.step_func_done(function(e){
assert_false(radio71.checked);
assert_true(radio72.checked);
assert_false(radio71.checked, "click on radio should uncheck other radio in same group");
assert_true(radio72.checked, "click on radio should check that radio");
e.preventDefault();
assert_false(radio71.checked);
assert_true(radio72.checked);
// The cancelation of the click doesn't have an effect until after all the click event handlers have been run.
assert_false(radio71.checked, "radio remains unchecked immediately after click event on other radio in same group is canceled");
assert_true(radio72.checked, "clicked radio remains checked immediately after click event is canceled");
});
t5.step(function(){
assert_true(radio71.checked);
assert_false(radio72.checked);
assert_true(radio71.checked, "initially checked radio should be checked");
assert_false(radio72.checked, "other radios in same group as initially-checked radio should be unchecked");
radio72.click();
assert_true(radio71.checked);
assert_false(radio72.checked);
// Now that the click event has been fully dispatched, its cancelation has taken effect.
assert_true(radio71.checked, "canceled click event on radio should leave the previously-checked radio checked");
assert_false(radio72.checked, "canceled click event on previously-unchecked radio should leave that radio unchecked");
});
</script>

View file

@ -0,0 +1,2 @@
@zqzhang
@tagawa

View file

@ -0,0 +1,4 @@
@bit
@acolwell
@shishimaru
@sideshowbarker

View file

@ -0,0 +1,2 @@
@hillbrad
@foolip

View file

@ -0,0 +1,3 @@
@dontcallmedom
@alvestrand

View file

@ -0,0 +1 @@
@kristijanburnik

View file

@ -0,0 +1,2 @@
@plehegar
@foolip

View file

@ -0,0 +1,4 @@
@chunywang
@sideshowbarker
@xinliux
@ibelem

View file

@ -1,11 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Sandbox: iframe sandbox attribute value support DOMSettableTokenList interface.</title>
<title>HTML5 Sandbox: iframe sandbox attribute value support DOMTokenList interface.</title>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#the-iframe-element" />
<meta name="assert" content="iframe sandbox attribute value support DOMSettableTokenList interface." />
<meta name="assert" content="iframe sandbox attribute value support DOMTokenList interface." />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
@ -13,53 +13,53 @@
<div id=log></div>
<iframe id="iframe1" src="about:blank" sandbox="allow-scripts allow-same-origin allow-forms" style="display : none"></iframe>
<script type="text/javascript">
test(function() {
var iframeEle = document.getElementById("iframe1");
assert_equals(iframeEle.sandbox.length, 3)
}, "DOMSettableTokenList length")
}, "DOMTokenList length")
test(function() {
var iframeEle = document.getElementById("iframe1");
assert_equals(iframeEle.sandbox.item(1), "allow-same-origin")
}, "DOMSettableTokenList item(index)")
}, "DOMTokenList item(index)")
test(function() {
var iframeEle = document.getElementById("iframe1");
assert_true(iframeEle.sandbox.contains("allow-forms"))
}, "DOMSettableTokenList contains(DomString)")
}, "DOMTokenList contains(DomString)")
test(function() {
var iframeEle = document.getElementById("iframe1");
var iframeEle = document.getElementById("iframe1");
iframeEle.sandbox.add("ALLOW-SANDBOX");
assert_true(iframeEle.sandbox.contains("ALLOW-SANDBOX"))
}, "DOMSettableTokenList add(DomString)")
}, "DOMTokenList add(DomString)")
test(function() {
var iframeEle = document.getElementById("iframe1");
iframeEle.sandbox.remove("ALLOW-SANDBOX");
assert_false(iframeEle.sandbox.contains("ALLOW-SANDBOX"))
}, "DOMSettableTokenList remove(DomString)")
}, "DOMTokenList remove(DomString)")
test(function() {
var iframeEle = document.getElementById("iframe1");
iframeEle.sandbox.remove("ALLOW-SANDBOX");
assert_true(
assert_true(
iframeEle.sandbox.toggle("allow-top-navigation") && iframeEle.sandbox.contains("allow-top-navigation") &&
!iframeEle.sandbox.toggle("allow-top-navigation") && !iframeEle.sandbox.contains("allow-top-navigation")
)
}, "DOMSettableTokenList toggle(DomString) - Returns true if token is now present (it was added); returns false if it is not (it was removed).")
}, "DOMTokenList toggle(DomString) - Returns true if token is now present (it was added); returns false if it is not (it was removed).")
test(function() {
var iframeEle = document.getElementById("iframe1");
assert_equals(iframeEle.sandbox.value, iframeEle.sandbox.toString())
}, "DOMSettableTokenList sandbox.toString()")
}, "DOMTokenList sandbox.toString()")
test(function() {
var iframeEle = document.getElementById("iframe1");
iframeEle.sandbox.remove("ALLOW-SANDBOX");
assert_true(iframeEle.sandbox.contains("allow-scripts") != iframeEle.sandbox.contains("Allow-SCRIPTS"))
}, "DOMSettableTokenList case sensitivity")
}, "DOMTokenList case sensitivity")
</script>
</body>
</html>

View file

@ -0,0 +1,2 @@
@plehegar
@foolip

View file

@ -0,0 +1 @@
@plehegar

View file

@ -0,0 +1,7 @@
@bethge
@Steditor
@EvgenyAgafonchikov
@jacobrossi
@plehegar
@scottgonzalez
@staktrace

View file

@ -0,0 +1 @@
@plehegar

View file

@ -0,0 +1,2 @@
@zqzhang
@dontcallmedom

View file

@ -0,0 +1 @@
@zcorpan

View file

@ -0,0 +1 @@
@kristijanburnik

View file

@ -0,0 +1,3 @@
@haoxli
@plehegar
@zqzhang

View file

@ -0,0 +1 @@
@haoxli

View file

@ -0,0 +1 @@
@ayg

View file

@ -41,13 +41,6 @@ tests.forEach(function(arr) {
assert_equals(sheet.cssRules[0].cssText.substr(0, expected.length), expected);
}, input + ' getting CSSRule#cssText' + use_media);
test(function() {
var sheet = new_sheet(use_media);
sheet.insertRule('before_set {}', 0);
sheet.cssRules[0].cssText = input + ' {}';
assert_equals(sheet.cssRules[0].cssText.substr(0, expected.length), expected);
}, input + ' setting CSSRule#cssText' + use_media);
test(function() {
var sheet = new_sheet(use_media);
sheet.insertRule(input + ' {}', 0);

View file

@ -0,0 +1 @@
@ehsan

View file

@ -0,0 +1,2 @@
@inexorabletash
@wanderview

View file

@ -35,3 +35,203 @@ function cache_test(test_function, description) {
.then(test_function);
}, description);
}
// A set of Request/Response pairs to be used with prepopulated_cache_test().
var simple_entries = [
{
name: 'a',
request: new Request('http://example.com/a'),
response: new Response('')
},
{
name: 'b',
request: new Request('http://example.com/b'),
response: new Response('')
},
{
name: 'a_with_query',
request: new Request('http://example.com/a?q=r'),
response: new Response('')
},
{
name: 'A',
request: new Request('http://example.com/A'),
response: new Response('')
},
{
name: 'a_https',
request: new Request('https://example.com/a'),
response: new Response('')
},
{
name: 'a_org',
request: new Request('http://example.org/a'),
response: new Response('')
},
{
name: 'cat',
request: new Request('http://example.com/cat'),
response: new Response('')
},
{
name: 'catmandu',
request: new Request('http://example.com/catmandu'),
response: new Response('')
},
{
name: 'cat_num_lives',
request: new Request('http://example.com/cat?lives=9'),
response: new Response('')
},
{
name: 'cat_in_the_hat',
request: new Request('http://example.com/cat/in/the/hat'),
response: new Response('')
},
{
name: 'non_2xx_response',
request: new Request('http://example.com/non2xx'),
response: new Response('', {status: 404, statusText: 'nope'})
},
{
name: 'error_response',
request: new Request('http://example.com/error'),
response: Response.error()
},
];
// A set of Request/Response pairs to be used with prepopulated_cache_test().
// These contain a mix of test cases that use Vary headers.
var vary_entries = [
{
name: 'vary_cookie_is_cookie',
request: new Request('http://example.com/c',
{headers: {'Cookies': 'is-for-cookie'}}),
response: new Response('',
{headers: {'Vary': 'Cookies'}})
},
{
name: 'vary_cookie_is_good',
request: new Request('http://example.com/c',
{headers: {'Cookies': 'is-good-enough-for-me'}}),
response: new Response('',
{headers: {'Vary': 'Cookies'}})
},
{
name: 'vary_cookie_absent',
request: new Request('http://example.com/c'),
response: new Response('',
{headers: {'Vary': 'Cookies'}})
}
];
// Run |test_function| with a Cache object and a map of entries. Prior to the
// call, the Cache is populated by cache entries from |entries|. The latter is
// expected to be an Object mapping arbitrary keys to objects of the form
// {request: <Request object>, response: <Response object>}. There's no
// guarantee on the order in which entries will be added to the cache.
//
// |test_function| should return a Promise that can be used with promise_test.
function prepopulated_cache_test(entries, test_function, description) {
cache_test(function(cache) {
var p = Promise.resolve();
var hash = {};
return Promise.all(entries.map(function(entry) {
hash[entry.name] = entry;
return cache.put(entry.request.clone(),
entry.response.clone())
.catch(function(e) {
assert_unreached(
'Test setup failed for entry ' + entry.name + ': ' + e);
});
}))
.then(function() {
assert_equals(Object.keys(hash).length, entries.length);
})
.then(function() {
return test_function(cache, hash);
});
}, description);
}
// Helper for testing with Headers objects. Compares Headers instances
// by serializing |expected| and |actual| to arrays and comparing.
function assert_header_equals(actual, expected, description) {
assert_class_string(actual, "Headers", description);
var header;
var actual_headers = [];
var expected_headers = [];
for (header of actual)
actual_headers.push(header[0] + ": " + header[1]);
for (header of expected)
expected_headers.push(header[0] + ": " + header[1]);
assert_array_equals(actual_headers, expected_headers,
description + " Headers differ.");
}
// Helper for testing with Response objects. Compares simple
// attributes defined on the interfaces, as well as the headers. It
// does not compare the response bodies.
function assert_response_equals(actual, expected, description) {
assert_class_string(actual, "Response", description);
["type", "url", "status", "ok", "statusText"].forEach(function(attribute) {
assert_equals(actual[attribute], expected[attribute],
description + " Attributes differ: " + attribute + ".");
});
assert_header_equals(actual.headers, expected.headers, description);
}
// Assert that the two arrays |actual| and |expected| contain the same
// set of Responses as determined by assert_response_equals. The order
// is not significant.
//
// |expected| is assumed to not contain any duplicates.
function assert_response_array_equivalent(actual, expected, description) {
assert_true(Array.isArray(actual), description);
assert_equals(actual.length, expected.length, description);
expected.forEach(function(expected_element) {
// assert_response_in_array treats the first argument as being
// 'actual', and the second as being 'expected array'. We are
// switching them around because we want to be resilient
// against the |actual| array containing duplicates.
assert_response_in_array(expected_element, actual, description);
});
}
// Asserts that two arrays |actual| and |expected| contain the same
// set of Responses as determined by assert_response_equals(). The
// corresponding elements must occupy corresponding indices in their
// respective arrays.
function assert_response_array_equals(actual, expected, description) {
assert_true(Array.isArray(actual), description);
assert_equals(actual.length, expected.length, description);
actual.forEach(function(value, index) {
assert_response_equals(value, expected[index],
description + " : object[" + index + "]");
});
}
// Equivalent to assert_in_array, but uses assert_response_equals.
function assert_response_in_array(actual, expected_array, description) {
assert_true(expected_array.some(function(element) {
try {
assert_response_equals(actual, element);
return true;
} catch (e) {
return false;
}
}), description);
}

View file

@ -31,70 +31,3 @@ function assert_promise_rejects(promise, code, description) {
}
});
}
// Helper for testing with Headers objects. Compares Headers instances
// by serializing |expected| and |actual| to arrays and comparing.
function assert_header_equals(actual, expected, description) {
assert_class_string(actual, "Headers", description);
var header, actual_headers = [], expected_headers = [];
for (header of actual)
actual_headers.push(header[0] + ": " + header[1]);
for (header of expected)
expected_headers.push(header[0] + ": " + header[1]);
assert_array_equals(actual_headers, expected_headers,
description + " Headers differ.");
}
// Helper for testing with Response objects. Compares simple
// attributes defined on the interfaces, as well as the headers. It
// does not compare the response bodies.
function assert_response_equals(actual, expected, description) {
assert_class_string(actual, "Response", description);
["type", "url", "status", "ok", "statusText"].forEach(function(attribute) {
assert_equals(actual[attribute], expected[attribute],
description + " Attributes differ: " + attribute + ".");
});
assert_header_equals(actual.headers, expected.headers, description);
}
// Assert that the two arrays |actual| and |expected| contain the same
// set of Responses as determined by assert_response_equals. The order
// is not significant.
//
// |expected| is assumed to not contain any duplicates.
function assert_response_array_equivalent(actual, expected, description) {
assert_true(Array.isArray(actual), description);
assert_equals(actual.length, expected.length, description);
expected.forEach(function(expected_element) {
// assert_response_in_array treats the first argument as being
// 'actual', and the second as being 'expected array'. We are
// switching them around because we want to be resilient
// against the |actual| array containing duplicates.
assert_response_in_array(expected_element, actual, description);
});
}
// Asserts that two arrays |actual| and |expected| contain the same
// set of Responses as determined by assert_response_equals(). The
// corresponding elements must occupy corresponding indices in their
// respective arrays.
function assert_response_array_equals(actual, expected, description) {
assert_true(Array.isArray(actual), description);
assert_equals(actual.length, expected.length, description);
actual.forEach(function(value, index) {
assert_response_equals(value, expected[index],
description + " : object[" + index + "]");
});
}
// Equivalent to assert_in_array, but uses assert_response_equals.
function assert_response_in_array(actual, expected_array, description) {
assert_true(expected_array.some(function(element) {
try {
assert_response_equals(actual, element);
return true;
} catch (e) {
return false;
}
}), description);
}

View file

@ -16,6 +16,16 @@ cache_test(function(cache) {
.then(function(result) {
assert_equals(result, undefined,
'Cache.add should resolve with undefined on success.');
return cache.match('../resources/simple.txt');
})
.then(function(response) {
assert_class_string(response, 'Response',
'Cache.add should put a resource in the cache.');
return response.text();
})
.then(function(body) {
assert_equals(body, 'a simple text file\n',
'Cache.add should retrieve the correct body.');
});
}, 'Cache.add called with relative URL specified as a string');
@ -35,6 +45,15 @@ cache_test(function(cache) {
});
}, 'Cache.add called with Request object');
cache_test(function(cache) {
var request = new Request('../resources/simple.txt',
{method: 'POST', body: 'This is a body.'});
return assert_promise_rejects(
cache.add(request),
new TypeError(),
'Cache.add should throw a TypeError for non-GET requests.');
}, 'Cache.add called with POST request');
cache_test(function(cache) {
var request = new Request('../resources/simple.txt');
return cache.add(request)
@ -51,6 +70,17 @@ cache_test(function(cache) {
});
}, 'Cache.add called twice with the same Request object');
cache_test(function(cache) {
var request = new Request('../resources/simple.txt');
return request.text()
.then(function() {
assert_false(request.bodyUsed);
})
.then(function() {
return cache.add(request);
});
}, 'Cache.add with request with null body (not consumed)');
cache_test(function(cache) {
return cache.add('this-does-not-exist-please-dont-create-it')
.then(function(result) {
@ -84,19 +114,62 @@ cache_test(function(cache) {
}, 'Cache.addAll with a mix of valid and undefined arguments');
cache_test(function(cache) {
// Assumes the existence of ../resources/simple.txt and ../resources/blank.html
var urls = ['../resources/simple.txt', self.location.href, '../resources/blank.html'];
return cache.addAll([])
.then(function(result) {
assert_equals(result, undefined,
'Cache.addAll should resolve with undefined on ' +
'success.');
return cache.keys();
})
.then(function(result) {
assert_equals(result.length, 0,
'There should be no entry in the cache.');
});
}, 'Cache.addAll with an empty array');
cache_test(function(cache) {
// Assumes the existence of ../resources/simple.txt and
// ../resources/blank.html
var urls = ['../resources/simple.txt',
self.location.href,
'../resources/blank.html'];
return cache.addAll(urls)
.then(function(result) {
assert_equals(result, undefined,
'Cache.addAll should resolve with undefined on ' +
'success.');
return Promise.all(
urls.map(function(url) { return cache.match(url); }));
})
.then(function(responses) {
assert_class_string(
responses[0], 'Response',
'Cache.addAll should put a resource in the cache.');
assert_class_string(
responses[1], 'Response',
'Cache.addAll should put a resource in the cache.');
assert_class_string(
responses[2], 'Response',
'Cache.addAll should put a resource in the cache.');
return Promise.all(
responses.map(function(response) { return response.text(); }));
})
.then(function(bodies) {
assert_equals(
bodies[0], 'a simple text file\n',
'Cache.add should retrieve the correct body.');
assert_equals(
bodies[2], '<!DOCTYPE html>\n<title>Empty doc</title>\n',
'Cache.add should retrieve the correct body.');
});
}, 'Cache.addAll with string URL arguments');
cache_test(function(cache) {
// Assumes the existence of ../resources/simple.txt and ../resources/blank.html
var urls = ['../resources/simple.txt', self.location.href, '../resources/blank.html'];
// Assumes the existence of ../resources/simple.txt and
// ../resources/blank.html
var urls = ['../resources/simple.txt',
self.location.href,
'../resources/blank.html'];
var requests = urls.map(function(url) {
return new Request(url);
});
@ -105,13 +178,38 @@ cache_test(function(cache) {
assert_equals(result, undefined,
'Cache.addAll should resolve with undefined on ' +
'success.');
return Promise.all(
urls.map(function(url) { return cache.match(url); }));
})
.then(function(responses) {
assert_class_string(
responses[0], 'Response',
'Cache.addAll should put a resource in the cache.');
assert_class_string(
responses[1], 'Response',
'Cache.addAll should put a resource in the cache.');
assert_class_string(
responses[2], 'Response',
'Cache.addAll should put a resource in the cache.');
return Promise.all(
responses.map(function(response) { return response.text(); }));
})
.then(function(bodies) {
assert_equals(
bodies[0], 'a simple text file\n',
'Cache.add should retrieve the correct body.');
assert_equals(
bodies[2], '<!DOCTYPE html>\n<title>Empty doc</title>\n',
'Cache.add should retrieve the correct body.');
});
}, 'Cache.addAll with Request arguments');
cache_test(function(cache) {
// Assumes that ../resources/simple.txt and ../resources/blank.html exist. The second
// resource does not.
var urls = ['../resources/simple.txt', 'this-resource-should-not-exist', '../resources/blank.html'];
// Assumes that ../resources/simple.txt and ../resources/blank.html exist.
// The second resource does not.
var urls = ['../resources/simple.txt',
'this-resource-should-not-exist',
'../resources/blank.html'];
var requests = urls.map(function(url) {
return new Request(url);
});
@ -120,6 +218,32 @@ cache_test(function(cache) {
assert_equals(result, undefined,
'Cache.addAll should resolve with undefined on ' +
'success.');
return Promise.all(
urls.map(function(url) { return cache.match(url); }));
})
.then(function(responses) {
assert_class_string(
responses[0], 'Response',
'Cache.addAll should put a resource in the cache.');
assert_class_string(
responses[1], 'Response',
'Cache.addAll should put a resource in the cache.');
assert_equals(
responses[1].status, 404,
'Cache.addAll should put a 404 resource in the cache.');
assert_class_string(
responses[2], 'Response',
'Cache.addAll should put a resource in the cache.');
return Promise.all(
responses.map(function(response) { return response.text(); }));
})
.then(function(bodies) {
assert_equals(
bodies[0], 'a simple text file\n',
'Cache.add should retrieve the correct body.');
assert_equals(
bodies[2], '<!DOCTYPE html>\n<title>Empty doc</title>\n',
'Cache.add should retrieve the correct body.');
});
}, 'Cache.addAll with a mix of succeeding and failing requests');

View file

@ -4,105 +4,6 @@ if (self.importScripts) {
importScripts('../resources/test-helpers.js');
}
// A set of Request/Response pairs to be used with prepopulated_cache_test().
var simple_entries = [
{
name: 'a',
request: new Request('http://example.com/a'),
response: new Response('')
},
{
name: 'b',
request: new Request('http://example.com/b'),
response: new Response('')
},
{
name: 'a_with_query',
request: new Request('http://example.com/a?q=r'),
response: new Response('')
},
{
name: 'A',
request: new Request('http://example.com/A'),
response: new Response('')
},
{
name: 'a_https',
request: new Request('https://example.com/a'),
response: new Response('')
},
{
name: 'a_org',
request: new Request('http://example.org/a'),
response: new Response('')
},
{
name: 'cat',
request: new Request('http://example.com/cat'),
response: new Response('')
},
{
name: 'catmandu',
request: new Request('http://example.com/catmandu'),
response: new Response('')
},
{
name: 'cat_num_lives',
request: new Request('http://example.com/cat?lives=9'),
response: new Response('')
},
{
name: 'cat_in_the_hat',
request: new Request('http://example.com/cat/in/the/hat'),
response: new Response('')
}
];
// A set of Request/Response pairs to be used with prepopulated_cache_test().
// These contain a mix of test cases that use Vary headers.
var vary_entries = [
{
name: 'vary_cookie_is_cookie',
request: new Request('http://example.com/c',
{headers: {'Cookies': 'is-for-cookie'}}),
response: new Response('',
{headers: {'Vary': 'Cookies'}})
},
{
name: 'vary_cookie_is_good',
request: new Request('http://example.com/c',
{headers: {'Cookies': 'is-good-enough-for-me'}}),
response: new Response('',
{headers: {'Vary': 'Cookies'}})
},
{
name: 'vary_cookie_absent',
request: new Request('http://example.com/c'),
response: new Response('',
{headers: {'Vary': 'Cookies'}})
}
];
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll('not-present-in-the-cache')
.then(function(result) {
assert_response_array_equivalent(
result, [],
'Cache.matchAll should resolve with an empty array on failure.');
});
}, 'Cache.matchAll with no matching entries');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.match('not-present-in-the-cache')
.then(function(result) {
@ -111,14 +12,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) {
});
}, 'Cache.match with no matching entries');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(entries.a.request.url)
.then(function(result) {
assert_response_array_equals(result, [entries.a.response],
'Cache.matchAll should match by URL.');
});
}, 'Cache.matchAll with URL');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.match(entries.a.request.url)
.then(function(result) {
@ -127,15 +20,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) {
});
}, 'Cache.match with URL');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(entries.a.request)
.then(function(result) {
assert_response_array_equals(
result, [entries.a.response],
'Cache.matchAll should match by Request.');
});
}, 'Cache.matchAll with Request');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.match(entries.a.request)
.then(function(result) {
@ -144,15 +28,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) {
});
}, 'Cache.match with Request');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(new Request(entries.a.request.url))
.then(function(result) {
assert_response_array_equals(
result, [entries.a.response],
'Cache.matchAll should match by Request.');
});
}, 'Cache.matchAll with new Request');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.match(new Request(entries.a.request.url))
.then(function(result) {
@ -161,23 +36,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) {
});
}, 'Cache.match with new Request');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(entries.a.request,
{ignoreSearch: true})
.then(function(result) {
assert_response_array_equivalent(
result,
[
entries.a.response,
entries.a_with_query.response
],
'Cache.matchAll with ignoreSearch should ignore the ' +
'search parameters of cached request.');
});
},
'Cache.matchAll with ignoreSearch option (request with no search ' +
'parameters)');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.match(entries.a.request,
{ignoreSearch: true})
@ -195,22 +53,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) {
'Cache.match with ignoreSearch option (request with no search ' +
'parameters)');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(entries.a_with_query.request,
{ignoreSearch: true})
.then(function(result) {
assert_response_array_equivalent(
result,
[
entries.a.response,
entries.a_with_query.response
],
'Cache.matchAll with ignoreSearch should ignore the ' +
'search parameters of request.');
});
},
'Cache.matchAll with ignoreSearch option (request with search parameter)');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.match(entries.a_with_query.request,
{ignoreSearch: true})
@ -227,18 +69,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) {
},
'Cache.match with ignoreSearch option (request with search parameter)');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(entries.cat.request.url + '#mouse')
.then(function(result) {
assert_response_array_equivalent(
result,
[
entries.cat.response,
],
'Cache.matchAll should ignore URL fragment.');
});
}, 'Cache.matchAll with URL containing fragment');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.match(entries.cat.request.url + '#mouse')
.then(function(result) {
@ -247,16 +77,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) {
});
}, 'Cache.match with URL containing fragment');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll('http')
.then(function(result) {
assert_response_array_equivalent(
result, [],
'Cache.matchAll should treat query as a URL and not ' +
'just a string fragment.');
});
}, 'Cache.matchAll with string fragment "http" as query');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.match('http')
.then(function(result) {
@ -267,48 +87,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) {
});
}, 'Cache.match with string fragment "http" as query');
prepopulated_cache_test(vary_entries, function(cache, entries) {
return cache.matchAll('http://example.com/c')
.then(function(result) {
assert_response_array_equivalent(
result,
[
entries.vary_cookie_absent.response
],
'Cache.matchAll should exclude matches if a vary header is ' +
'missing in the query request, but is present in the cached ' +
'request.');
})
.then(function() {
return cache.matchAll(
new Request('http://example.com/c',
{headers: {'Cookies': 'none-of-the-above'}}));
})
.then(function(result) {
assert_response_array_equivalent(
result,
[
],
'Cache.matchAll should exclude matches if a vary header is ' +
'missing in the cached request, but is present in the query ' +
'request.');
})
.then(function() {
return cache.matchAll(
new Request('http://example.com/c',
{headers: {'Cookies': 'is-for-cookie'}}));
})
.then(function(result) {
assert_response_array_equivalent(
result,
[entries.vary_cookie_is_cookie.response],
'Cache.matchAll should match the entire header if a vary header ' +
'is present in both the query and cached requests.');
});
}, 'Cache.matchAll with responses containing "Vary" header');
prepopulated_cache_test(vary_entries, function(cache, entries) {
return cache.match('http://example.com/c')
.then(function(result) {
@ -321,21 +99,6 @@ prepopulated_cache_test(vary_entries, function(cache, entries) {
});
}, 'Cache.match with responses containing "Vary" header');
prepopulated_cache_test(vary_entries, function(cache, entries) {
return cache.matchAll('http://example.com/c',
{ignoreVary: true})
.then(function(result) {
assert_response_array_equivalent(
result,
[
entries.vary_cookie_is_cookie.response,
entries.vary_cookie_is_good.response,
entries.vary_cookie_absent.response,
],
'Cache.matchAll should honor "ignoreVary" parameter.');
});
}, 'Cache.matchAll with "ignoreVary" parameter');
cache_test(function(cache) {
var request = new Request('http://example.com');
var response;
@ -397,7 +160,7 @@ cache_test(function(cache) {
}, 'Cache.match invoked multiple times for the same Request/Response');
prepopulated_cache_test(simple_entries, function(cache, entries) {
var request = new Request(entries.a.request, { method: 'POST' });
var request = new Request(entries.a.request.clone(), {method: 'POST'});
return cache.match(request)
.then(function(result) {
assert_equals(result, undefined,
@ -405,38 +168,26 @@ prepopulated_cache_test(simple_entries, function(cache, entries) {
});
}, 'Cache.match with POST Request');
// Helpers ---
prepopulated_cache_test(simple_entries, function(cache, entries) {
var response = entries.non_2xx_response.response;
return cache.match(entries.non_2xx_response.request.url)
.then(function(result) {
assert_response_equals(
result, entries.non_2xx_response.response,
'Cache.match should return a Response object that has the ' +
'same properties as a stored non-2xx response.');
});
}, 'Cache.match with a non-2xx Response');
// Run |test_function| with a Cache object as its only parameter. Prior to the
// call, the Cache is populated by cache entries from |entries|. The latter is
// expected to be an Object mapping arbitrary keys to objects of the form
// {request: <Request object>, response: <Response object>}. There's no
// guarantee on the order in which entries will be added to the cache.
//
// |test_function| should return a Promise that can be used with promise_test.
function prepopulated_cache_test(entries, test_function, description) {
cache_test(function(cache) {
var p = Promise.resolve();
var hash = {};
entries.forEach(function(entry) {
p = p.then(function() {
return cache.put(entry.request.clone(),
entry.response.clone())
.catch(function(e) {
assert_unreached('Test setup failed for entry ' +
entry.name + ': ' + e);
});
});
hash[entry.name] = entry;
prepopulated_cache_test(simple_entries, function(cache, entries) {
var response = entries.error_response.response;
return cache.match(entries.error_response.request.url)
.then(function(result) {
assert_response_equals(
result, entries.error_response.response,
'Cache.match should return a Response object that has the ' +
'same properties as a stored network error response.');
});
p = p.then(function() {
assert_equals(Object.keys(hash).length, entries.length);
});
return p.then(function() {
return test_function(cache, hash);
});
}, description);
}
}, 'Cache.match with a network error Response');
done();

View file

@ -0,0 +1,154 @@
if (self.importScripts) {
importScripts('/resources/testharness.js');
importScripts('../resources/testharness-helpers.js');
importScripts('../resources/test-helpers.js');
}
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll('not-present-in-the-cache')
.then(function(result) {
assert_response_array_equivalent(
result, [],
'Cache.matchAll should resolve with an empty array on failure.');
});
}, 'Cache.matchAll with no matching entries');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(entries.a.request.url)
.then(function(result) {
assert_response_array_equals(result, [entries.a.response],
'Cache.matchAll should match by URL.');
});
}, 'Cache.matchAll with URL');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(entries.a.request)
.then(function(result) {
assert_response_array_equals(
result, [entries.a.response],
'Cache.matchAll should match by Request.');
});
}, 'Cache.matchAll with Request');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(new Request(entries.a.request.url))
.then(function(result) {
assert_response_array_equals(
result, [entries.a.response],
'Cache.matchAll should match by Request.');
});
}, 'Cache.matchAll with new Request');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(entries.a.request,
{ignoreSearch: true})
.then(function(result) {
assert_response_array_equivalent(
result,
[
entries.a.response,
entries.a_with_query.response
],
'Cache.matchAll with ignoreSearch should ignore the ' +
'search parameters of cached request.');
});
},
'Cache.matchAll with ignoreSearch option (request with no search ' +
'parameters)');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(entries.a_with_query.request,
{ignoreSearch: true})
.then(function(result) {
assert_response_array_equivalent(
result,
[
entries.a.response,
entries.a_with_query.response
],
'Cache.matchAll with ignoreSearch should ignore the ' +
'search parameters of request.');
});
},
'Cache.matchAll with ignoreSearch option (request with search parameter)');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll(entries.cat.request.url + '#mouse')
.then(function(result) {
assert_response_array_equivalent(
result,
[
entries.cat.response,
],
'Cache.matchAll should ignore URL fragment.');
});
}, 'Cache.matchAll with URL containing fragment');
prepopulated_cache_test(simple_entries, function(cache, entries) {
return cache.matchAll('http')
.then(function(result) {
assert_response_array_equivalent(
result, [],
'Cache.matchAll should treat query as a URL and not ' +
'just a string fragment.');
});
}, 'Cache.matchAll with string fragment "http" as query');
prepopulated_cache_test(vary_entries, function(cache, entries) {
return cache.matchAll('http://example.com/c')
.then(function(result) {
assert_response_array_equivalent(
result,
[
entries.vary_cookie_absent.response
],
'Cache.matchAll should exclude matches if a vary header is ' +
'missing in the query request, but is present in the cached ' +
'request.');
})
.then(function() {
return cache.matchAll(
new Request('http://example.com/c',
{headers: {'Cookies': 'none-of-the-above'}}));
})
.then(function(result) {
assert_response_array_equivalent(
result,
[
],
'Cache.matchAll should exclude matches if a vary header is ' +
'missing in the cached request, but is present in the query ' +
'request.');
})
.then(function() {
return cache.matchAll(
new Request('http://example.com/c',
{headers: {'Cookies': 'is-for-cookie'}}));
})
.then(function(result) {
assert_response_array_equivalent(
result,
[entries.vary_cookie_is_cookie.response],
'Cache.matchAll should match the entire header if a vary header ' +
'is present in both the query and cached requests.');
});
}, 'Cache.matchAll with responses containing "Vary" header');
prepopulated_cache_test(vary_entries, function(cache, entries) {
return cache.matchAll('http://example.com/c',
{ignoreVary: true})
.then(function(result) {
assert_response_array_equivalent(
result,
[
entries.vary_cookie_is_cookie.response,
entries.vary_cookie_is_good.response,
entries.vary_cookie_absent.response
],
'Cache.matchAll should honor "ignoreVary" parameter.');
});
}, 'Cache.matchAll with "ignoreVary" parameter');
done();

View file

@ -250,16 +250,22 @@ cache_test(function(cache) {
assert_true(
response.bodyUsed,
'[https://fetch.spec.whatwg.org/#concept-body-consume-body] ' +
'The text() method should set "body used" flag.');
return assert_promise_rejects(
cache.put(new Request(test_url), response),
new TypeError,
'[https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cache-put] ' +
'Cache put should reject with TypeError when Response ' +
'body is already used.');
});
'The text() method should make the body disturbed.');
var request = new Request(test_url);
return cache.put(request, response).then(() => {
assert_unreached('cache.put should be rejected');
}, () => {});
});
}, 'Cache.put with a used response body');
cache_test(function(cache) {
var response = new Response(test_body);
return cache.put(new Request(test_url), response)
.then(function() {
assert_throws(new TypeError(), () => response.body.getReader());
});
}, 'getReader() after Cache.put');
cache_test(function(cache) {
return assert_promise_rejects(
cache.put(new Request(test_url),

View file

@ -106,7 +106,6 @@ promise_test(function(t) {
promise_test(function(t) {
var cache_name = 'cache-storage/open';
var url = '../resources/simple.txt';
var cache;
return self.caches.delete(cache_name)
.then(function() {
@ -135,7 +134,7 @@ promise_test(function(t) {
assert_array_equals(actual_urls, expected_urls,
'CacheStorage.open should return a new Cache ' +
'object for the same backing store.');
})
});
}, 'CacheStorage.open with existing cache');
promise_test(function(t) {

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<title>Cache.match and Cache.matchAll</title>
<title>Cache.match</title>
<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-match">
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<title>Cache.matchAll</title>
<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-matchall">
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../service-workers/resources/test-helpers.js"></script>
<script>
service_worker_test('../script-tests/cache-matchAll.js');
</script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<title>Cache Storage: Cache.match and Cache.matchAll</title>
<title>Cache Storage: Cache.match</title>
<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-match">
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>

Some files were not shown because too many files have changed in this diff Show more