Bug 1103906 - Update web-platform-tests to revision 551060ba2eb3fa6d1c713c179d52fdf1132ea50c, a=testonly

--HG--
rename : testing/web-platform/tests/dom/nodes/Document-createComment.html => testing/web-platform/tests/dom/nodes/Document-createTextNode.html
rename : testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-baseline.html => testing/web-platform/tests/selectors-api/tests/submissions/Opera/Element-matches.html
rename : testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-baseline.html => testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-find-findAll.html
rename : testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-lib.js => testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-find-findAll.js
This commit is contained in:
James Graham 2014-11-24 12:56:30 +00:00
parent 1b1a24b820
commit 174983d7b3
72 changed files with 1682 additions and 1115 deletions

View File

@ -0,0 +1,83 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Re-initializing events while dispatching them</title>
<link rel="author" title="Josh Matthews" href="mailto:josh@joshmatthews.net">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
var events = {
'KeyboardEvent': {
'constructor': function() { return new KeyboardEvent("type", {key: "A"}); },
'init': function(ev) { ev.initKeyboardEvent("type2", true, true, null, "a", 1, "", true, "") },
'check': function(ev) {
assert_equals(ev.key, "A", "initKeyboardEvent key setter should short-circuit");
assert_false(ev.repeat, "initKeyboardEvent repeat setter should short-circuit");
assert_equals(ev.location, 0, "initKeyboardEvent location setter should short-circuit");
}
},
'MouseEvent': {
'constructor': function() { return new MouseEvent("type"); },
'init': function(ev) { ev.initMouseEvent("type2", true, true, null, 0, 1, 1, 1, 1, true, true, true, true, 1, null) },
'check': function(ev) {
assert_equals(ev.screenX, 0, "initMouseEvent screenX setter should short-circuit");
assert_equals(ev.screenY, 0, "initMouseEvent screenY setter should short-circuit");
assert_equals(ev.clientX, 0, "initMouseEvent clientX setter should short-circuit");
assert_equals(ev.clientY, 0, "initMouseEvent clientY setter should short-circuit");
assert_false(ev.ctrlKey, "initMouseEvent ctrlKey setter should short-circuit");
assert_false(ev.altKey, "initMouseEvent altKey setter should short-circuit");
assert_false(ev.shiftKey, "initMouseEvent shiftKey setter should short-circuit");
assert_false(ev.metaKey, "initMouseEvent metaKey setter should short-circuit");
assert_equals(ev.button, 0, "initMouseEvent button setter should short-circuit");
}
},
'CustomEvent': {
'constructor': function() { return new CustomEvent("type") },
'init': function(ev) { ev.initCustomEvent("type2", true, true, 1) },
'check': function(ev) {
assert_equals(ev.detail, null, "initCustomEvent detail setter should short-circuit");
}
},
'UIEvent': {
'constructor': function() { return new UIEvent("type") },
'init': function(ev) { ev.initUIEvent("type2", true, true, window, 1) },
'check': function(ev) {
assert_equals(ev.view, null, "initUIEvent view setter should short-circuit");
assert_equals(ev.detail, 0, "initUIEvent detail setter should short-circuit");
}
},
'Event': {
'constructor': function() { return new Event("type") },
'init': function(ev) { ev.initEvent("type2", true, true) },
'check': function(ev) {
assert_equals(ev.bubbles, false, "initEvent bubbles setter should short-circuit");
assert_equals(ev.cancelable, false, "initEvent cancelable setter should short-circuit");
assert_equals(ev.type, "type", "initEvent type setter should short-circuit");
}
}
};
var names = Object.keys(events);
for (var i = 0; i < names.length; i++) {
var t = async_test("Calling init" + names[i] + " while dispatching.");
t.step(function() {
var e = events[names[i]].constructor();
var target = document.createElement("div")
target.addEventListener("type", t.step_func(function() {
events[names[i]].init(e);
var o = e;
while ((o = Object.getPrototypeOf(o))) {
if (!(o.constructor.name in events)) {
break;
}
events[o.constructor.name].check(e);
}
}), false);
assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
});
t.done();
}
</script>

View File

@ -1,75 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title> addEventListener() optional parameter: useCapture </title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<div id=log></div>
<table id="table" border="1" style="display: none">
<tbody id="table-body">
<tr id="table-row">
<td id="table-cell">Shady Grove</td>
<td>Aeolian</td>
</tr>
<tr id="parent">
<td id="target">Over the river, Charlie</td>
<td>Dorian</td>
</tr>
</tbody>
</table>
<script>
var EVENT = "foo";
var TARGET = document.getElementById("target");
var PARENT = document.getElementById("parent");
var TBODY = document.getElementById("table-body");
var TABLE = document.getElementById("table");
var BODY = document.body;
var HTML = document.documentElement;
var CurrentTargets = [TARGET, PARENT, TBODY, TABLE, BODY, HTML, document, window];
var ExpectResult = CurrentTargets;
var ActualResult = [];
var ExpectPhases = [2,3,3,3,3,3,3,3];
var ActualPhases = [];
var description = "Test Description: " +
"useCapture is an optional parameter for EventTarget.addEventListener and EventTarget.removeEventListener. " +
"If it is not provided, both methods must behave as if useCapture were specified to be false.";
var EventHandlers = [ function(evt){ TestEvent(evt, 0); }, function(evt){ TestEvent(evt, 1); } ]
test(function()
{
for (var i=0; i < CurrentTargets.length; i++)
{
CurrentTargets[i].addEventListener(EVENT, TestEvent);
}
var evt = document.createEvent("Event");
evt.initEvent(EVENT, true, true);
TARGET.dispatchEvent(evt);
for (var i=0; i < CurrentTargets.length; i++)
{
CurrentTargets[i].removeEventListener(EVENT, TestEvent);
}
TARGET.dispatchEvent(evt);
assert_array_equals(ActualResult, ExpectResult, "ActualResult");
assert_array_equals(ActualPhases, ExpectPhases, "ActualPhases");
}, description);
function TestEvent(evt, i)
{
ActualResult.push(evt.currentTarget);
ActualPhases.push(evt.eventPhase);
}
</script>
</body>
</html>

View File

@ -1,61 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title> dispatchEvent() return value and Event.preventDefault() </title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<div id=log></div>
<table id="table" border="1" style="display: none">
<tbody id="table-body">
<tr id="table-row">
<td id="table-cell">Shady Grove</td>
<td>Aeolian</td>
</tr>
<tr id="parent">
<td id="target">Over the river, Charlie</td>
<td>Dorian</td>
</tr>
</tbody>
</table>
<script>
var EVENT = "foo";
var TARGET = document.getElementById("target");
var PARENT = document.getElementById("parent");
var DefaultPrevented = false;
var description = "Test Description: " +
"dispatchEvent() return value indicates whether any of the listeners which handled the event called " +
"Event.preventDefault(). If Event.preventDefault() was called the returned value must be false, else " +
"it must be true.";
test(function()
{
PARENT.addEventListener(EVENT, function(e){TestEvent(e, 0)}, true);
TARGET.addEventListener(EVENT, function(e){TestEvent(e, 1)}, true);
TARGET.addEventListener(EVENT, function(e){TestEvent(e, 2)}, true);
var evt = document.createEvent("Event");
evt.initEvent(EVENT, true, true);
var ReturnValue1 = PARENT.dispatchEvent(evt);
var ReturnValue2 = TARGET.dispatchEvent(evt);
assert_array_equals([DefaultPrevented, ReturnValue1, ReturnValue2], [true, true, false]);
}, description);
function TestEvent(evt, i)
{
if (1 == i)
{
evt.preventDefault();
DefaultPrevented = evt.defaultPrevented;
}
}
</script>
</body>
</html>

View File

@ -1,75 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title> addEventListener() optional parameter: useCapture </title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<div id=log></div>
<table id="table" border="1" style="display: none">
<tbody id="table-body">
<tr id="table-row">
<td id="table-cell">Shady Grove</td>
<td>Aeolian</td>
</tr>
<tr id="parent">
<td id="target">Over the river, Charlie</td>
<td>Dorian</td>
</tr>
</tbody>
</table>
<script>
var EVENT = "foo";
var TARGET = document.getElementById("target");
var PARENT = document.getElementById("parent");
var TBODY = document.getElementById("table-body");
var TABLE = document.getElementById("table");
var BODY = document.body;
var HTML = document.documentElement;
var CurrentTargets = [TARGET, PARENT, TBODY, TABLE, BODY, HTML, document, window];
var ExpectResult = CurrentTargets;
var ActualResult = [];
var ExpectPhases = [2,3,3,3,3,3,3,3];
var ActualPhases = [];
var description = "Test Description: " +
"useCapture is an optional parameter for EventTarget.addEventListener and EventTarget.removeEventListener. " +
"If it is not provided, both methods must behave as if useCapture were specified to be false.";
var EventHandlers = [ function(evt){ TestEvent(evt, 0); }, function(evt){ TestEvent(evt, 1); } ]
test(function()
{
for (var i=0; i < CurrentTargets.length; i++)
{
CurrentTargets[i].addEventListener(EVENT, TestEvent);
}
var evt = document.createEvent("Event");
evt.initEvent(EVENT, true, true);
TARGET.dispatchEvent(evt);
for (var i=0; i < CurrentTargets.length; i++)
{
CurrentTargets[i].removeEventListener(EVENT, TestEvent);
}
TARGET.dispatchEvent(evt);
assert_array_equals(ActualResult, ExpectResult, "ActualResult");
assert_array_equals(ActualPhases, ExpectPhases, "ActualPhases");
}, description);
function TestEvent(evt, i)
{
ActualResult.push(evt.currentTarget);
ActualPhases.push(evt.eventPhase);
}
</script>
</body>
</html>

View File

@ -1,62 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title> dispatchEvent() return value and Event.preventDefault() </title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<div id=log></div>
<table id="table" border="1" style="display: none">
<tbody id="table-body">
<tr id="table-row">
<td id="table-cell">Shady Grove</td>
<td>Aeolian</td>
</tr>
<tr id="parent">
<td id="target">Over the river, Charlie</td>
<td>Dorian</td>
</tr>
</tbody>
</table>
<script>
var EVENT = "foo";
var TARGET = document.getElementById("target");
var PARENT = document.getElementById("parent");
var DefaultPrevented = false;
var description = "Test Description: " +
"dispatchEvent() return value indicates whether any of the listeners which handled the event called " +
"Event.preventDefault(). If Event.preventDefault() was called the returned value must be false, else " +
"it must be true.";
test(function()
{
PARENT.addEventListener(EVENT, function(e){TestEvent(e, 0)}, true);
TARGET.addEventListener(EVENT, function(e){TestEvent(e, 1)}, true);
TARGET.addEventListener(EVENT, function(e){TestEvent(e, 2)}, true);
var evt = document.createEvent("Event");
evt.initEvent(EVENT, true, true);
var ReturnValue1 = PARENT.dispatchEvent(evt);
var ReturnValue2 = TARGET.dispatchEvent(evt);
assert_array_equals([DefaultPrevented, ReturnValue1, ReturnValue2], [true, true, false]);
}, description);
function TestEvent(evt, i)
{
if (1 == i)
{
evt.preventDefault();
DefaultPrevented = evt.defaultPrevented;
}
}
</script>
</body>
</html>

View File

@ -10,9 +10,42 @@
<div id=log></div> <div id=log></div>
<script type=text/plain class=untested> <script type=text/plain class=untested>
[Constructor(DOMString type, optional EventInit eventInitDict)/*,
Exposed=(Window,Worker)*/]
interface Event {
readonly attribute DOMString type;
readonly attribute EventTarget? target;
readonly attribute EventTarget? currentTarget;
const unsigned short NONE = 0;
const unsigned short CAPTURING_PHASE = 1;
const unsigned short AT_TARGET = 2;
const unsigned short BUBBLING_PHASE = 3;
readonly attribute unsigned short eventPhase;
void stopPropagation();
void stopImmediatePropagation();
readonly attribute boolean bubbles;
readonly attribute boolean cancelable;
void preventDefault();
readonly attribute boolean defaultPrevented;
[Unforgeable] readonly attribute boolean isTrusted;
readonly attribute DOMTimeStamp timeStamp;
void initEvent(DOMString type, boolean bubbles, boolean cancelable);
};
dictionary EventInit {
boolean bubbles = false;
boolean cancelable = false;
};
/*[Exposed=(Window,Worker)]*/
interface EventTarget { interface EventTarget {
void addEventListener(DOMString type, EventListener? callback, optional boolean capture /* = false */); void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
void removeEventListener(DOMString type, EventListener? callback, optional boolean capture /* = false */); void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
boolean dispatchEvent(Event event); boolean dispatchEvent(Event event);
}; };
</script> </script>
@ -22,7 +55,8 @@ callback EventHandlerNonNull = any (Event event);
typedef EventHandlerNonNull? EventHandler; typedef EventHandlerNonNull? EventHandler;
</script> </script>
<script type=text/plain> <script type=text/plain>
[NoInterfaceObject] [NoInterfaceObject/*,
Exposed=(Window,Worker)*/]
interface XMLHttpRequestEventTarget : EventTarget { interface XMLHttpRequestEventTarget : EventTarget {
// event handlers // event handlers
attribute EventHandler onloadstart; attribute EventHandler onloadstart;
@ -34,6 +68,7 @@ interface XMLHttpRequestEventTarget : EventTarget {
attribute EventHandler onloadend; attribute EventHandler onloadend;
}; };
/*[Exposed=(Window,Worker)]*/
interface XMLHttpRequestUpload : XMLHttpRequestEventTarget { interface XMLHttpRequestUpload : XMLHttpRequestEventTarget {
}; };
@ -46,7 +81,8 @@ enum XMLHttpRequestResponseType {
"text" "text"
}; };
[Constructor] [Constructor/*,
Exposed=(Window,Worker)*/]
interface XMLHttpRequest : XMLHttpRequestEventTarget { interface XMLHttpRequest : XMLHttpRequestEventTarget {
// event handler // event handler
attribute EventHandler onreadystatechange; attribute EventHandler onreadystatechange;
@ -60,16 +96,17 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget {
readonly attribute unsigned short readyState; readonly attribute unsigned short readyState;
// request // request
void open(ByteString method, /*[EnsureUTF16]*/ DOMString url); void open(ByteString method, USVString url);
void open(ByteString method, /*[EnsureUTF16]*/ DOMString url, boolean async, optional /*[EnsureUTF16]*/ DOMString? username = null, optional /*[EnsureUTF16]*/ DOMString? password = null); void open(ByteString method, USVString url, boolean async, optional USVString? username = null, optional USVString? password = null);
void setRequestHeader(ByteString name, ByteString value); void setRequestHeader(ByteString name, ByteString value);
attribute unsigned long timeout; attribute unsigned long timeout;
attribute boolean withCredentials; attribute boolean withCredentials;
readonly attribute XMLHttpRequestUpload upload; readonly attribute XMLHttpRequestUpload upload;
void send(optional (ArrayBufferView or Blob or Document or /*[EnsureUTF16]*/ DOMString or FormData or URLSearchParams)? data = null); void send(optional (Document or BodyInit)? body = null);
void abort(); void abort();
// response // response
readonly attribute USVString responseURL;
readonly attribute unsigned short status; readonly attribute unsigned short status;
readonly attribute ByteString statusText; readonly attribute ByteString statusText;
ByteString? getResponseHeader(ByteString name); ByteString? getResponseHeader(ByteString name);
@ -77,19 +114,38 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget {
void overrideMimeType(DOMString mime); void overrideMimeType(DOMString mime);
attribute XMLHttpRequestResponseType responseType; attribute XMLHttpRequestResponseType responseType;
readonly attribute any response; readonly attribute any response;
readonly attribute DOMString responseText; readonly attribute USVString responseText;
readonly attribute Document? responseXML; [Exposed=Window] readonly attribute Document? responseXML;
}; };
typedef (File or USVString) FormDataEntryValue;
[Constructor(optional HTMLFormElement form)/*,
Exposed=(Window,Worker)*/]
interface FormData { interface FormData {
void append(/*[EnsureUTF16]*/ DOMString name, Blob value, optional /*[EnsureUTF16]*/ DOMString filename); void append(USVString name, Blob value, optional USVString filename);
void append(/*[EnsureUTF16]*/ DOMString name, /*[EnsureUTF16]*/ DOMString value); void append(USVString name, USVString value);
void delete(/*[EnsureUTF16]*/ DOMString name); void delete(USVString name);
FormDataEntryValue? get(/*[EnsureUTF16]*/ DOMString name); FormDataEntryValue? get(USVString name);
sequence<FormDataEntryValue> getAll(/*[EnsureUTF16]*/ DOMString name); sequence<FormDataEntryValue> getAll(USVString name);
boolean has(/*[EnsureUTF16]*/ DOMString name); boolean has(USVString name);
void set(/*[EnsureUTF16]*/ DOMString name, Blob value, optional /*[EnsureUTF16]*/ DOMString filename); void set(USVString name, Blob value, optional USVString filename);
void set(/*[EnsureUTF16]*/ DOMString name, /*[EnsureUTF16]*/ DOMString value); void set(USVString name, USVString value);
/*iterable<USVString, FormDataEntryValue>;*/
};
[Constructor(DOMString type, optional ProgressEventInit eventInitDict)/*,
Exposed=(Window,Worker)*/]
interface ProgressEvent : Event {
readonly attribute boolean lengthComputable;
readonly attribute unsigned long long loaded;
readonly attribute unsigned long long total;
};
dictionary ProgressEventInit : EventInit {
boolean lengthComputable = false;
unsigned long long loaded = 0;
unsigned long long total = 0;
}; };
</script> </script>
<script> <script>

View File

@ -1,9 +1,10 @@
import imp import imp
import os import os
here = os.path.split(os.path.abspath(__file__))[0]
def main(request, response): def main(request, response):
auth = imp.load_source("", os.path.join(os.path.abspath(os.curdir), auth = imp.load_source("", os.path.join(here,
"XMLHttpRequest", "..",
"resources",
"authentication.py")) "authentication.py"))
return auth.main(request, response) return auth.main(request, response)

View File

@ -1,9 +1,10 @@
import imp import imp
import os import os
here = os.path.split(os.path.abspath(__file__))[0]
def main(request, response): def main(request, response):
auth = imp.load_source("", os.path.join(os.path.abspath(os.curdir), auth = imp.load_source("", os.path.join(here,
"XMLHttpRequest", "..",
"resources",
"authentication.py")) "authentication.py"))
return auth.main(request, response) return auth.main(request, response)

View File

@ -1,9 +1,10 @@
import imp import imp
import os import os
here = os.path.split(os.path.abspath(__file__))[0]
def main(request, response): def main(request, response):
auth = imp.load_source("", os.path.join(os.path.abspath(os.curdir), auth = imp.load_source("", os.path.join(here,
"XMLHttpRequest", "..",
"resources",
"authentication.py")) "authentication.py"))
return auth.main(request, response) return auth.main(request, response)

View File

@ -1,9 +1,10 @@
import imp import imp
import os import os
here = os.path.split(os.path.abspath(__file__))[0]
def main(request, response): def main(request, response):
auth = imp.load_source("", os.path.join(os.path.abspath(os.curdir), auth = imp.load_source("", os.path.join(here,
"XMLHttpRequest", "..",
"resources",
"authentication.py")) "authentication.py"))
return auth.main(request, response) return auth.main(request, response)

View File

@ -0,0 +1,61 @@
<!doctype html>
<meta charset=utf-8>
<title>XMLHttpRequest: passing objects to send()</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol/li[4]" />
<link rel="help" href="https://heycam.github.io/webidl/#es-union" data-tested-assertations="following::ol/li[16]" />
<div id="log"></div>
<script>
function do_test(obj, expected, name) {
var test = async_test(name)
test.step(function() {
var client = new XMLHttpRequest()
client.onload = test.step_func(function () {
assert_equals(client.responseText, expected)
test.done()
});
client.open('POST', 'resources/content.py')
if (expected.exception) {
assert_throws(expected.exception, function(){client.send(obj)})
test.done()
} else {
client.send(obj)
}
});
}
do_test({}, '[object Object]', 'sending a plain empty object')
do_test(Math, '[object Math]', 'sending the ES Math object')
do_test(new XMLHttpRequest, '[object XMLHttpRequest]', 'sending a new XHR instance')
do_test({toString:function(){}}, 'undefined', 'sending object that stringifies to undefined')
do_test({toString:function(){return null}}, 'null', 'sending object that stringifies to null')
var ancestor = {toString: function(){
var ar=[]
for (var prop in this) {
if (this.hasOwnProperty(prop)) {
ar.push(prop+'='+this[prop])
}
};
return ar.join('&')
}};
var myObj = Object.create(ancestor, {foo:{value:1, enumerable: true}, bar:{value:'foo', enumerable:true}})
do_test(myObj, 'foo=1&bar=foo', 'object that stringifies to query string')
var myFakeJSON = {a:'a', b:'b', toString:function(){ return JSON.stringify(this, function(key, val){ return key ==='toString'?undefined:val; }) }}
do_test(myFakeJSON, '{"a":"a","b":"b"}', 'object that stringifies to JSON string')
var myFakeDoc1 = {valueOf:function(){return document}}
do_test(myFakeDoc1, '[object Object]', 'object whose valueOf() returns a document - ignore valueOf(), stringify')
var myFakeDoc2 = {toString:function(){return document}}
do_test(myFakeDoc2, {exception:new TypeError()}, 'object whose toString() returns a document, expected to throw')
var myThrower = {toString:function(){throw {name:'FooError', message:'bar'}}}
do_test(myThrower, {exception:{name:'FooError'}}, 'object whose toString() throws, expected to throw')
</script>

View File

@ -0,0 +1,57 @@
<!doctype html>
<meta charset=utf-8>
<title>XMLHttpRequest: passing objects that interfere with the XHR instance to send()</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol/li[4]" />
<link rel="help" href="https://heycam.github.io/webidl/#es-union" data-tested-assertations="following::ol/li[16]" />
<div id="log"></div>
<script>
var test1 = async_test('abort() called from data stringification')
test1.step(function() {
var client = new XMLHttpRequest()
var objAbortsOnStringification = {toString:function(){
client.abort();
}}
client.open('POST', 'resources/content.py')
assert_throws("InvalidStateError", function(){
client.send(objAbortsOnStringification)
})
test1.done()
});
var test2 = async_test('open() called from data stringification')
test2.step(function() {
var client = new XMLHttpRequest()
var objOpensOnStringification = {toString:function(){
client.open('POST', 'resources/status.py?text=second_open_wins');
}}
client.onloadend = test2.step_func(function(){
assert_equals(client.statusText, 'second_open_wins')
test2.done()
})
client.open('POST', 'resources/status.py?text=first_open_wins')
client.send(objOpensOnStringification)
});
var test3 = async_test('send() called from data stringification')
test3.step(function() {
var client = new XMLHttpRequest()
var objSendsOnStringification = {toString:function(){
client.send('bomb!');
}}
client.onload = test3.step_func(function(){
assert_equals(client.responseText, 'bomb!')
test3.done()
})
client.open('POST', 'resources/content.py')
assert_throws('InvalidStateError', function(){
client.send(objSendsOnStringification)
})
});
</script>

View File

@ -22,7 +22,7 @@ edge-cases like tests that cause the browser to crash or hang.
## By Automating the Browser ## By Automating the Browser
For automated test running designed to be robust enough to use in a CI For automated test running designed to be robust enough to use in a CI
environment, the [wptrunner](http://github.com/wptrunner) test runner environment, the [wptrunner](http://github.com/w3c/wptrunner) test runner
can be used. This is a test runner written in Python and designed to can be used. This is a test runner written in Python and designed to
control the browser from the outside using some remote control control the browser from the outside using some remote control
protocol such as WebDriver. This allows it to handle cases such as the protocol such as WebDriver. This allows it to handle cases such as the

View File

@ -5,7 +5,6 @@
// Everything is done in functions in this test harness, so we have to declare // Everything is done in functions in this test harness, so we have to declare
// all the variables before use to make sure they can be reused. // all the variables before use to make sure they can be reused.
var selection;
var testDiv, paras, detachedDiv, detachedPara1, detachedPara2, var testDiv, paras, detachedDiv, detachedPara1, detachedPara2,
foreignDoc, foreignPara1, foreignPara2, xmlDoc, xmlElement, foreignDoc, foreignPara1, foreignPara2, xmlDoc, xmlElement,
detachedXmlElement, detachedTextNode, foreignTextNode, detachedXmlElement, detachedTextNode, foreignTextNode,
@ -17,7 +16,6 @@ var testDiv, paras, detachedDiv, detachedPara1, detachedPara2,
var testRangesShort, testRanges, testPoints, testNodesShort, testNodes; var testRangesShort, testRanges, testPoints, testNodesShort, testNodes;
function setupRangeTests() { function setupRangeTests() {
selection = getSelection();
testDiv = document.querySelector("#test"); testDiv = document.querySelector("#test");
if (testDiv) { if (testDiv) {
testDiv.parentNode.removeChild(testDiv); testDiv.parentNode.removeChild(testDiv);

View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>EventTarget.addEventListener: capture argument omitted</title>
<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener">
<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id=log></div>
<table id="table" border="1" style="display: none">
<tbody id="table-body">
<tr id="table-row">
<td id="table-cell">Shady Grove</td>
<td>Aeolian</td>
</tr>
<tr id="parent">
<td id="target">Over the river, Charlie</td>
<td>Dorian</td>
</tr>
</tbody>
</table>
<script>
test(function() {
var event_type = "foo";
var target = document.getElementById("target");
var targets = [
target,
document.getElementById("parent"),
document.getElementById("table-body"),
document.getElementById("table"),
document.body,
document.documentElement,
document,
window
];
var phases = [
Event.AT_TARGET,
Event.BUBBLING_PHASE,
Event.BUBBLING_PHASE,
Event.BUBBLING_PHASE,
Event.BUBBLING_PHASE,
Event.BUBBLING_PHASE,
Event.BUBBLING_PHASE,
Event.BUBBLING_PHASE
];
var actual_targets = [], actual_phases = [];
var test_event = function(evt) {
actual_targets.push(evt.currentTarget);
actual_phases.push(evt.eventPhase);
}
for (var i = 0; i < targets.length; i++) {
targets[i].addEventListener(event_type, test_event);
}
var evt = document.createEvent("Event");
evt.initEvent(event_type, true, true);
target.dispatchEvent(evt);
for (var i = 0; i < targets.length; i++) {
targets[i].removeEventListener(event_type, test_event);
}
target.dispatchEvent(evt);
assert_array_equals(actual_targets, targets, "targets");
assert_array_equals(actual_phases, phases, "phases");
}, "EventTarget.addEventListener with the capture argument omitted");
</script>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>EventTarget.dispatchEvent: return value</title>
<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-preventdefault">
<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-defaultprevented">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id=log></div>
<table id="table" border="1" style="display: none">
<tbody id="table-body">
<tr id="table-row">
<td id="table-cell">Shady Grove</td>
<td>Aeolian</td>
</tr>
<tr id="parent">
<td id="target">Over the river, Charlie</td>
<td>Dorian</td>
</tr>
</tbody>
</table>
<script>
test(function() {
var event_type = "foo";
var target = document.getElementById("target");
var parent = document.getElementById("parent");
var default_prevented;
parent.addEventListener(event_type, function(e) {}, true);
target.addEventListener(event_type, function(e) {
evt.preventDefault();
default_prevented = evt.defaultPrevented;
}, true);
target.addEventListener(event_type, function(e) {}, true);
var evt = document.createEvent("Event");
evt.initEvent(event_type, true, true);
assert_true(parent.dispatchEvent(evt));
assert_false(target.dispatchEvent(evt));
assert_true(default_prevented);
}, "Return value of EventTarget.dispatchEvent.");
</script>

View File

@ -360,7 +360,8 @@ interface Attr {
readonly attribute DOMString localName; readonly attribute DOMString localName;
readonly attribute DOMString name; readonly attribute DOMString name;
attribute DOMString value; attribute DOMString value;
attribute DOMString textContent; // alias of .value attribute DOMString nodeValue; // legacy alias of .value
attribute DOMString textContent; // legacy alias of .value
readonly attribute Element? ownerElement; readonly attribute Element? ownerElement;

View File

@ -0,0 +1,77 @@
function test_constructor(ctor) {
test(function() {
var object = new window[ctor]();
assert_equals(Object.getPrototypeOf(object),
window[ctor].prototype, "Prototype chain: " + ctor);
assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(object)),
CharacterData.prototype, "Prototype chain: CharacterData");
assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(object))),
Node.prototype, "Prototype chain: Node");
}, "new " + ctor + "(): prototype chain");
test(function() {
var object = new window[ctor]();
assert_true(object instanceof Node, "Should be a Node");
assert_true(object instanceof CharacterData, "Should be a CharacterData");
assert_true(object instanceof window[ctor], "Should be a " + ctor);
}, "new " + ctor + "(): instanceof");
test(function() {
var object = new window[ctor]();
assert_equals(object.data, "");
assert_equals(object.nodeValue, "");
assert_equals(object.ownerDocument, document);
}, "new " + ctor + "(): no arguments");
var arguments = [
[undefined, ""],
[null, "null"],
[42, "42"],
["", ""],
["-", "-"],
["--", "--"],
["-->", "-->"],
["<!--", "<!--"],
["\u0000", "\u0000"],
["\u0000test", "\u0000test"],
["&amp;", "&amp;"],
];
arguments.forEach(function(a) {
var argument = a[0], expected = a[1];
test(function() {
var object = new window[ctor](argument);
assert_equals(object.data, expected);
assert_equals(object.nodeValue, expected);
assert_equals(object.ownerDocument, document);
}, "new " + ctor + "(): " + format_value(argument));
});
test(function() {
var called = [];
var object = new window[ctor]({
toString: function() {
called.push("first");
return "text";
}
}, {
toString: function() {
called.push("second");
assert_unreached("Should not look at the second argument.");
}
});
assert_equals(object.data, "text");
assert_equals(object.nodeValue, "text");
assert_equals(object.ownerDocument, document);
assert_array_equals(called, ["first"]);
}, "new " + ctor + "(): two arguments")
async_test("new " + ctor + "() should get the correct ownerDocument across globals").step(function() {
var iframe = document.createElement("iframe");
iframe.onload = this.step_func_done(function() {
var object = new iframe.contentWindow[ctor]();
assert_equals(object.ownerDocument, iframe.contentDocument);
});
document.body.appendChild(iframe);
});
}

View File

@ -4,81 +4,8 @@
<link rel=help href="https://dom.spec.whatwg.org/#dom-comment"> <link rel=help href="https://dom.spec.whatwg.org/#dom-comment">
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script src="Comment-Text-constructor.js"></script>
<div id="log"></div> <div id="log"></div>
<script> <script>
test(function() { test_constructor("Comment");
var comment = new Comment();
assert_equals(Object.getPrototypeOf(comment),
Comment.prototype, "Prototype chain: Comment");
assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(comment)),
CharacterData.prototype, "Prototype chain: CharacterData");
assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(comment))),
Node.prototype, "Prototype chain: Node");
}, "new Comment(): prototype chain");
test(function() {
var comment = new Comment();
assert_true(comment instanceof Node, "Should be a Node");
assert_true(comment instanceof CharacterData, "Should be a CharacterData");
assert_true(comment instanceof Comment, "Should be a Comment");
}, "new Comment(): instanceof");
test(function() {
var comment = new Comment();
assert_equals(comment.data, "");
assert_equals(comment.nodeValue, "");
assert_equals(comment.ownerDocument, document);
}, "new Comment(): no arguments");
var arguments = [
[undefined, ""],
[null, "null"],
[42, "42"],
["", ""],
["-", "-"],
["--", "--"],
["-->", "-->"],
["<!--", "<!--"],
["\u0000", "\u0000"],
["\u0000test", "\u0000test"],
["&amp;", "&amp;"],
];
arguments.forEach(function(a) {
var argument = a[0], expected = a[1];
test(function() {
var comment = new Comment(argument);
assert_equals(comment.data, expected);
assert_equals(comment.nodeValue, expected);
assert_equals(comment.ownerDocument, document);
}, "new Comment(): " + format_value(argument));
});
test(function() {
var called = [];
var comment = new Comment({
toString: function() {
called.push("first");
return "text";
}
}, {
toString: function() {
called.push("second");
assert_unreached("Should not look at the second argument.");
}
});
assert_equals(comment.data, "text");
assert_equals(comment.nodeValue, "text");
assert_equals(comment.ownerDocument, document);
assert_array_equals(called, ["first"]);
}, "new Comment(): two arguments")
async_test("new Comment() should get the correct ownerDocument across globals").step(function() {
var iframe = document.createElement("iframe");
iframe.onload = this.step_func_done(function() {
var comment = new iframe.contentWindow.Comment();
assert_equals(comment.ownerDocument, iframe.contentDocument);
});
document.body.appendChild(iframe);
});
</script> </script>

View File

@ -107,6 +107,7 @@ test(function() {
assert_equals(doc.contentType, "application/xml") assert_equals(doc.contentType, "application/xml")
assert_equals(doc.URL, "about:blank") assert_equals(doc.URL, "about:blank")
assert_equals(doc.documentURI, "about:blank") assert_equals(doc.documentURI, "about:blank")
assert_equals(doc.createElement("DIV").localName, "DIV");
}, "createDocument test " + i + ": metadata for " + }, "createDocument test " + i + ": metadata for " +
[namespace, qualifiedName, doctype].map(function(el) { return format_value(el) })) [namespace, qualifiedName, doctype].map(function(el) { return format_value(el) }))
} }

View File

@ -10,48 +10,58 @@
<link rel=help href="https://dom.spec.whatwg.org/#dom-document-documentelement"> <link rel=help href="https://dom.spec.whatwg.org/#dom-document-documentelement">
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script src="DOMImplementation-createHTMLDocument.js"></script>
<div id="log"></div> <div id="log"></div>
<script> <script>
function checkDoc(title, expectedtitle, normalizedtitle) { createHTMLDocuments(function(doc, expectedtitle, normalizedtitle) {
test(function() { assert_true(doc instanceof Document, "Should be a Document")
var doc = document.implementation.createHTMLDocument(title); assert_true(doc instanceof Node, "Should be a Node")
assert_equals(doc.doctype.name, "html") assert_equals(doc.childNodes.length, 2,
assert_equals(doc.doctype.publicId, "") "Document should have two child nodes")
assert_equals(doc.doctype.systemId, "")
assert_equals(doc.documentElement.localName, "html")
assert_equals(doc.documentElement.firstChild.localName, "head")
if (title !== undefined) {
assert_equals(doc.documentElement.firstChild.childNodes.length, 1)
assert_equals(doc.documentElement.firstChild.firstChild.localName, "title")
assert_equals(doc.documentElement.firstChild.firstChild.firstChild.data,
expectedtitle)
} else {
assert_equals(doc.documentElement.firstChild.childNodes.length, 0)
}
assert_equals(doc.documentElement.lastChild.localName, "body")
assert_equals(doc.documentElement.lastChild.childNodes.length, 0)
})
}
checkDoc("", "", "")
checkDoc(null, "null", "null")
checkDoc(undefined, "", "")
checkDoc("foo bar baz", "foo bar baz", "foo bar baz")
checkDoc("foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz")
checkDoc("foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz")
checkDoc("foo\f\fbar baz", "foo\f\fbar baz", "foo bar baz")
checkDoc("foo\r\rbar baz", "foo\r\rbar baz", "foo bar baz")
test(function() { var doctype = doc.doctype
var doc = document.implementation.createHTMLDocument(); assert_true(doctype instanceof DocumentType,
assert_equals(doc.doctype.name, "html") "Doctype should be a DocumentType")
assert_equals(doc.doctype.publicId, "") assert_true(doctype instanceof Node, "Doctype should be a Node")
assert_equals(doc.doctype.systemId, "") assert_equals(doctype.name, "html")
assert_equals(doc.documentElement.localName, "html") assert_equals(doctype.publicId, "")
assert_equals(doc.documentElement.firstChild.localName, "head") assert_equals(doctype.systemId, "")
assert_equals(doc.documentElement.firstChild.childNodes.length, 0)
assert_equals(doc.documentElement.lastChild.localName, "body") var documentElement = doc.documentElement
assert_equals(doc.documentElement.lastChild.childNodes.length, 0) assert_true(documentElement instanceof HTMLHtmlElement,
}, "Missing title argument"); "Document element should be a HTMLHtmlElement")
assert_equals(documentElement.childNodes.length, 2,
"Document element should have two child nodes")
assert_equals(documentElement.localName, "html")
assert_equals(documentElement.tagName, "HTML")
var head = documentElement.firstChild
assert_true(head instanceof HTMLHeadElement,
"Head should be a HTMLHeadElement")
assert_equals(head.localName, "head")
assert_equals(head.tagName, "HEAD")
if (expectedtitle !== undefined) {
assert_equals(head.childNodes.length, 1)
var title = head.firstChild
assert_true(title instanceof HTMLTitleElement,
"Title should be a HTMLTitleElement")
assert_equals(title.localName, "title")
assert_equals(title.tagName, "TITLE")
assert_equals(title.childNodes.length, 1)
assert_equals(title.firstChild.data, expectedtitle)
} else {
assert_equals(head.childNodes.length, 0)
}
var body = documentElement.lastChild
assert_true(body instanceof HTMLBodyElement,
"Body should be a HTMLBodyElement")
assert_equals(body.localName, "body")
assert_equals(body.tagName, "BODY")
assert_equals(body.childNodes.length, 0)
})
test(function() { test(function() {
var doc = document.implementation.createHTMLDocument("test"); var doc = document.implementation.createHTMLDocument("test");

View File

@ -0,0 +1,25 @@
function createHTMLDocuments(checkDoc) {
var tests = [
["", "", ""],
[null, "null", "null"],
[undefined, undefined, ""],
["foo bar baz", "foo bar baz", "foo bar baz"],
["foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz"],
["foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz"],
["foo\f\fbar baz", "foo\f\fbar baz", "foo bar baz"],
["foo\r\rbar baz", "foo\r\rbar baz", "foo bar baz"],
]
tests.forEach(function(t, i) {
var title = t[0], expectedtitle = t[1], normalizedtitle = t[2]
test(function() {
var doc = document.implementation.createHTMLDocument(title);
checkDoc(doc, expectedtitle, normalizedtitle)
}, "createHTMLDocument test " + i + ": " + t.map(function(el) { return format_value(el) }))
})
test(function() {
var doc = document.implementation.createHTMLDocument();
checkDoc(doc, undefined, "")
}, "Missing title argument");
}

View File

@ -15,11 +15,11 @@ invalid_names.forEach(function(name) {
}, "createAttribute(" + format_value(name) + ")"); }, "createAttribute(" + format_value(name) + ")");
}); });
var tests = ["title", "TITLE"]; var tests = ["title", "TITLE", null, undefined];
tests.forEach(function(name) { tests.forEach(function(name) {
test(function() { test(function() {
var attribute = document.createAttribute(name); var attribute = document.createAttribute(name);
attr_is(attribute, "", name, null, null, name); attr_is(attribute, "", String(name), null, null, String(name));
assert_equals(attribute.ownerElement, null); assert_equals(attribute.ownerElement, null);
}, "createAttribute(" + format_value(name) + ")"); }, "createAttribute(" + format_value(name) + ")");
}); });

View File

@ -0,0 +1,22 @@
function test_create(method, iface, nodeType, nodeName) {
["\u000b", "a -- b", "a-", "-b", null, undefined].forEach(function(value) {
test(function() {
var c = document[method](value);
var expected = String(value);
assert_true(c instanceof iface);
assert_true(c instanceof CharacterData);
assert_true(c instanceof Node);
assert_equals(c.ownerDocument, document);
assert_equals(c.data, expected, "data");
assert_equals(c.nodeValue, expected, "nodeValue");
assert_equals(c.textContent, expected, "textContent");
assert_equals(c.length, expected.length);
assert_equals(c.nodeType, nodeType);
assert_equals(c.nodeName, nodeName);
assert_equals(c.hasChildNodes(), false);
assert_equals(c.childNodes.length, 0);
assert_equals(c.firstChild, null);
assert_equals(c.lastChild, null);
}, method + "(" + format_value(value) + ")");
});
}

View File

@ -14,27 +14,8 @@
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-lastchild"> <link rel=help href="https://dom.spec.whatwg.org/#dom-node-lastchild">
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script src="Document-createComment-createTextNode.js"></script>
<div id="log"></div> <div id="log"></div>
<script> <script>
test(function() { test_create("createComment", Comment, 8, "#comment");
["\u000b", "a -- b", "a-", "-b", null, undefined].forEach(function(value) {
test(function() {
var c = document.createComment(value);
var expected = String(value);
assert_true(c instanceof Comment);
assert_true(c instanceof Node);
assert_equals(c.ownerDocument, document);
assert_equals(c.data, expected, "data");
assert_equals(c.nodeValue, expected, "nodeValue");
assert_equals(c.textContent, expected, "textContent");
assert_equals(c.length, expected.length);
assert_equals(c.nodeType, 8);
assert_equals(c.nodeName, "#comment");
assert_equals(c.hasChildNodes(), false);
assert_equals(c.childNodes.length, 0);
assert_equals(c.firstChild, null);
assert_equals(c.lastChild, null);
}, "createComment(" + format_value(value) + ")");
});
});
</script> </script>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Document.createTextNode</title>
<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createtextnode">
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument">
<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodevalue">
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-textcontent">
<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-length">
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodetype">
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-haschildnodes">
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-childnodes">
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-firstchild">
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-lastchild">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="Document-createComment-createTextNode.js"></script>
<div id="log"></div>
<script>
test_create("createTextNode", Text, 3, "#text");
</script>

View File

@ -289,9 +289,9 @@
}, "where insertion order and tree order don't match"); }, "where insertion order and tree order don't match");
test(function() { test(function() {
let TEST_ID = "test14"; var TEST_ID = "test14";
let a = document.createElement("a"); var a = document.createElement("a");
let b = document.createElement("b"); var b = document.createElement("b");
a.appendChild(b); a.appendChild(b);
b.id = TEST_ID; b.id = TEST_ID;
assert_equals(document.getElementById(TEST_ID), null); assert_equals(document.getElementById(TEST_ID), null);

View File

@ -0,0 +1,11 @@
<!doctype html>
<meta charset=utf-8>
<title>Text constructor</title>
<link rel=help href="https://dom.spec.whatwg.org/#dom-text">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="Comment-Text-constructor.js"></script>
<div id="log"></div>
<script>
test_constructor("Text");
</script>

View File

@ -1,5 +1,6 @@
function attr_is(attr, v, ln, ns, p, n) { function attr_is(attr, v, ln, ns, p, n) {
assert_equals(attr.value, v) assert_equals(attr.value, v)
assert_equals(attr.nodeValue, v)
assert_equals(attr.textContent, v) assert_equals(attr.textContent, v)
assert_equals(attr.localName, ln) assert_equals(attr.localName, ln)
assert_equals(attr.namespaceURI, ns) assert_equals(attr.namespaceURI, ns)

View File

@ -0,0 +1,21 @@
<!doctype html>
<meta charset=gb18030> <!-- if the server overrides this, it is stupid, as this is a testsuite -->
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<div id=log></div>
<script>
function encode(input, output, desc) {
test(function() {
var a = document.createElement("a") // <a> uses document encoding for URL's query
a.href = "https://example.com/?" + input
assert_equals(a.search.substr(1), output) // remove leading "?"
}, "gb18030 encoder: " + desc)
}
encode("s", "s", "very basic")
encode("\u20AC", "%A2%E3", "Euro")
encode("\u4E02", "%81@", "character")
encode("\uE4C6", "%A1@", "PUA")
encode("\uE4C5", "%FE%FE", "PUA #2")
encode("\ud83d\udca9", "%949%DA3", "poo")
</script>

View File

@ -0,0 +1,21 @@
<!doctype html>
<meta charset=gbk> <!-- if the server overrides this, it is stupid, as this is a testsuite -->
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<div id=log></div>
<script>
function encode(input, output, desc) {
test(function() {
var a = document.createElement("a") // <a> uses document encoding for URL's query
a.href = "https://example.com/?" + input
assert_equals(a.search.substr(1), output) // remove leading "?"
}, "gbk encoder: " + desc)
}
encode("s", "s", "very basic")
encode("\u20AC", "%80", "Euro")
encode("\u4E02", "%81@", "character")
encode("\uE4C6", "%A1@", "PUA")
encode("\uE4C5", "%FE%FE", "PUA #2")
encode("\ud83d\udca9", "%26%23128169%3B", "poo")
</script>

View File

@ -0,0 +1,57 @@
<!doctype html>
<meta charset=utf-8>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<div id=log></div>
<script>
function decode(input, output, desc) {
test(function() {
var d = new TextDecoder("iso-2022-jp"),
buffer = new ArrayBuffer(input.length),
view = new Int8Array(buffer)
for(var i = 0, l = input.length; i < l; i++) {
view[i] = input[i]
}
assert_equals(d.decode(view), output)
}, "iso-2022-jp decoder: " + desc)
}
decode([0x1b, 0x24], "<22>$", "Error ESC")
decode([0x1b, 0x24, 0x50], "<22>$P", "Error ESC, character")
decode([0x1b, 0x28, 0x42, 0x50], "<22>P", "ASCII ESC, character")
decode([0x1b, 0x28, 0x42, 0x1b, 0x28, 0x42, 0x50], "<22><>P", "Double ASCII ESC, character")
decode([0x50, 0x1b, 0x28, 0x42, 0x50], "PP", "character, ASCII ESC, character")
decode([0x5C, 0x5D, 0x7E], "\\]~", "characters")
decode([0x0D, 0x0E, 0x0F, 0x10], "\x0D<30><44>\x10", "SO / SI")
decode([0x1b, 0x28, 0x4A, 0x5C, 0x5D, 0x7E], "¥]‾", "Roman ESC, characters")
decode([0x1b, 0x28, 0x4A, 0x0D, 0x0E, 0x0F, 0x10], "\x0D<30><44>\x10", "Roman ESC, SO / SI")
decode([0x1b, 0x28, 0x4A, 0x1b, 0x1b, 0x28, 0x49, 0x50], "<22>ミ", "Roman ESC, error ESC, Katakana ESC")
decode([0x1b, 0x28, 0x49, 0x50], "ミ", "Katakana ESC, character")
decode([0x1b, 0x28, 0x49, 0x1b, 0x24, 0x40, 0x50, 0x50], "<22>佩", "Katakana ESC, multibyte ESC, character")
decode([0x1b, 0x28, 0x49, 0x1b, 0x50], "<22>ミ", "Katakana ESC, error ESC, character")
decode([0x1b, 0x28, 0x49, 0x1b, 0x24, 0x50], "<22>、ミ", "Katakana ESC, error ESC #2, character")
decode([0x1b, 0x28, 0x49, 0x50, 0x1b, 0x28, 0x49, 0x50], "ミミ", "Katakana ESC, character, Katakana ESC, character")
decode([0x1b, 0x28, 0x49, 0x0D, 0x0E, 0x0F, 0x10], "<22><><EFBFBD><EFBFBD>", "Katakana ESC, SO / SI")
decode([0x1b, 0x24, 0x40, 0x50, 0x50], "佩", "Multibyte ESC, character")
decode([0x1b, 0x24, 0x42, 0x50, 0x50], "佩", "Multibyte ESC #2, character")
decode([0x1b, 0x24, 0x42, 0x1b, 0x50, 0x50], "<22>佩", "Multibyte ESC, error ESC, character")
decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x40], "<22>", "Double multibyte ESC")
decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x40, 0x50, 0x50], "<22>佩", "Double multibyte ESC, character")
decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x42, 0x50, 0x50], "<22>佩", "Double multibyte ESC #2, character")
decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x50, 0x50], "<22><EFBFBD>", "Multibyte ESC, error ESC #2, character")
decode([0x1b, 0x24, 0x40, 0x50, 0x1b, 0x24, 0x40, 0x50, 0x50], "<22>佩", "Multibyte ESC, single byte, multibyte ESC, character")
decode([0x1b, 0x24, 0x40, 0x20, 0x50], "<22><>", "Multibyte ESC, lead error byte")
decode([0x1b, 0x24, 0x40, 0x50, 0x20], "<22>", "Multibyte ESC, trail error byte")
decode([0x50, 0x1b], "P<>", "character, error ESC")
decode([0x50, 0x1b, 0x24], "P<>$", "character, error ESC #2")
decode([0x50, 0x1b, 0x50], "P<>P", "character, error ESC #3")
decode([0x50, 0x1b, 0x28, 0x42], "P", "character, ASCII ESC")
decode([0x50, 0x1b, 0x28, 0x4A], "P", "character, Roman ESC")
decode([0x50, 0x1b, 0x28, 0x49], "P", "character, Katakana ESC")
decode([0x50, 0x1b, 0x24, 0x40], "P", "character, Multibyte ESC")
decode([0x50, 0x1b, 0x24, 0x42], "P", "character, Multibyte ESC #2")
</script>

View File

@ -0,0 +1,18 @@
<!doctype html>
<meta charset=iso-2022-jp> <!-- if the server overrides this, it is stupid, as this is a testsuite -->
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<div id=log></div>
<script>
function encode(input, output, desc) {
test(function() {
var a = document.createElement("a") // <a> uses document encoding for URL's query
a.href = "https://example.com/?" + input
assert_equals(a.search.substr(1), output) // remove leading "?"
}, "iso-2022-jp encoder: " + desc)
}
encode("s", "s", "very basic")
encode("\u00A5\u203Es\\\uFF90\u4F69", "%1B(J\\~s%1B(B\\%1B$B%_PP%1B(B", "basics")
encode("\x0E\x0F\x1Bx", "%0E%0F%1Bx", "SO/SI ESC")
</script>

View File

@ -0,0 +1,3 @@
def main(request, response):
response.headers.set("Content-Type", "text/plain;charset=" + request.GET.first("label"))
response.content = "".join(chr(byte) for byte in xrange(255))

View File

@ -0,0 +1,176 @@
<!doctype html>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<div id=log></div>
<script>
// https://encoding.spec.whatwg.org/encodings.json
var singleByteEncodings = [{
"labels": [ "866", "cp866", "csibm866", "ibm866" ],
"name": "ibm866"
},{
"labels": [ "csisolatin2", "iso-8859-2", "iso-ir-101", "iso8859-2", "iso88592", "iso_8859-2", "iso_8859-2:1987", "l2", "latin2" ],
"name": "iso-8859-2"
},{
"labels": [ "csisolatin3", "iso-8859-3", "iso-ir-109", "iso8859-3", "iso88593", "iso_8859-3", "iso_8859-3:1988", "l3", "latin3" ],
"name": "iso-8859-3"
},{
"labels": [ "csisolatin4", "iso-8859-4", "iso-ir-110", "iso8859-4", "iso88594", "iso_8859-4", "iso_8859-4:1988", "l4", "latin4" ],
"name": "iso-8859-4"
},{
"labels": [ "csisolatincyrillic", "cyrillic", "iso-8859-5", "iso-ir-144", "iso8859-5", "iso88595", "iso_8859-5", "iso_8859-5:1988" ],
"name": "iso-8859-5"
},{
"labels": [ "arabic", "asmo-708", "csiso88596e", "csiso88596i", "csisolatinarabic", "ecma-114", "iso-8859-6", "iso-8859-6-e", "iso-8859-6-i", "iso-ir-127", "iso8859-6", "iso88596", "iso_8859-6", "iso_8859-6:1987" ],
"name": "iso-8859-6"
},{
"labels": [ "csisolatingreek", "ecma-118", "elot_928", "greek", "greek8", "iso-8859-7", "iso-ir-126", "iso8859-7", "iso88597", "iso_8859-7", "iso_8859-7:1987", "sun_eu_greek" ],
"name": "iso-8859-7"
},{
"labels": [ "csiso88598e", "csisolatinhebrew", "hebrew", "iso-8859-8", "iso-8859-8-e", "iso-ir-138", "iso8859-8", "iso88598", "iso_8859-8", "iso_8859-8:1988", "visual" ],
"name": "iso-8859-8"
},{
"labels": [ "csiso88598i", "iso-8859-8-i", "logical" ],
"name": "iso-8859-8-i"
},{
"labels": [ "csisolatin6", "iso-8859-10", "iso-ir-157", "iso8859-10", "iso885910", "l6", "latin6" ],
"name": "iso-8859-10"
},{
"labels": [ "iso-8859-13", "iso8859-13", "iso885913" ],
"name": "iso-8859-13"
},{
"labels": [ "iso-8859-14", "iso8859-14", "iso885914" ],
"name": "iso-8859-14"
},{
"labels": [ "csisolatin9", "iso-8859-15", "iso8859-15", "iso885915", "iso_8859-15", "l9" ],
"name": "iso-8859-15"
},{
"labels": [ "iso-8859-16" ],
"name": "iso-8859-16"
},{
"labels": [ "cskoi8r", "koi", "koi8", "koi8-r", "koi8_r" ],
"name": "koi8-r"
},{
"labels": [ "koi8-u" ],
"name": "koi8-u"
},{
"labels": [ "csmacintosh", "mac", "macintosh", "x-mac-roman" ],
"name": "macintosh"
},{
"labels": [ "dos-874", "iso-8859-11", "iso8859-11", "iso885911", "tis-620", "windows-874" ],
"name": "windows-874"
},{
"labels": [ "cp1250", "windows-1250", "x-cp1250" ],
"name": "windows-1250"
},{
"labels": [ "cp1251", "windows-1251", "x-cp1251" ],
"name": "windows-1251"
},{
"labels": [ "ansi_x3.4-1968", "ascii", "cp1252", "cp819", "csisolatin1", "ibm819", "iso-8859-1", "iso-ir-100", "iso8859-1", "iso88591", "iso_8859-1", "iso_8859-1:1987", "l1", "latin1", "us-ascii", "windows-1252", "x-cp1252" ],
"name": "windows-1252"
},{
"labels": [ "cp1253", "windows-1253", "x-cp1253" ],
"name": "windows-1253"
},{
"labels": [ "cp1254", "csisolatin5", "iso-8859-9", "iso-ir-148", "iso8859-9", "iso88599", "iso_8859-9", "iso_8859-9:1989", "l5", "latin5", "windows-1254", "x-cp1254" ],
"name": "windows-1254"
},{
"labels": [ "cp1255", "windows-1255", "x-cp1255" ],
"name": "windows-1255"
},{
"labels": [ "cp1256", "windows-1256", "x-cp1256" ],
"name": "windows-1256"
},{
"labels": [ "cp1257", "windows-1257", "x-cp1257" ],
"name": "windows-1257"
},{
"labels": [ "cp1258", "windows-1258", "x-cp1258" ],
"name": "windows-1258"
},{
"labels": [ "x-mac-cyrillic", "x-mac-ukrainian" ],
"name": "x-mac-cyrillic"
}],
// https://encoding.spec.whatwg.org/indexes.json
singleByteIndexes = {
"ibm866":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1025,1105,1028,1108,1031,1111,1038,1118,176,8729,183,8730,8470,164,9632,160],
"iso-8859-2":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,728,321,164,317,346,167,168,352,350,356,377,173,381,379,176,261,731,322,180,318,347,711,184,353,351,357,378,733,382,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729],
"iso-8859-3":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,294,728,163,164,null,292,167,168,304,350,286,308,173,null,379,176,295,178,179,180,181,293,183,184,305,351,287,309,189,null,380,192,193,194,null,196,266,264,199,200,201,202,203,204,205,206,207,null,209,210,211,212,288,214,215,284,217,218,219,220,364,348,223,224,225,226,null,228,267,265,231,232,233,234,235,236,237,238,239,null,241,242,243,244,289,246,247,285,249,250,251,252,365,349,729],
"iso-8859-4":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,312,342,164,296,315,167,168,352,274,290,358,173,381,175,176,261,731,343,180,297,316,711,184,353,275,291,359,330,382,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,298,272,325,332,310,212,213,214,215,216,370,218,219,220,360,362,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,299,273,326,333,311,244,245,246,247,248,371,250,251,252,361,363,729],
"iso-8859-5":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,173,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8470,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,167,1118,1119],
"iso-8859-6":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,null,null,164,null,null,null,null,null,null,null,1548,173,null,null,null,null,null,null,null,null,null,null,null,null,null,1563,null,null,null,1567,null,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,null,null,null,null,null,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,null,null,null,null,null,null,null,null,null,null,null,null,null],
"iso-8859-7":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8216,8217,163,8364,8367,166,167,168,169,890,171,172,173,null,8213,176,177,178,179,900,901,902,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null],
"iso-8859-8":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null],
"iso-8859-10":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,274,290,298,296,310,167,315,272,352,358,381,173,362,330,176,261,275,291,299,297,311,183,316,273,353,359,382,8213,363,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,207,208,325,332,211,212,213,214,360,216,370,218,219,220,221,222,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,239,240,326,333,243,244,245,246,361,248,371,250,251,252,253,254,312],
"iso-8859-13":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8221,162,163,164,8222,166,167,216,169,342,171,172,173,174,198,176,177,178,179,8220,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,8217],
"iso-8859-14":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,7682,7683,163,266,267,7690,167,7808,169,7810,7691,7922,173,174,376,7710,7711,288,289,7744,7745,182,7766,7809,7767,7811,7776,7923,7812,7813,7777,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,372,209,210,211,212,213,214,7786,216,217,218,219,220,221,374,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,373,241,242,243,244,245,246,7787,248,249,250,251,252,253,375,255],
"iso-8859-15":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,8364,165,352,167,353,169,170,171,172,173,174,175,176,177,178,179,381,181,182,183,382,185,186,187,338,339,376,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255],
"iso-8859-16":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,261,321,8364,8222,352,167,353,169,536,171,377,173,378,379,176,177,268,322,381,8221,182,183,382,269,537,187,338,339,376,380,192,193,194,258,196,262,198,199,200,201,202,203,204,205,206,207,272,323,210,211,212,336,214,346,368,217,218,219,220,280,538,223,224,225,226,259,228,263,230,231,232,233,234,235,236,237,238,239,273,324,242,243,244,337,246,347,369,249,250,251,252,281,539,255],
"koi8-r":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,1025,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066],
"koi8-u":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,1108,9556,1110,1111,9559,9560,9561,9562,9563,1169,9565,9566,9567,9568,9569,1025,1028,9571,1030,1031,9574,9575,9576,9577,9578,1168,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066],
"macintosh":[196,197,199,201,209,214,220,225,224,226,228,227,229,231,233,232,234,235,237,236,238,239,241,243,242,244,246,245,250,249,251,252,8224,176,162,163,167,8226,182,223,174,169,8482,180,168,8800,198,216,8734,177,8804,8805,165,181,8706,8721,8719,960,8747,170,186,937,230,248,191,161,172,8730,402,8776,8710,171,187,8230,160,192,195,213,338,339,8211,8212,8220,8221,8216,8217,247,9674,255,376,8260,8364,8249,8250,64257,64258,8225,183,8218,8222,8240,194,202,193,203,200,205,206,207,204,211,212,63743,210,218,219,217,305,710,732,175,728,729,730,184,733,731,711],
"windows-874":[8364,129,130,131,132,8230,134,135,136,137,138,139,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,153,154,155,156,157,158,159,160,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,null,null,null,null,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,null,null,null,null],
"windows-1250":[8364,129,8218,131,8222,8230,8224,8225,136,8240,352,8249,346,356,381,377,144,8216,8217,8220,8221,8226,8211,8212,152,8482,353,8250,347,357,382,378,160,711,728,321,164,260,166,167,168,169,350,171,172,173,174,379,176,177,731,322,180,181,182,183,184,261,351,187,317,733,318,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729],
"windows-1251":[1026,1027,8218,1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039,1106,8216,8217,8220,8221,8226,8211,8212,152,8482,1113,8250,1114,1116,1115,1119,160,1038,1118,1032,164,1168,166,167,1025,169,1028,171,172,173,174,1031,176,177,1030,1110,1169,181,182,183,1105,8470,1108,187,1112,1029,1109,1111,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103],
"windows-1252":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,381,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,382,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255],
"windows-1253":[8364,129,8218,402,8222,8230,8224,8225,136,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,157,158,159,160,901,902,163,164,165,166,167,168,169,null,171,172,173,174,8213,176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null],
"windows-1254":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,286,209,210,211,212,213,214,215,216,217,218,219,220,304,350,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,287,241,242,243,244,245,246,247,248,249,250,251,252,305,351,255],
"windows-1255":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,156,157,158,159,160,161,162,163,8362,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,191,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,null,1467,1468,1469,1470,1471,1472,1473,1474,1475,1520,1521,1522,1523,1524,null,null,null,null,null,null,null,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null],
"windows-1256":[8364,1662,8218,402,8222,8230,8224,8225,710,8240,1657,8249,338,1670,1688,1672,1711,8216,8217,8220,8221,8226,8211,8212,1705,8482,1681,8250,339,8204,8205,1722,160,1548,162,163,164,165,166,167,168,169,1726,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,1563,187,188,189,190,1567,1729,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,215,1591,1592,1593,1594,1600,1601,1602,1603,224,1604,226,1605,1606,1607,1608,231,232,233,234,235,1609,1610,238,239,1611,1612,1613,1614,244,1615,1616,247,1617,249,1618,251,252,8206,8207,1746],
"windows-1257":[8364,129,8218,131,8222,8230,8224,8225,136,8240,138,8249,140,168,711,184,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,175,731,159,160,null,162,163,164,null,166,167,216,169,342,171,172,173,174,198,176,177,178,179,180,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,729],
"windows-1258":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,258,196,197,198,199,200,201,202,203,768,205,206,207,272,209,777,211,212,416,214,215,216,217,218,219,220,431,771,223,224,225,226,259,228,229,230,231,232,233,234,235,769,237,238,239,273,241,803,243,244,417,246,247,248,249,250,251,252,432,8363,255],
"x-mac-cyrillic":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,8224,176,1168,163,167,8226,182,1030,174,169,8482,1026,1106,8800,1027,1107,8734,177,8804,8805,1110,181,1169,1032,1028,1108,1031,1111,1033,1113,1034,1114,1112,1029,172,8730,402,8776,8710,171,187,8230,160,1035,1115,1036,1116,1109,8211,8212,8220,8221,8216,8217,247,8222,1038,1118,1039,1119,8470,1025,1105,1103,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,8364]
}
// For TextDecoder tests
var buffer = ArrayBuffer(255),
view = Uint8Array(buffer)
for(var i = 0, l = view.byteLength; i < l; i++) {
view[i] = i
}
// For XMLHttpRequest and TextDecoder tests
function assert_decode(data, encoding) {
if(encoding == "iso-8859-8-i") {
encoding = "iso-8859-8"
}
for(var i = 0, l = data.length; i < l; i++) {
var cp = data.charCodeAt(i),
expectedCp = (i < 0x80) ? i : singleByteIndexes[encoding][i-0x80]
if(expectedCp == null) {
expectedCp = 0xFFFD
}
assert_equals(cp, expectedCp, encoding + ":" + i)
}
}
// Setting up all the tests
for(var i = 0, l = singleByteEncodings.length; i < l; i++) {
var encoding = singleByteEncodings[i]
for(var ii = 0, ll = encoding.labels.length; ii < ll; ii++) {
var label = encoding.labels[ii]
async_test(function(t) {
var xhr = new XMLHttpRequest,
name = encoding.name // need scoped variable
xhr.open("GET", "resources/single-byte-raw.py?label=" + label)
xhr.send(null)
xhr.onload = t.step_func_done(function() { assert_decode(xhr.responseText, name) })
}, encoding.name + ": " + label + " (XMLHttpRequest)")
test(function() {
var d = new TextDecoder(label),
data = d.decode(view)
assert_equals(d.encoding, encoding.name)
assert_decode(data, encoding.name)
}, encoding.name + ": " + label + " (TextDecoder)")
async_test(function(t) {
var frame = document.createElement("iframe"),
name = encoding.name
frame.src = "resources/single-byte-raw.py?label=" + label
frame.onload = t.step_func_done(function() { assert_equals(frame.contentDocument.characterSet, name) })
t.add_cleanup(function() { document.body.removeChild(frame) })
document.body.appendChild(frame)
}, encoding.name + ": " + label + " (document.characterSet)")
}
}
</script>

View File

@ -2,25 +2,10 @@
<title>Document.title and DOMImplementation.createHTMLDocument</title> <title>Document.title and DOMImplementation.createHTMLDocument</title>
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script src="/dom/nodes/DOMImplementation-createHTMLDocument.js"></script>
<div id="log"></div> <div id="log"></div>
<script> <script>
function checkDoc(title, expectedtitle, normalizedtitle) { createHTMLDocuments(function(doc, expectedtitle, normalizedtitle) {
test(function() { assert_equals(doc.title, normalizedtitle)
var doc = document.implementation.createHTMLDocument(title); })
assert_equals(doc.title, normalizedtitle)
})
}
checkDoc("", "", "")
checkDoc(null, "null", "null")
checkDoc(undefined, "", "")
checkDoc("foo bar baz", "foo bar baz", "foo bar baz")
checkDoc("foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz")
checkDoc("foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz")
checkDoc("foo\f\fbar baz", "foo\f\fbar baz", "foo bar baz")
checkDoc("foo\r\rbar baz", "foo\r\rbar baz", "foo bar baz")
test(function() {
var doc = document.implementation.createHTMLDocument()
assert_equals(doc.title, "")
}, "Missing title argument");
</script> </script>

View File

@ -9,12 +9,12 @@
onload = function() { onload = function() {
var ifr = document.getElementsByTagName('iframe')[0]; var ifr = document.getElementsByTagName('iframe')[0];
ifr.contentDocument.body.appendChild(ifr.contentDocument.createElement('p')).textContent = 'Modified document'; ifr.contentDocument.body.appendChild(ifr.contentDocument.createElement('p')).textContent = 'Modified document';
setTimeout(function () { setTimeout(function() {
document.getElementById('target').appendChild(ifr); ifr.onload = function() {
setTimeout(function() {
assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1); assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1);
done(); done();
}, 100); };
document.getElementById('target').appendChild(ifr);
}, 100); }, 100);
} }
</script> </script>

View File

@ -12,11 +12,11 @@ onload = function() {
ifr.contentDocument.write('Modified document'); ifr.contentDocument.write('Modified document');
ifr.contentDocument.close(); ifr.contentDocument.close();
setTimeout(function() { setTimeout(function() {
document.getElementById('target').appendChild(ifr); ifr.onload = function() {
setTimeout(function() {
assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1); assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1);
done(); done();
}, 100); };
document.getElementById('target').appendChild(ifr);
}, 100); }, 100);
} }
</script> </script>

View File

@ -10,11 +10,11 @@ onload = function() {
var ifr = document.getElementsByTagName('iframe')[0]; var ifr = document.getElementsByTagName('iframe')[0];
ifr.contentDocument.body.appendChild(ifr.contentDocument.createElement('p')).textContent = 'Modified document'; ifr.contentDocument.body.appendChild(ifr.contentDocument.createElement('p')).textContent = 'Modified document';
setTimeout(function() { setTimeout(function() {
document.getElementById('target').appendChild(ifr); ifr.onload = function() {
setTimeout(function() {
assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1); assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1);
done(); done();
}, 100); };
document.getElementById('target').appendChild(ifr);
}, 100); }, 100);
} }
</script> </script>

View File

@ -11,12 +11,12 @@ onload = function(){
ifr.contentDocument.open(); ifr.contentDocument.open();
ifr.contentDocument.write('Modified document'); ifr.contentDocument.write('Modified document');
ifr.contentDocument.close(); ifr.contentDocument.close();
setTimeout(function () { setTimeout(function() {
document.getElementById('target').appendChild(ifr); ifr.onload = function () {
setTimeout(function () {
assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1); assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1);
done(); done();
}, 100); };
document.getElementById('target').appendChild(ifr);
}, 100); }, 100);
} }
</script> </script>

View File

@ -10,7 +10,6 @@
<div id="log"></div> <div id="log"></div>
<script> <script>
var video = document.createElement('video');
var contents = {'/media/white.webm': 'video/webm; codecs="vorbis,vp8"', var contents = {'/media/white.webm': 'video/webm; codecs="vorbis,vp8"',
'/media/white.mp4' : 'video/mp4'}; '/media/white.mp4' : 'video/mp4'};
@ -49,13 +48,15 @@ function mediaTest(file, mime) {
mediaSource.addEventListener('sourceopen', function(e) { mediaSource.addEventListener('sourceopen', function(e) {
sourceBuffer = mediaSource.addSourceBuffer(mime); sourceBuffer = mediaSource.addSourceBuffer(mime);
mediaSource.endOfStream(); mediaSource.endOfStream();
assert_equals(mediaSource.readyState, 'ended',
'mediaSource.readyState is "ended" after endOfStream()');
}); });
mediaSource.addEventListener('sourceclose', function(e) { mediaSource.addEventListener('sourceended', t.step_func_done(function(e) {
assert_throws({name: 'InvalidStateError'}, function() { assert_throws({name: 'InvalidStateError'}, function() {
sourceBuffer.abort(); sourceBuffer.abort();
}); });
t.done(); }));
}); var video = document.createElement('video');
video.src = window.URL.createObjectURL(mediaSource); video.src = window.URL.createObjectURL(mediaSource);
}); });
}, 'SourceBuffer#abort() (' + mime + ') : If the readyState attribute ' + }, 'SourceBuffer#abort() (' + mime + ') : If the readyState attribute ' +

View File

@ -10,7 +10,6 @@
<div id="log"></div> <div id="log"></div>
<script> <script>
var video = document.createElement('video');
var mimes = ['video/webm; codecs="vorbis,vp8"', 'video/mp4']; var mimes = ['video/webm; codecs="vorbis,vp8"', 'video/mp4'];
//check the browser supports the MIME used in this test //check the browser supports the MIME used in this test
@ -30,18 +29,16 @@ function mediaTest(mime) {
return; return;
} }
var mediaSource = new MediaSource(); var mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', function(e) { mediaSource.addEventListener('sourceopen', t.step_func_done(function(e) {
var sourceBuffer = mediaSource.addSourceBuffer(mime); var sourceBuffer = mediaSource.addSourceBuffer(mime);
mediaSource.removeSourceBuffer(sourceBuffer); mediaSource.removeSourceBuffer(sourceBuffer);
t.step(function() { assert_throws({name: 'InvalidStateError'},
assert_throws({name: 'InvalidStateError'}, function() {
function() { sourceBuffer.abort();
sourceBuffer.abort(); },
}, 'SourceBuffer#abort() after removing the SourceBuffer object');
'SourceBuffer#abort() after removing the SourceBuffer object'); }), false);
}); var video = document.createElement('video');
t.done();
}, false);
video.src = window.URL.createObjectURL(mediaSource); video.src = window.URL.createObjectURL(mediaSource);
}, 'SourceBuffer#abort (' + mime + ') : ' + }, 'SourceBuffer#abort (' + mime + ') : ' +
'if this object has been removed from the sourceBuffers attribute of the parent media source, ' + 'if this object has been removed from the sourceBuffers attribute of the parent media source, ' +

View File

@ -10,7 +10,6 @@
<div id="log"></div> <div id="log"></div>
<script> <script>
var video = document.createElement('video');
var contents = {'/media/white.webm': 'video/webm; codecs="vorbis,vp8"', var contents = {'/media/white.webm': 'video/webm; codecs="vorbis,vp8"',
'/media/white.mp4' : 'video/mp4'}; '/media/white.mp4' : 'video/mp4'};
@ -47,26 +46,22 @@ function mediaTest(file, mime) {
var mediaSource = new MediaSource(); var mediaSource = new MediaSource();
var num_updateend = 0; var num_updateend = 0;
var events = []; var events = [];
mediaSource.addEventListener('sourceopen', function(e) { mediaSource.addEventListener('sourceopen', t.step_func(function(e) {
var sourceBuffer = mediaSource.addSourceBuffer(mime); var sourceBuffer = mediaSource.addSourceBuffer(mime);
t.step(function() { assert_equals(sourceBuffer.updating, false);
assert_equals(sourceBuffer.updating, false); sourceBuffer.addEventListener('updatestart', t.step_func(function(e) {
});
sourceBuffer.addEventListener('updatestart', function(e) {
events.push('updatestart'); events.push('updatestart');
//abort when sourceBuffer#updating is true //abort when sourceBuffer#updating is true
sourceBuffer.abort(); sourceBuffer.abort();
t.step(function() { assert_equals(sourceBuffer.updating, false,
assert_equals(sourceBuffer.updating, false, 'Check updating value after calling abort.');
'Check updating value after calling abort.'); assert_equals(sourceBuffer.appendWindowStart, 0);
assert_equals(sourceBuffer.appendWindowStart, 0); assert_equals(sourceBuffer.appendWindowEnd, Number.POSITIVE_INFINITY);
assert_equals(sourceBuffer.appendWindowEnd, Number.POSITIVE_INFINITY); }));
}); sourceBuffer.addEventListener('update', t.step_func(function(e) {
});
sourceBuffer.addEventListener('update', function(e) {
assert_unreached("Can't touch this"); assert_unreached("Can't touch this");
}); }));
sourceBuffer.addEventListener('updateend', function(e) { sourceBuffer.addEventListener('updateend', function(e) {
events.push('updateend'); events.push('updateend');
mediaSource.endOfStream(); mediaSource.endOfStream();
@ -74,19 +69,17 @@ function mediaTest(file, mime) {
sourceBuffer.addEventListener('abort', function(e) { sourceBuffer.addEventListener('abort', function(e) {
events.push('abort'); events.push('abort');
}); });
sourceBuffer.addEventListener('error', function(e) { sourceBuffer.addEventListener('error', t.step_func(function(e) {
assert_unreached("Can't touch this"); assert_unreached("Can't touch this");
}); }));
sourceBuffer.appendBuffer(data); sourceBuffer.appendBuffer(data);
}); }));
mediaSource.addEventListener('sourceended', function(e) { mediaSource.addEventListener('sourceended', t.step_func_done(function(e) {
t.step(function() { assert_array_equals(events,
assert_array_equals(events, ['updatestart', 'abort', 'updateend'],
['updatestart', 'abort', 'updateend'], 'Check the sequence of fired events.');
'Check the sequence of fired events.'); }));
}); var video = document.createElement('video');
t.done();
});
video.src = window.URL.createObjectURL(mediaSource); video.src = window.URL.createObjectURL(mediaSource);
}); });
}, 'SourceBuffer#abort() (' + mime + ') : Check the algorithm when the updating attribute is true.'); }, 'SourceBuffer#abort() (' + mime + ') : Check the algorithm when the updating attribute is true.');

View File

@ -10,40 +10,24 @@
<div id="log"></div> <div id="log"></div>
<script> <script>
var video = document.createElement('video');
var mimes = ['video/webm; codecs="vorbis,vp8"', 'video/mp4']; var mimes = ['video/webm; codecs="vorbis,vp8"', 'video/mp4'];
//check the browser supports the MIME used in this test mimes.forEach(function(mime) {
function isTypeSupported(mime) { async_test(function() {
if(!MediaSource.isTypeSupported(mime)) { assert_true(MediaSource.isTypeSupported(mime),
this.step(function() { "Browser doesn't support the MIME used in this test: " + mime);
assert_unreached("Browser doesn't support the MIME used in this test: " + mime);
});
this.done();
return false;
}
return true;
}
function mediaTest(mime) {
async_test(function(t) {
if(!isTypeSupported.bind(t)(mime)) {
return;
}
var mediaSource = new MediaSource(); var mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', function(e) { mediaSource.addEventListener('sourceopen', this.step_func_done(function(e) {
var sourceBuffer = mediaSource.addSourceBuffer(mime); var sourceBuffer = mediaSource.addSourceBuffer(mime);
sourceBuffer.abort(); sourceBuffer.abort();
t.step(function() { assert_equals(sourceBuffer.appendWindowStart, 0);
assert_equals(sourceBuffer.appendWindowStart, 0); assert_equals(sourceBuffer.appendWindowEnd, Number.POSITIVE_INFINITY);
assert_equals(sourceBuffer.appendWindowEnd, Number.POSITIVE_INFINITY); }));
});
t.done(); var video = document.createElement('video');
});
video.src = window.URL.createObjectURL(mediaSource); video.src = window.URL.createObjectURL(mediaSource);
}, 'SourceBuffer#abort() (' + mime + '): Check the values of appendWindowStart and appendWindowEnd.'); }, 'SourceBuffer#abort() (' + mime + '): Check the values of appendWindowStart and appendWindowEnd.');
}
mimes.forEach(function(mime) {
mediaTest(mime);
}); });
</script> </script>
</body> </body>

View File

@ -15,7 +15,7 @@
<ol> <ol>
<li> Put your mouse over the lower rectangle. pointerover should be received for the purple rectangle <li> Put your mouse over the lower rectangle. pointerover should be received for the purple rectangle
<li> Press and hold left mouse button over "Set Capture" button <li> Press and hold left mouse button over "Set Capture" button
<li> Put your mouse over the lower rectangle. pointerover should be received for the black rectangle <li> Put your mouse over the upper rectangle. pointerover should be received for the black rectangle
<li> Release left mouse button to complete the test. <li> Release left mouse button to complete the test.
</ol> </ol>
</h4> </h4>

View File

@ -1,5 +1,5 @@
def main(request, response): def main(request, response):
response.headers.extend([('Transfer-Encoding', 'chunked'), response.headers.update([('Transfer-Encoding', 'chunked'),
('Content-Type', 'text/html'), ('Content-Type', 'text/html'),
('Connection', 'keep-alive')]) ('Connection', 'keep-alive')])
response.write_status_headers() response.write_status_headers()

View File

@ -426,6 +426,9 @@ IdlArray.prototype.assert_type_is = function(value, type)
return; return;
case "DOMString": case "DOMString":
case "ByteString":
case "USVString":
// TODO: https://github.com/w3c/testharness.js/issues/92
assert_equals(typeof value, "string"); assert_equals(typeof value, "string");
return; return;
@ -1798,6 +1801,8 @@ function create_suitable_object(type)
return 7; return 7;
case "DOMString": case "DOMString":
case "ByteString":
case "USVString":
return "foo"; return "foo";
case "object": case "object":

View File

@ -16,7 +16,8 @@ To use testharness.js you must include two scripts, in the order given:
## Full documentation ## ## Full documentation ##
Full documentation of the API is kept in the source of testharness.js. Full user documentation for the API is in the
[docs/api.md](https://github.com/w3c/testharness.js/blob/master/docs/api.md) file.
You can also read a tutorial on You can also read a tutorial on
[Using testharness.js](http://darobin.github.com/test-harness-tutorial/docs/using-testharness.html). [Using testharness.js](http://darobin.github.com/test-harness-tutorial/docs/using-testharness.html).

View File

@ -0,0 +1,87 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Selectors-API Level 2 Test Suite: HTML with Selectors Level 3</title>
<!-- Selectors API Test Suite Version 3 -->
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/dom/nodes/selectors.js"></script>
<script src="level2-lib.js"></script>
<script src="Element-matches.js"></script>
<style>iframe { visibility: hidden; position: absolute; }</style>
<div id="log">This test requires JavaScript.</div>
<script>
var docType = "html"; // Only run tests suitable for HTML
var frame = document.createElement("iframe"),
doc;
frame.onload = init;
frame.src = "/dom/nodes/ParentNode-querySelector-All-content.html#target";
document.body.appendChild(frame);
function init() {
/*
* This test suite tests Selectors API methods in 4 different contexts:
* 1. Document node
* 2. In-document Element node
* 3. Detached Element node (an element with no parent, not in the document)
* 4. Document Fragment node
*
* For each context, the following tests are run:
*
* The interface check tests ensure that each type of node exposes the Selectors API methods.
*
* The matches() tests are run
* All the selectors tested for both the valid and invalid selector tests are found in selectors.js.
* See comments in that file for documentation of the format used.
*
* The level2-lib.js file contains all the common test functions for running each of the aforementioned tests
*/
// Prepare the nodes for testing
doc = frame.contentDocument; // Document Node tests
var element = doc.getElementById("root"); // In-document Element Node tests
//Setup the namespace tests
setupSpecialElements(element);
var outOfScope = element.cloneNode(true); // Append this to the body before running the in-document
// Element tests, but after running the Document tests. This
// tests that no elements that are not descendants of element
// are selected.
traverse(outOfScope, function(elem) { // Annotate each element as being a clone; used for verifying
elem.setAttribute("data-clone", ""); // that none of these elements ever match.
});
var detached = element.cloneNode(true); // Detached Element Node tests
var fragment = doc.createDocumentFragment(); // Fragment Node tests
fragment.appendChild(element.cloneNode(true));
// Setup Tests
interfaceCheckMatches("Document", doc);
interfaceCheckMatches("Detached Element", detached);
interfaceCheckMatches("Fragment", fragment);
interfaceCheckMatches("In-document Element", element);
runSpecialMatchesTests("DIV Element", element);
runSpecialMatchesTests("NULL Element", document.createElement("null"));
runSpecialMatchesTests("UNDEFINED Element", document.createElement("undefined"));
runInvalidSelectorTestMatches("Document", doc, invalidSelectors);
runInvalidSelectorTestMatches("Detached Element", detached, invalidSelectors);
runInvalidSelectorTestMatches("Fragment", fragment, invalidSelectors);
runInvalidSelectorTestMatches("In-document Element", element, invalidSelectors);
runMatchesTest("In-document", doc, validSelectors, "html");
runMatchesTest("Detached", detached, validSelectors, "html");
runMatchesTest("Fragment", fragment, validSelectors, "html");
runMatchesTest("In-document", doc, scopedSelectors, "html");
}
</script>

View File

@ -0,0 +1,127 @@
/*
* Check that the matches() method exists on the given Node
*/
function interfaceCheckMatches(type, obj) {
if (obj.nodeType === obj.ELEMENT_NODE) {
test(function() {
assert_idl_attribute(obj, "matches", type + " supports matches");
}, type + " supports matches")
}
}
function runSpecialMatchesTests(type, element) {
test(function() { // 1
if (element.tagName.toLowerCase() === "null") {
assert_true(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match.");
} else {
assert_false(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match.");
}
}, type + ".matches(null)")
test(function() { // 2
if (element.tagName.toLowerCase() === "undefined") {
assert_true(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match.");
} else {
assert_false(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match.");
}
}, type + ".matches(undefined)")
test(function() { // 3
assert_throws(TypeError(), function() {
element.matches();
}, "This should throw a TypeError.")
}, type + ".matches no parameter")
}
/*
* Execute queries with the specified invalid selectors for matches()
* Only run these tests when errors are expected. Don't run for valid selector tests.
*/
function runInvalidSelectorTestMatches(type, root, selectors) {
if (root.nodeType === root.ELEMENT_NODE) {
for (var i = 0; i < selectors.length; i++) {
var s = selectors[i];
var n = s["name"];
var q = s["selector"];
test(function() {
assert_throws("SyntaxError", function() {
root.matches(q)
})
}, type + ".matches: " + n + ": " + q);
}
}
}
function runMatchesTest(type, root, selectors, docType) {
var nodeType = getNodeType(root);
for (var i = 0; i < selectors.length; i++) {
var s = selectors[i];
var n = s["name"];
var q = s["selector"];
var e = s["expect"];
var u = s["unexpected"];
var ctx = s["ctx"];
var ref = s["ref"];
if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1))
&& (s["testType"] & TEST_MATCH) ) {
if (ctx && !ref) {
test(function() {
var j, element, refNode;
for (j = 0; j < e.length; j++) {
element = root.querySelector("#" + e[j]);
refNode = root.querySelector(ctx);
assert_true(element.matches(q, refNode), "The element #" + e[j] + " should match the selector.")
}
if (u) {
for (j = 0; j < u.length; j++) {
element = root.querySelector("#" + u[j]);
refNode = root.querySelector(ctx);
assert_false(element.matches(q, refNode), "The element #" + u[j] + " should not match the selector.")
}
}
}, type + " Element.matches: " + n + " (with refNode Element): " + q);
}
if (ref) {
test(function() {
var j, element, refNodes;
for (j = 0; j < e.length; j++) {
element = root.querySelector("#" + e[j]);
refNodes = root.querySelectorAll(ref);
assert_true(element.matches(q, refNodes), "The element #" + e[j] + " should match the selector.")
}
if (u) {
for (j = 0; j < u.length; j++) {
element = root.querySelector("#" + u[j]);
refNodes = root.querySelectorAll(ref);
assert_false(element.matches(q, refNodes), "The element #" + u[j] + " should not match the selector.")
}
}
}, type + " Element.matches: " + n + " (with refNodes NodeList): " + q);
}
if (!ctx && !ref) {
test(function() {
for (var j = 0; j < e.length; j++) {
var element = root.querySelector("#" + e[j]);
assert_true(element.matches(q), "The element #" + e[j] + " should match the selector.")
}
if (u) {
for (j = 0; j < u.length; j++) {
element = root.querySelector("#" + u[j]);
assert_false(element.matches(q), "The element #" + u[j] + " should not match the selector.")
}
}
}, type + " Element.matches: " + n + " (with no refNodes): " + q);
}
}
}
}

View File

@ -6,12 +6,12 @@
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script src="/dom/nodes/selectors.js"></script> <script src="/dom/nodes/selectors.js"></script>
<script src="level2-lib.js"></script> <script src="level2-lib.js"></script>
<script src="ParentNode-find-findAll.js"></script>
<style>iframe { visibility: hidden; position: absolute; }</style> <style>iframe { visibility: hidden; position: absolute; }</style>
<div id="log">This test requires JavaScript.</div> <div id="log">This test requires JavaScript.</div>
<script> <script>
var testType = TEST_FIND | TEST_MATCH;
var docType = "html"; // Only run tests suitable for HTML var docType = "html"; // Only run tests suitable for HTML
var frame = document.createElement("iframe"), var frame = document.createElement("iframe"),
@ -64,36 +64,26 @@ function init() {
fragment.appendChild(element.cloneNode(true)); fragment.appendChild(element.cloneNode(true));
// Setup Tests // Setup Tests
interfaceCheck("Document", doc, testType); interfaceCheckFind("Document", doc);
interfaceCheck("Detached Element", detached, testType); interfaceCheckFind("Detached Element", detached);
interfaceCheck("Fragment", fragment, testType); interfaceCheckFind("Fragment", fragment);
interfaceCheck("In-document Element", element, testType); interfaceCheckFind("In-document Element", element);
runSpecialSelectorTests("Document", doc); runSpecialSelectorTests("Document", doc);
runSpecialSelectorTests("Detached Element", detached); runSpecialSelectorTests("Detached Element", detached);
runSpecialSelectorTests("Fragment", fragment); runSpecialSelectorTests("Fragment", fragment);
runSpecialSelectorTests("In-document Element", element); runSpecialSelectorTests("In-document Element", element);
runSpecialMatchesTests("DIV Element", element);
runSpecialMatchesTests("NULL Element", document.createElement("null"));
runSpecialMatchesTests("UNDEFINED Element", document.createElement("undefined"));
verifyStaticList("Document", doc); verifyStaticList("Document", doc);
verifyStaticList("Detached Element", detached); verifyStaticList("Detached Element", detached);
verifyStaticList("Fragment", fragment); verifyStaticList("Fragment", fragment);
verifyStaticList("In-document Element", element); verifyStaticList("In-document Element", element);
runInvalidSelectorTest("Document", doc, invalidSelectors); runInvalidSelectorTestFind("Document", doc, invalidSelectors);
runInvalidSelectorTest("Detached Element", detached, invalidSelectors); runInvalidSelectorTestFind("Detached Element", detached, invalidSelectors);
runInvalidSelectorTest("Fragment", fragment, invalidSelectors); runInvalidSelectorTestFind("Fragment", fragment, invalidSelectors);
runInvalidSelectorTest("In-document Element", element, invalidSelectors); runInvalidSelectorTestFind("In-document Element", element, invalidSelectors);
runMatchesTest("In-document", doc, validSelectors, testType, "html"); runValidSelectorTest("In-document", doc, scopedSelectors, "html");
runMatchesTest("Detached", detached, validSelectors, testType, "html");
runMatchesTest("Fragment", fragment, validSelectors, testType, "html");
runMatchesTest("In-document", doc, scopedSelectors, testType, "html");
runValidSelectorTest("In-document", doc, scopedSelectors, testType, "html");
} }
</script> </script>

View File

@ -0,0 +1,278 @@
/*
* Check that the find and findAll methods exist on the given Node
*/
function interfaceCheckFind(type, obj) {
test(function() {
var q = typeof obj.find === "function";
assert_true(q, type + " supports find.");
}, type + " supports find")
test(function() {
var qa = typeof obj.findAll === "function";
assert_true( qa, type + " supports findAll.");
}, type + " supports findAll")
}
/*
* Verify that the NodeList returned by findAll is static and and that a new list is created after
* each call. A static list should not be affected by subsequent changes to the DOM.
*/
function verifyStaticList(type, root) {
var pre, post, preLength;
test(function() {
pre = root.findAll("div");
preLength = pre.length;
var div = doc.createElement("div");
(root.body || root).appendChild(div);
assert_equals(pre.length, preLength, "The length of the NodeList should not change.")
}, type + ": static NodeList")
test(function() {
post = root.findAll("div"),
assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list.")
}, type + ": new NodeList")
}
/*
* Verify handling of special values for the selector parameter, including stringification of
* null and undefined, and the handling of the empty string.
*/
function runSpecialSelectorTests(type, root) {
test(function() { // 1
assert_equals(root.findAll(null).length, 1, "This should find one element with the tag name 'NULL'.");
}, type + ".findAll null")
test(function() { // 2
assert_equals(root.findAll(undefined).length, 1, "This should find one elements with the tag name 'UNDEFINED'.");
}, type + ".findAll undefined")
test(function() { // 3
assert_throws(TypeError(), function() {
root.findAll();
}, "This should throw a TypeError.")
}, type + ".findAll no parameter")
test(function() { // 4
var elm = root.find(null)
assert_not_equals(elm, null, "This should find an element.");
assert_equals(elm.tagName.toUpperCase(), "NULL", "The tag name should be 'NULL'.")
}, type + ".find null")
test(function() { // 5
var elm = root.find(undefined)
assert_not_equals(elm, undefined, "This should find an element.");
assert_equals(elm.tagName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'.")
}, type + ".find undefined")
test(function() { // 6
assert_throws(TypeError(), function() {
root.find();
}, "This should throw a TypeError.")
}, type + ".find no parameter.")
test(function() { // 7
result = root.findAll("*");
var i = 0;
traverse(root, function(elem) {
if (elem !== root) {
assert_equals(elem, result[i++], "The result in index " + i + " should be in tree order.")
}
})
}, type + ".findAll tree order");
}
/*
* Execute queries with the specified valid selectors for both find() and findAll()
* Only run these tests when results are expected. Don't run for syntax error tests.
*
* context.findAll(selector, refNodes)
* context.findAll(selector) // Only if refNodes is not specified
* root.findAll(selector, context) // Only if refNodes is not specified
* root.findAll(selector, refNodes) // Only if context is not specified
* root.findAll(selector) // Only if neither context nor refNodes is specified
*
* Equivalent tests will be run for .find() as well.
*/
function runValidSelectorTest(type, root, selectors, docType) {
var nodeType = getNodeType(root);
for (var i = 0; i < selectors.length; i++) {
var s = selectors[i];
var n = s["name"];
var q = s["selector"];
var e = s["expect"];
var ctx = s["ctx"];
var ref = s["ref"];
if (!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) {
//console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s))
var foundall, found, context, refNodes, refArray;
if (s["testType"] & TEST_FIND) {
/*
* If ctx and ref are specified:
* context.findAll(selector, refNodes)
* context.find(selector, refNodes)
*/
if (ctx && ref) {
context = root.querySelector(ctx);
refNodes = root.querySelectorAll(ref);
refArray = Array.prototype.slice.call(refNodes, 0);
test(function() {
foundall = context.findAll(q, refNodes);
verifyNodeList(foundall, expect);
}, type + " [Context Element].findAll: " + n + " (with refNodes NodeList): " + q);
test(function() {
foundall = context.findAll(q, refArray);
verifyNodeList(foundall, expect);
}, type + " [Context Element].findAll: " + n + " (with refNodes Array): " + q);
test(function() {
found = context.find(q, refNodes);
verifyElement(found, foundall, expect)
}, type + " [Context Element].find: " + n + " (with refNodes NodeList): " + q);
test(function() {
found = context.find(q, refArray);
verifyElement(found, foundall, expect)
}, type + " [Context Element].find: " + n + " (with refNodes Array): " + q);
}
/*
* If ctx is specified, ref is not:
* context.findAll(selector)
* context.find(selector)
* root.findAll(selector, context)
* root.find(selector, context)
*/
if (ctx && !ref) {
context = root.querySelector(ctx);
test(function() {
foundall = context.findAll(q);
verifyNodeList(foundall, expect);
}, type + " [Context Element].findAll: " + n + " (with no refNodes): " + q);
test(function() {
found = context.find(q);
verifyElement(found, foundall, expect)
}, type + " [Context Element].find: " + n + " (with no refNodes): " + q);
test(function() {
foundall = root.findAll(q, context);
verifyNodeList(foundall, expect);
}, type + " [Root Node].findAll: " + n + " (with refNode Element): " + q);
test(function() {
foundall = root.find(q, context);
verifyElement(found, foundall, expect);
}, type + " [Root Node].find: " + n + " (with refNode Element): " + q);
}
/*
* If ref is specified, ctx is not:
* root.findAll(selector, refNodes)
* root.find(selector, refNodes)
*/
if (!ctx && ref) {
refNodes = root.querySelectorAll(ref);
refArray = Array.prototype.slice.call(refNodes, 0);
test(function() {
foundall = root.findAll(q, refNodes);
verifyNodeList(foundall, expect);
}, type + " [Root Node].findAll: " + n + " (with refNodes NodeList): " + q);
test(function() {
foundall = root.findAll(q, refArray);
verifyNodeList(foundall, expect);
}, type + " [Root Node].findAll: " + n + " (with refNodes Array): " + q);
test(function() {
found = root.find(q, refNodes);
verifyElement(found, foundall, expect);
}, type + " [Root Node].find: " + n + " (with refNodes NodeList): " + q);
test(function() {
found = root.find(q, refArray);
verifyElement(found, foundall, expect);
}, type + " [Root Node].find: " + n + " (with refNodes Array): " + q);
}
/*
* If neither ctx nor ref is specified:
* root.findAll(selector)
* root.find(selector)
*/
if (!ctx && !ref) {
test(function() {
foundall = root.findAll(q);
verifyNodeList(foundall, expect);
}, type + ".findAll: " + n + " (with no refNodes): " + q);
test(function() {
found = root.find(q);
verifyElement(found, foundall, expect);
}, type + ".find: " + n + " (with no refNodes): " + q);
}
}
} else {
//console.log("Excluding for " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s))
}
}
}
/*
* Execute queries with the specified invalid selectors for both find() and findAll()
* Only run these tests when errors are expected. Don't run for valid selector tests.
*/
function runInvalidSelectorTestFind(type, root, selectors) {
for (var i = 0; i < selectors.length; i++) {
var s = selectors[i];
var n = s["name"];
var q = s["selector"];
test(function() {
assert_throws("SyntaxError", function() {
root.find(q)
})
}, type + ".find: " + n + ": " + q);
test(function() {
assert_throws("SyntaxError", function() {
root.findAll(q)
})
}, type + ".findAll: " + n + ": " + q);
}
}
function verifyNodeList(resultAll, expect) {
assert_not_equals(resultAll, null, "The method should not return null.");
assert_equals(resultAll.length, e.length, "The method should return the expected number of matches.");
for (var i = 0; i < e.length; i++) {
assert_not_equals(resultAll[i], null, "The item in index " + i + " should not be null.")
assert_equals(resultAll[i].getAttribute("id"), e[i], "The item in index " + i + " should have the expected ID.");
assert_false(resultAll[i].hasAttribute("data-clone"), "This should not be a cloned element.");
}
}
function verifyElement(result, resultAll, expect) {
if (expect.length > 0) {
assert_not_equals(result, null, "The method should return a match.")
assert_equals(found.getAttribute("id"), e[0], "The method should return the first match.");
assert_equals(result, resultAll[0], "The result should match the first item from querySelectorAll.");
assert_false(found.hasAttribute("data-clone"), "This should not be annotated as a cloned element.");
} else {
assert_equals(result, null, "The method should not match anything.");
}
}

View File

@ -47,403 +47,14 @@ function setupSpecialElements(parent) {
parent.appendChild(noNS); parent.appendChild(noNS);
} }
/*
* Check that the find, findAll and matches() methods exist on the given Node
*/
function interfaceCheck(type, obj) {
test(function() {
var q = typeof obj.find === "function";
assert_true(q, type + " supports find.");
}, type + " supports find")
test(function() {
var qa = typeof obj.findAll === "function";
assert_true( qa, type + " supports findAll.");
}, type + " supports findAll")
if (obj.nodeType === obj.ELEMENT_NODE) {
test(function() {
assert_idl_attribute(obj, "matches", type + " supports matches");
}, type + " supports matches")
}
}
/*
* Verify that the NodeList returned by findAll is static and and that a new list is created after
* each call. A static list should not be affected by subsequent changes to the DOM.
*/
function verifyStaticList(type, root) {
var pre, post, preLength;
test(function() {
pre = root.findAll("div");
preLength = pre.length;
var div = doc.createElement("div");
(root.body || root).appendChild(div);
assert_equals(pre.length, preLength, "The length of the NodeList should not change.")
}, type + ": static NodeList")
test(function() {
post = root.findAll("div"),
assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list.")
}, type + ": new NodeList")
}
/*
* Verify handling of special values for the selector parameter, including stringification of
* null and undefined, and the handling of the empty string.
*/
function runSpecialSelectorTests(type, root) {
test(function() { // 1
assert_equals(root.findAll(null).length, 1, "This should find one element with the tag name 'NULL'.");
}, type + ".findAll null")
test(function() { // 2
assert_equals(root.findAll(undefined).length, 1, "This should find one elements with the tag name 'UNDEFINED'.");
}, type + ".findAll undefined")
test(function() { // 3
assert_throws(TypeError(), function() {
root.findAll();
}, "This should throw a TypeError.")
}, type + ".findAll no parameter")
test(function() { // 4
var elm = root.find(null)
assert_not_equals(elm, null, "This should find an element.");
assert_equals(elm.tagName.toUpperCase(), "NULL", "The tag name should be 'NULL'.")
}, type + ".find null")
test(function() { // 5
var elm = root.find(undefined)
assert_not_equals(elm, undefined, "This should find an element.");
assert_equals(elm.tagName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'.")
}, type + ".find undefined")
test(function() { // 6
assert_throws(TypeError(), function() {
root.find();
}, "This should throw a TypeError.")
}, type + ".find no parameter.")
test(function() { // 7
result = root.findAll("*");
var i = 0;
traverse(root, function(elem) {
if (elem !== root) {
assert_equals(elem, result[i++], "The result in index " + i + " should be in tree order.")
}
})
}, type + ".findAll tree order");
}
function runSpecialMatchesTests(type, element) {
test(function() { // 1
if (element.tagName.toLowerCase() === "null") {
assert_true(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match.");
} else {
assert_false(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match.");
}
}, type + ".matches(null)")
test(function() { // 2
if (element.tagName.toLowerCase() === "undefined") {
assert_true(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match.");
} else {
assert_false(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match.");
}
}, type + ".matches(undefined)")
test(function() { // 3
assert_throws(TypeError(), function() {
element.matches();
}, "This should throw a TypeError.")
}, type + ".matches no parameter")
}
/*
* Execute queries with the specified valid selectors for both find() and findAll()
* Only run these tests when results are expected. Don't run for syntax error tests.
*
* Where testType is TEST_FIND_BASELINE or TEST_FIND_ADDITIONAL:
*
* context.findAll(selector, refNodes)
* context.findAll(selector) // Only if refNodes is not specified
* root.findAll(selector, context) // Only if refNodes is not specified
* root.findAll(selector, refNodes) // Only if context is not specified
* root.findAll(selector) // Only if neither context nor refNodes is specified
*
* Where testType is TEST_QSA_BASELINE or TEST_QSA_ADDITIONAL
*
* context.querySelectorAll(selector) // Only if refNodes is not specified
* root.querySelectorAll(selector) // Only if neither context nor refNodes is specified
*
* Equivalent tests will be run for .find() as well.
* Note: Do not specify a testType of TEST_QSA_* where either implied :scope or explicit refNodes
* are required.
*/
function runValidSelectorTest(type, root, selectors, testType, docType) {
var nodeType = getNodeType(root);
for (var i = 0; i < selectors.length; i++) {
var s = selectors[i];
var n = s["name"];
var q = s["selector"];
var e = s["expect"];
var ctx = s["ctx"];
var ref = s["ref"];
if (!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) {
//console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s))
var foundall, found, context, refNodes, refArray;
if (s["testType"] & testType & (TEST_FIND)) {
/*
* If ctx and ref are specified:
* context.findAll(selector, refNodes)
* context.find(selector, refNodes)
*/
if (ctx && ref) {
context = root.querySelector(ctx);
refNodes = root.querySelectorAll(ref);
refArray = Array.prototype.slice.call(refNodes, 0);
test(function() {
foundall = context.findAll(q, refNodes);
verifyNodeList(foundall, expect);
}, type + " [Context Element].findAll: " + n + " (with refNodes NodeList): " + q);
test(function() {
foundall = context.findAll(q, refArray);
verifyNodeList(foundall, expect);
}, type + " [Context Element].findAll: " + n + " (with refNodes Array): " + q);
test(function() {
found = context.find(q, refNodes);
verifyElement(found, foundall, expect)
}, type + " [Context Element].find: " + n + " (with refNodes NodeList): " + q);
test(function() {
found = context.find(q, refArray);
verifyElement(found, foundall, expect)
}, type + " [Context Element].find: " + n + " (with refNodes Array): " + q);
}
/*
* If ctx is specified, ref is not:
* context.findAll(selector)
* context.find(selector)
* root.findAll(selector, context)
* root.find(selector, context)
*/
if (ctx && !ref) {
context = root.querySelector(ctx);
test(function() {
foundall = context.findAll(q);
verifyNodeList(foundall, expect);
}, type + " [Context Element].findAll: " + n + " (with no refNodes): " + q);
test(function() {
found = context.find(q);
verifyElement(found, foundall, expect)
}, type + " [Context Element].find: " + n + " (with no refNodes): " + q);
test(function() {
foundall = root.findAll(q, context);
verifyNodeList(foundall, expect);
}, type + " [Root Node].findAll: " + n + " (with refNode Element): " + q);
test(function() {
foundall = root.find(q, context);
verifyElement(found, foundall, expect);
}, type + " [Root Node].find: " + n + " (with refNode Element): " + q);
}
/*
* If ref is specified, ctx is not:
* root.findAll(selector, refNodes)
* root.find(selector, refNodes)
*/
if (!ctx && ref) {
refNodes = root.querySelectorAll(ref);
refArray = Array.prototype.slice.call(refNodes, 0);
test(function() {
foundall = root.findAll(q, refNodes);
verifyNodeList(foundall, expect);
}, type + " [Root Node].findAll: " + n + " (with refNodes NodeList): " + q);
test(function() {
foundall = root.findAll(q, refArray);
verifyNodeList(foundall, expect);
}, type + " [Root Node].findAll: " + n + " (with refNodes Array): " + q);
test(function() {
found = root.find(q, refNodes);
verifyElement(found, foundall, expect);
}, type + " [Root Node].find: " + n + " (with refNodes NodeList): " + q);
test(function() {
found = root.find(q, refArray);
verifyElement(found, foundall, expect);
}, type + " [Root Node].find: " + n + " (with refNodes Array): " + q);
}
/*
* If neither ctx nor ref is specified:
* root.findAll(selector)
* root.find(selector)
*/
if (!ctx && !ref) {
test(function() {
foundall = root.findAll(q);
verifyNodeList(foundall, expect);
}, type + ".findAll: " + n + " (with no refNodes): " + q);
test(function() {
found = root.find(q);
verifyElement(found, foundall, expect);
}, type + ".find: " + n + " (with no refNodes): " + q);
}
}
if (s["testType"] & testType & (TEST_QSA)) {
if (ctx && !ref) {
// context.querySelectorAll(selector) // Only if refNodes is not specified
}
if (!ctx && !ref) {
// root.querySelectorAll(selector) // Only if neither context nor refNodes is specified
}
}
} else {
//console.log("Excluding for " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s))
}
}
}
/*
* Execute queries with the specified invalid selectors for both find() and findAll()
* Only run these tests when errors are expected. Don't run for valid selector tests.
*/
function runInvalidSelectorTest(type, root, selectors) {
for (var i = 0; i < selectors.length; i++) {
var s = selectors[i];
var n = s["name"];
var q = s["selector"];
test(function() {
assert_throws("SyntaxError", function() {
root.find(q)
})
}, type + ".find: " + n + ": " + q);
test(function() {
assert_throws("SyntaxError", function() {
root.findAll(q)
})
}, type + ".findAll: " + n + ": " + q);
if (root.nodeType === root.ELEMENT_NODE) {
test(function() {
assert_throws("SyntaxError", function() {
root.matches(q)
})
}, type + ".matches: " + n + ": " + q);
}
}
}
function runMatchesTest(type, root, selectors, testType, docType) {
var nodeType = getNodeType(root);
for (var i = 0; i < selectors.length; i++) {
var s = selectors[i];
var n = s["name"];
var q = s["selector"];
var e = s["expect"];
var u = s["unexpected"];
var ctx = s["ctx"];
var ref = s["ref"];
if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1))
&& (s["testType"] & testType & (TEST_MATCH)) ) {
if (ctx && !ref) {
test(function() {
var j, element, refNode;
for (j = 0; j < e.length; j++) {
element = root.querySelector("#" + e[j]);
refNode = root.querySelector(ctx);
assert_true(element.matches(q, refNode), "The element #" + e[j] + " should match the selector.")
}
if (u) {
for (j = 0; j < u.length; j++) {
element = root.querySelector("#" + u[j]);
refNode = root.querySelector(ctx);
assert_false(element.matches(q, refNode), "The element #" + u[j] + " should not match the selector.")
}
}
}, type + " Element.matches: " + n + " (with refNode Element): " + q);
}
if (ref) {
test(function() {
var j, element, refNodes;
for (j = 0; j < e.length; j++) {
element = root.querySelector("#" + e[j]);
refNodes = root.querySelectorAll(ref);
assert_true(element.matches(q, refNodes), "The element #" + e[j] + " should match the selector.")
}
if (u) {
for (j = 0; j < u.length; j++) {
element = root.querySelector("#" + u[j]);
refNodes = root.querySelectorAll(ref);
assert_false(element.matches(q, refNodes), "The element #" + u[j] + " should not match the selector.")
}
}
}, type + " Element.matches: " + n + " (with refNodes NodeList): " + q);
}
if (!ctx && !ref) {
test(function() {
for (var j = 0; j < e.length; j++) {
var element = root.querySelector("#" + e[j]);
assert_true(element.matches(q), "The element #" + e[j] + " should match the selector.")
}
if (u) {
for (j = 0; j < u.length; j++) {
element = root.querySelector("#" + u[j]);
assert_false(element.matches(q), "The element #" + u[j] + " should not match the selector.")
}
}
}, type + " Element.matches: " + n + " (with no refNodes): " + q);
}
}
}
}
function traverse(elem, fn) { function traverse(elem, fn) {
if (elem.nodeType === elem.ELEMENT_NODE) { if (elem.nodeType === elem.ELEMENT_NODE) {
fn(elem); fn(elem);
}
elem = elem.firstChild; elem = elem.firstChild;
while (elem) { while (elem) {
traverse(elem, fn); traverse(elem, fn);
elem = elem.nextSibling; elem = elem.nextSibling;
}
} }
} }
@ -460,25 +71,3 @@ function getNodeType(node) {
return "unknown"; // This should never happen. return "unknown"; // This should never happen.
} }
} }
function verifyNodeList(resultAll, expect) {
assert_not_equals(resultAll, null, "The method should not return null.");
assert_equals(resultAll.length, e.length, "The method should return the expected number of matches.");
for (var i = 0; i < e.length; i++) {
assert_not_equals(resultAll[i], null, "The item in index " + i + " should not be null.")
assert_equals(resultAll[i].getAttribute("id"), e[i], "The item in index " + i + " should have the expected ID.");
assert_false(resultAll[i].hasAttribute("data-clone"), "This should not be a cloned element.");
}
}
function verifyElement(result, resultAll, expect) {
if (expect.length > 0) {
assert_not_equals(result, null, "The method should return a match.")
assert_equals(found.getAttribute("id"), e[0], "The method should return the first match.");
assert_equals(result, resultAll[0], "The result should match the first item from querySelectorAll.");
assert_false(found.hasAttribute("data-clone"), "This should not be annotated as a cloned element.");
} else {
assert_equals(result, null, "The method should not match anything.");
}
}

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import argparse import argparse
import json import json
import logging
import os import os
import signal import signal
import socket import socket
@ -19,6 +18,8 @@ repo_root = os.path.abspath(os.path.split(__file__)[0])
sys.path.insert(1, os.path.join(repo_root, "tools", "wptserve")) sys.path.insert(1, os.path.join(repo_root, "tools", "wptserve"))
from wptserve import server as wptserve, handlers from wptserve import server as wptserve, handlers
from wptserve.router import any_method from wptserve.router import any_method
from wptserve.logger import set_logger
sys.path.insert(1, os.path.join(repo_root, "tools", "pywebsocket", "src")) sys.path.insert(1, os.path.join(repo_root, "tools", "pywebsocket", "src"))
from mod_pywebsocket import standalone as pywebsocket from mod_pywebsocket import standalone as pywebsocket
@ -39,12 +40,12 @@ subdomains = [u"www",
u"天気の良い日", u"天気の良い日",
u"élève"] u"élève"]
logger = None def setup_logger(level):
import logging
def default_logger(level): global logger
logger = logging.getLogger("web-platform-tests") logger = logging.getLogger("web-platform-tests")
logging.basicConfig(level=getattr(logging, level.upper())) logging.basicConfig(level=getattr(logging, level.upper()))
return logger set_logger(logger)
def open_socket(port): def open_socket(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -323,12 +324,10 @@ def load_config(default_path, override_path=None):
return rv return rv
def main(): def main():
global logger
config = load_config("config.default.json", config = load_config("config.default.json",
"config.json") "config.json")
logger = default_logger(config["log_level"]) setup_logger(config["log_level"])
config_, servers = start(config) config_, servers = start(config)

View File

@ -21,7 +21,7 @@ interface ServiceWorkerGlobalScope : WorkerGlobalScope {
readonly attribute ServiceWorkerClients clients; readonly attribute ServiceWorkerClients clients;
[Unforgeable] readonly attribute DOMString scope; [Unforgeable] readonly attribute DOMString scope;
Promise<any> fetch((Request or USVString) request); Promise<any> fetch((Request or ScalarValueString) request);
void update(); void update();
void unregister(); void unregister();
@ -55,7 +55,7 @@ synchronous requests MUST NOT be initiated inside of a Service Worker.
interface CacheStorage {}; interface CacheStorage {};
interface ServiceWorkerClients {}; interface ServiceWorkerClients {};
interface Request {}; interface Request {};
interface USVString {}; interface ScalarValueString {};
interface EventHandler {}; interface EventHandler {};
interface WorkerGlobalScope {}; interface WorkerGlobalScope {};
</pre> </pre>

View File

@ -15,11 +15,11 @@
<script type=text/plain id="idl_0"> <script type=text/plain id="idl_0">
[Constructor] [Constructor]
interface Cache { interface Cache {
Promise<AbstractResponse> match((Request or USVString) request, optional QueryParams params); Promise<AbstractResponse> match((Request or ScalarValueString) request, optional QueryParams params);
Promise<sequence<AbstractResponse>> matchAll((Request or USVString) request, optional QueryParams params); Promise<sequence<AbstractResponse>> matchAll((Request or ScalarValueString) request, optional QueryParams params);
Promise<any> add((Request or USVString)... requests); Promise<any> add((Request or ScalarValueString)... requests);
Promise<any> put((Request or USVString) request, AbstractResponse response); Promise<any> put((Request or ScalarValueString) request, AbstractResponse response);
Promise<any> delete((Request or USVString) request, optional QueryParams params); Promise<any> delete((Request or ScalarValueString) request, optional QueryParams params);
Promise<any> each(CacheIterationCallback callback, optional object thisArg); Promise<any> each(CacheIterationCallback callback, optional object thisArg);
}; };
@ -30,7 +30,7 @@ dictionary QueryParams {
boolean prefixMatch; boolean prefixMatch;
}; };
callback CacheIterationCallback = void (AbstractResponse value, (Request or USVString) key, Cache map); callback CacheIterationCallback = void (AbstractResponse value, (Request or ScalarValueString) key, Cache map);
</pre> </pre>
@ -38,7 +38,7 @@ callback CacheIterationCallback = void (AbstractResponse value, (Request or USVS
<script type=text/plain id="untested_idls"> <script type=text/plain id="untested_idls">
interface AbstractResponse {}; interface AbstractResponse {};
interface Request {}; interface Request {};
interface USVString {}; interface ScalarValueString {};
</pre> </pre>
<script> <script>

View File

@ -15,7 +15,7 @@
<script type=text/plain id="idl_0"> <script type=text/plain id="idl_0">
[Constructor(sequence<any> iterable)] [Constructor(sequence<any> iterable)]
interface CacheStorage { interface CacheStorage {
Promise<any> match(USVString url, optional DOMString cacheName); Promise<any> match(ScalarValueString url, optional DOMString cacheName);
Promise<Cache> get(DOMString key); Promise<Cache> get(DOMString key);
Promise<boolean> has(DOMString key); Promise<boolean> has(DOMString key);
Promise<any> set(DOMString key, Cache val); Promise<any> set(DOMString key, Cache val);
@ -42,7 +42,7 @@ convenience methods.
<script type=text/plain id="untested_idls"> <script type=text/plain id="untested_idls">
interface USVString {}; interface ScalarValueString {};
interface Cache {}; interface Cache {};
</pre> </pre>

View File

@ -21,7 +21,7 @@ interface FetchEvent : Event {
readonly attribute boolean isReload; readonly attribute boolean isReload;
void respondWith(Promise<AbstractResponse> r); void respondWith(Promise<AbstractResponse> r);
Promise<any> forwardTo(USVString url); Promise<any> forwardTo(ScalarValueString url);
Promise<any> default(); Promise<any> default();
}; };
@ -51,7 +51,7 @@ Service Workers use the `[FetchEvent][1]` interface for `[fetch][2]` event.
interface Request {}; interface Request {};
interface Client {}; interface Client {};
interface AbstractResponse {}; interface AbstractResponse {};
interface USVString {}; interface ScalarValueString {};
interface Event {}; interface Event {};
</pre> </pre>

View File

@ -1,6 +1,5 @@
import cgi import cgi
import json import json
import logging
import os import os
import traceback import traceback
import urllib import urllib
@ -9,14 +8,13 @@ import urlparse
from constants import content_types from constants import content_types
from pipes import Pipeline, template from pipes import Pipeline, template
from ranges import RangeParser from ranges import RangeParser
from request import Authentication
from response import MultipartContent from response import MultipartContent
from utils import HTTPException from utils import HTTPException
logger = logging.getLogger("wptserve")
__all__ = ["file_handler", "python_script_handler", __all__ = ["file_handler", "python_script_handler",
"FunctionHandler", "handler", "json_handler", "FunctionHandler", "handler", "json_handler",
"as_is_handler", "ErrorHandler"] "as_is_handler", "ErrorHandler", "BasicAuthHandler"]
def guess_content_type(path): def guess_content_type(path):
@ -38,10 +36,15 @@ def filesystem_path(base_path, request, url_base="/"):
path = path[len(url_base):] path = path[len(url_base):]
if ".." in path: if ".." in path:
raise HTTPException(500) raise HTTPException(404)
return os.path.join(base_path, path) new_path = os.path.join(base_path, path)
# Otherwise setting path to / allows access outside the root directory
if not new_path.startswith(base_path):
raise HTTPException(404)
return new_path
class DirectoryHandler(object): class DirectoryHandler(object):
def __init__(self, base_path=None, url_base="/"): def __init__(self, base_path=None, url_base="/"):
@ -153,7 +156,8 @@ class FileHandler(object):
except IOError: except IOError:
return [] return []
else: else:
data = template(request, data) if use_sub:
data = template(request, data)
return [tuple(item.strip() for item in line.split(":", 1)) return [tuple(item.strip() for item in line.split(":", 1))
for line in data.splitlines() if line] for line in data.splitlines() if line]
@ -222,7 +226,7 @@ def FunctionHandler(func):
def inner(request, response): def inner(request, response):
try: try:
rv = func(request, response) rv = func(request, response)
except: except Exception:
msg = traceback.format_exc() msg = traceback.format_exc()
raise HTTPException(500, message=msg) raise HTTPException(500, message=msg)
if rv is not None: if rv is not None:
@ -267,7 +271,7 @@ class AsIsHandler(object):
self.base_path = base_path self.base_path = base_path
self.url_base = url_base self.url_base = url_base
def __call__(request, response): def __call__(self, request, response):
path = filesystem_path(self.base_path, request, self.url_base) path = filesystem_path(self.base_path, request, self.url_base)
try: try:
@ -279,6 +283,33 @@ class AsIsHandler(object):
as_is_handler = AsIsHandler() as_is_handler = AsIsHandler()
class BasicAuthHandler(object):
def __init__(self, handler, user, password):
"""
A Basic Auth handler
:Args:
- handler: a secondary handler for the request after authentication is successful (example file_handler)
- user: string of the valid user name or None if any / all credentials are allowed
- password: string of the password required
"""
self.user = user
self.password = password
self.handler = handler
def __call__(self, request, response):
if "authorization" not in request.headers:
response.status = 401
response.headers.set("WWW-Authenticate", "Basic")
return response
else:
auth = Authentication(request.headers)
if self.user is not None and (self.user != auth.username or self.password != auth.password):
response.set_error(403, "Invalid username or password")
return response
return self.handler(request, response)
basic_auth_handler = BasicAuthHandler(file_handler, None, None)
class ErrorHandler(object): class ErrorHandler(object):
def __init__(self, status): def __init__(self, status):

View File

@ -0,0 +1,29 @@
class NoOpLogger(object):
def critical(self, msg):
pass
def error(self, msg):
pass
def info(self, msg):
pass
def warning(self, msg):
pass
def debug(self, msg):
pass
logger = NoOpLogger()
_set_logger = False
def set_logger(new_logger):
global _set_logger
if _set_logger:
raise Exception("Logger must be set at most once")
global logger
logger = new_logger
_set_logger = True
def get_logger():
return logger

View File

@ -1,14 +1,11 @@
from cgi import escape from cgi import escape
import gzip as gzip_module import gzip as gzip_module
import logging
import re import re
import time import time
import types import types
import uuid import uuid
from cStringIO import StringIO from cStringIO import StringIO
logger = logging.getLogger("wptserve")
def resolve_content(response): def resolve_content(response):
rv = "".join(item for item in response.iter_content()) rv = "".join(item for item in response.iter_content())
@ -289,7 +286,7 @@ class ReplacementTokenizer(object):
token = token[1:-1] token = token[1:-1]
try: try:
token = int(token) token = int(token)
except: except ValueError:
token = unicode(token, "utf8") token = unicode(token, "utf8")
return ("index", token) return ("index", token)
@ -311,9 +308,9 @@ class FirstWrapper(object):
def __getitem__(self, key): def __getitem__(self, key):
try: try:
return self.params.first(key) return self.params.first(key)
except KeyError: except KeyError:
return "" return ""
@pipe() @pipe()
@ -442,7 +439,7 @@ def gzip(request, response):
out = StringIO() out = StringIO()
with gzip_module.GzipFile(fileobj=out, mode="w") as f: with gzip_module.GzipFile(fileobj=out, mode="w") as f:
f.write(content) f.write(content)
response.content = out.getvalue() response.content = out.getvalue()
response.headers.set("Content-Length", len(response.content)) response.headers.set("Content-Length", len(response.content))

View File

@ -1,8 +1,6 @@
import base64 import base64
import cgi import cgi
import Cookie import Cookie
import logging
import os
import StringIO import StringIO
import tempfile import tempfile
import urlparse import urlparse
@ -10,7 +8,6 @@ import urlparse
import stash import stash
from utils import HTTPException from utils import HTTPException
logger = logging.getLogger("wptserve")
missing = object() missing = object()
@ -374,7 +371,7 @@ class RequestHeaders(dict):
a list""" a list"""
try: try:
return dict.__getitem__(self, key.lower()) return dict.__getitem__(self, key.lower())
except: except KeyError:
if default is not missing: if default is not missing:
return default return default
else: else:

View File

@ -2,17 +2,15 @@ from collections import OrderedDict
from datetime import datetime, timedelta from datetime import datetime, timedelta
import Cookie import Cookie
import json import json
import logging
import types import types
import uuid import uuid
import socket import socket
from constants import response_codes from constants import response_codes
from logger import get_logger
logger = logging.getLogger("wptserve")
missing = object() missing = object()
class Response(object): class Response(object):
"""Object representing the response to a HTTP request """Object representing the response to a HTTP request
@ -77,6 +75,8 @@ class Response(object):
self.headers = ResponseHeaders() self.headers = ResponseHeaders()
self.content = [] self.content = []
self.logger = get_logger()
@property @property
def status(self): def status(self):
return self._status return self._status
@ -213,7 +213,7 @@ class Response(object):
("Content-Length", len(data))] ("Content-Length", len(data))]
self.content = data self.content = data
if code == 500: if code == 500:
logger.error(message) self.logger.error(message)
class MultipartContent(object): class MultipartContent(object):
@ -403,7 +403,7 @@ class ResponseWriter(object):
self.write_default_headers() self.write_default_headers()
self.write("\r\n") self.write("\r\n")
if not "content-length" in self._headers_seen: if "content-length" not in self._headers_seen:
self._response.close_connection = True self._response.close_connection = True
if not self._response.explicit_flush: if not self._response.explicit_flush:
self.flush() self.flush()

View File

@ -1,10 +1,8 @@
import itertools import itertools
import logging
import re import re
import types import types
logger = logging.getLogger("wptserve") from logger import get_logger
logger.setLevel(logging.DEBUG)
any_method = object() any_method = object()
@ -99,6 +97,7 @@ class Router(object):
def __init__(self, doc_root, routes): def __init__(self, doc_root, routes):
self.doc_root = doc_root self.doc_root = doc_root
self.routes = [] self.routes = []
self.logger = get_logger()
for route in reversed(routes): for route in reversed(routes):
self.register(*route) self.register(*route)
@ -140,7 +139,7 @@ class Router(object):
methods = [methods] methods = [methods]
for method in methods: for method in methods:
self.routes.append((method, compile_path_match(path), handler)) self.routes.append((method, compile_path_match(path), handler))
logger.debug("Route pattern: %s" % self.routes[-1][1].pattern) self.logger.debug("Route pattern: %s" % self.routes[-1][1].pattern)
def get_handler(self, request): def get_handler(self, request):
"""Get a handler for a request or None if there is no handler. """Get a handler for a request or None if there is no handler.
@ -158,7 +157,7 @@ class Router(object):
name = handler.__name__ name = handler.__name__
else: else:
name = handler.__class__.__name__ name = handler.__class__.__name__
logger.debug("Found handler %s" % name) self.logger.debug("Found handler %s" % name)
match_parts = m.groupdict().copy() match_parts = m.groupdict().copy()
if len(match_parts) < len(m.groups()): if len(match_parts) < len(m.groups()):

View File

@ -1,6 +1,5 @@
import BaseHTTPServer import BaseHTTPServer
import errno import errno
import logging
import os import os
import re import re
import socket import socket
@ -12,16 +11,14 @@ import traceback
import types import types
import urlparse import urlparse
import routes as default_routes
from logger import get_logger
from request import Server, Request from request import Server, Request
from response import Response from response import Response
from router import Router from router import Router
import routes as default_routes
from utils import HTTPException from utils import HTTPException
logger = logging.getLogger("wptserve")
logger.setLevel(logging.DEBUG)
"""HTTP server designed for testing purposes. """HTTP server designed for testing purposes.
The server is designed to provide flexibility in the way that The server is designed to provide flexibility in the way that
@ -67,6 +64,7 @@ class RequestRewriter(object):
self.rules = {} self.rules = {}
for rule in reversed(rules): for rule in reversed(rules):
self.register(*rule) self.register(*rule)
self.logger = get_logger()
def register(self, methods, input_path, output_path): def register(self, methods, input_path, output_path):
"""Register a rewrite rule. """Register a rewrite rule.
@ -95,7 +93,7 @@ class RequestRewriter(object):
if split_url.path in self.rules: if split_url.path in self.rules:
methods, destination = self.rules[split_url.path] methods, destination = self.rules[split_url.path]
if "*" in methods or request_handler.command in methods: if "*" in methods or request_handler.command in methods:
logger.debug("Rewriting request path %s to %s" % self.logger.debug("Rewriting request path %s to %s" %
(request_handler.path, destination)) (request_handler.path, destination))
new_url = list(split_url) new_url = list(split_url)
new_url[2] = destination new_url[2] = destination
@ -106,6 +104,7 @@ class RequestRewriter(object):
class WebTestServer(ThreadingMixIn, BaseHTTPServer.HTTPServer): class WebTestServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
allow_reuse_address = True allow_reuse_address = True
acceptable_errors = (errno.EPIPE, errno.ECONNABORTED) acceptable_errors = (errno.EPIPE, errno.ECONNABORTED)
request_queue_size = 2000
# Ensure that we don't hang on shutdown waiting for requests # Ensure that we don't hang on shutdown waiting for requests
daemon_threads = True daemon_threads = True
@ -143,6 +142,7 @@ class WebTestServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
self.rewriter = rewriter self.rewriter = rewriter
self.scheme = "https" if use_ssl else "http" self.scheme = "https" if use_ssl else "http"
self.logger = get_logger()
if bind_hostname: if bind_hostname:
hostname_port = server_address hostname_port = server_address
@ -155,7 +155,7 @@ class WebTestServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
if config is not None: if config is not None:
Server.config = config Server.config = config
else: else:
logger.debug("Using default configuration") self.logger.debug("Using default configuration")
Server.config = {"host": server_address[0], Server.config = {"host": server_address[0],
"domains": {"": server_address[0]}, "domains": {"": server_address[0]},
"ports": {"http": [self.server_address[1]]}} "ports": {"http": [self.server_address[1]]}}
@ -177,7 +177,7 @@ class WebTestServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
error.errno in self.acceptable_errors)): error.errno in self.acceptable_errors)):
pass # remote hang up before the result is sent pass # remote hang up before the result is sent
else: else:
logger.error(traceback.format_exc()) self.logger.error(traceback.format_exc())
class WebTestRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): class WebTestRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
@ -187,6 +187,7 @@ class WebTestRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def handle_one_request(self): def handle_one_request(self):
response = None response = None
logger = get_logger()
try: try:
self.close_connection = False self.close_connection = False
request_line_is_valid = self.get_request_line() request_line_is_valid = self.get_request_line()
@ -225,8 +226,11 @@ class WebTestRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
err = [] err = []
err.append(traceback.format_exc()) err.append(traceback.format_exc())
response.set_error(500, "\n".join(err)) response.set_error(500, "\n".join(err))
logger.info("%i %s %s (%s) %i" % (response.status[0], request.method, logger.debug("%i %s %s (%s) %i" % (response.status[0],
request.request_path, request.headers.get('Referer'), request.raw_input.length)) request.method,
request.request_path,
request.headers.get('Referer'),
request.raw_input.length))
if not response.writer.content_written: if not response.writer.content_written:
response.write() response.write()
@ -261,10 +265,10 @@ class WebTestRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.close_connection = True self.close_connection = True
return False return False
if len(self.raw_requestline) > 65536: if len(self.raw_requestline) > 65536:
self.requestline = '' self.requestline = ''
self.request_version = '' self.request_version = ''
self.command = '' self.command = ''
return False return False
if not self.raw_requestline: if not self.raw_requestline:
self.close_connection = True self.close_connection = True
return True return True
@ -334,6 +338,7 @@ class WebTestHttpd(object):
self.rewriter = rewriter_cls(rewrites if rewrites is not None else []) self.rewriter = rewriter_cls(rewrites if rewrites is not None else [])
self.use_ssl = use_ssl self.use_ssl = use_ssl
self.logger = get_logger()
if server_cls is None: if server_cls is None:
server_cls = WebTestServer server_cls = WebTestServer
@ -357,7 +362,7 @@ class WebTestHttpd(object):
_host, self.port = self.httpd.socket.getsockname() _host, self.port = self.httpd.socket.getsockname()
except Exception: except Exception:
logger.error('Init failed! You may need to modify your hosts file. Refer to README.md.'); self.logger.error('Init failed! You may need to modify your hosts file. Refer to README.md.');
raise raise
def start(self, block=False): def start(self, block=False):
@ -365,7 +370,7 @@ class WebTestHttpd(object):
:param block: True to run the server on the current thread, blocking, :param block: True to run the server on the current thread, blocking,
False to run on a separate thread.""" False to run on a separate thread."""
logger.info("Starting http server on %s:%s" % (self.host, self.port)) self.logger.info("Starting http server on %s:%s" % (self.host, self.port))
self.started = True self.started = True
if block: if block:
self.httpd.serve_forever() self.httpd.serve_forever()
@ -386,7 +391,7 @@ class WebTestHttpd(object):
self.httpd.server_close() self.httpd.server_close()
self.server_thread.join() self.server_thread.join()
self.server_thread = None self.server_thread = None
logger.info("Stopped http server on %s:%s" % (self.host, self.port)) self.logger.info("Stopped http server on %s:%s" % (self.host, self.port))
except AttributeError: except AttributeError:
pass pass
self.started = False self.started = False

View File

@ -12,26 +12,26 @@
[Constructor(DOMString url, optional DOMString base = "about:blank"), [Constructor(DOMString url, optional DOMString base = "about:blank"),
Exposed=Window,Worker] Exposed=Window,Worker]
interface URL { interface URL {
static DOMString domainToASCII(USVString domain); static DOMString domainToASCII(ScalarValueString domain);
static DOMString domainToUnicode(USVString domain); static DOMString domainToUnicode(ScalarValueString domain);
}; };
URL implements URLUtils; URL implements URLUtils;
[NoInterfaceObject] [NoInterfaceObject]
interface URLUtils { interface URLUtils {
stringifier attribute USVString href; stringifier attribute ScalarValueString href;
readonly attribute DOMString origin; readonly attribute DOMString origin;
attribute USVString protocol; attribute ScalarValueString protocol;
attribute USVString username; attribute ScalarValueString username;
attribute USVString password; attribute ScalarValueString password;
attribute USVString host; attribute ScalarValueString host;
attribute USVString hostname; attribute ScalarValueString hostname;
attribute USVString port; attribute ScalarValueString port;
attribute USVString pathname; attribute ScalarValueString pathname;
attribute USVString search; attribute ScalarValueString search;
attribute URLSearchParams searchParams; attribute URLSearchParams searchParams;
attribute USVString hash; attribute ScalarValueString hash;
}; };
[NoInterfaceObject] [NoInterfaceObject]
@ -48,15 +48,15 @@ interface URLUtilsReadOnly {
readonly attribute DOMString hash; readonly attribute DOMString hash;
}; };
interface URLSearchParams { interface URLSearchParams {
void append(USVString name, USVString value); void append(ScalarValueString name, ScalarValueString value);
void delete(USVString name); void delete(ScalarValueString name);
DOMString? get(USVString name); DOMString? get(ScalarValueString name);
sequence<DOMString> getAll(USVString name); sequence<DOMString> getAll(ScalarValueString name);
boolean has(USVString name); boolean has(ScalarValueString name);
void set(USVString name, USVString value); void set(ScalarValueString name, ScalarValueString value);
stringifier; stringifier;
}; };
typedef DOMString USVString; typedef DOMString ScalarValueString;
</script> </script>
<script> <script>
"use strict"; "use strict";

View File

@ -91,7 +91,7 @@ mailto:example.com/ s:mailto p:example.com/
/a/\s/c s:http h:example.org p:/a/%20/c /a/\s/c s:http h:example.org p:/a/%20/c
/a%2fc s:http h:example.org p:/a%2fc /a%2fc s:http h:example.org p:/a%2fc
/a/%2f/c s:http h:example.org p:/a/%2f/c /a/%2f/c s:http h:example.org p:/a/%2f/c
\#\u03B2 s:http h:example.org p:/foo/bar f:#\u03B2 \#\u03B2 s:http h:example.org p:/foo/bar f:#%CE%B2
data:text/html,test#test s:data p:text/html,test f:#test data:text/html,test#test s:data p:text/html,test f:#test
# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/file.html # Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/file.html
@ -166,7 +166,7 @@ http://www.google.com/foo?bar=baz# about:blank s:http h:www.google.com p:/foo q:
http://www.google.com/foo?bar=baz#\s\u00BB s:http h:www.google.com p:/foo q:?bar=baz f:#\s%C2%BB http://www.google.com/foo?bar=baz#\s\u00BB s:http h:www.google.com p:/foo q:?bar=baz f:#\s%C2%BB
http://[www.google.com]/ http://[www.google.com]/
http://www.google.com s:http h:www.google.com p:/ http://www.google.com s:http h:www.google.com p:/
http://192.0x00A80001 s:http h:192.0x00a80001 p:/ http://192.0x00A80001 s:http h:192.168.0.1 p:/
http://www/foo%2Ehtml s:http h:www p:/foo%2Ehtml http://www/foo%2Ehtml s:http h:www p:/foo%2Ehtml
http://www/foo/%2E/html s:http h:www p:/foo/html http://www/foo/%2E/html s:http h:www p:/foo/html
http://user:pass@/ http://user:pass@/
@ -315,9 +315,9 @@ http://hello%00
# Escaped numbers should be treated like IP addresses if they are. # Escaped numbers should be treated like IP addresses if they are.
# No special handling for IPv4 or IPv4-like URLs # No special handling for IPv4 or IPv4-like URLs
http://%30%78%63%30%2e%30%32%35%30.01 s:http p:/ h:0xc0.0250.01 http://%30%78%63%30%2e%30%32%35%30.01 s:http p:/ h:192.168.0.1
http://%30%78%63%30%2e%30%32%35%30.01%2e s:http p:/ h:0xc0.0250.01. http://%30%78%63%30%2e%30%32%35%30.01%2e s:http p:/ h:0xc0.0250.01.
http://192.168.0.257 s:http p:/ h:192.168.0.257 http://192.168.0.257
# Invalid escaping should trigger the regular host error handling. # Invalid escaping should trigger the regular host error handling.
http://%3g%78%63%30%2e%30%32%35%30%2E.01 http://%3g%78%63%30%2e%30%32%35%30%2E.01
@ -328,7 +328,13 @@ http://192.168.0.1\shello
# Fullwidth and escaped UTF-8 fullwidth should still be treated as IP. # Fullwidth and escaped UTF-8 fullwidth should still be treated as IP.
# These are "0Xc0.0250.01" in fullwidth. # These are "0Xc0.0250.01" in fullwidth.
http://\uff10\uff38\uff43\uff10\uff0e\uff10\uff12\uff15\uff10\uff0e\uff10\uff11 s:http p:/ h:0xc0.0250.01 http://\uff10\uff38\uff43\uff10\uff0e\uff10\uff12\uff15\uff10\uff0e\uff10\uff11 s:http p:/ h:192.168.0.1
# Broken IPv6 # Broken IPv6
http://[google.com] http://[google.com]
# Misc Unicode
http://foo:\uD83D\uDCA9@example.com/bar s:http h:example.com p:/bar u:foo pass:%F0%9F%92%A9
# resolving a relative reference against an unknown scheme results in an error
x test:test

View File

@ -5,8 +5,6 @@
<title>Vibration API: test a simple array parameter to vibrate()</title> <title>Vibration API: test a simple array parameter to vibrate()</title>
<link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/> <link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
<link rel='help' href='http://www.w3.org/TR/vibration/#methods'/> <link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
<meta name='flags' content='dom, interact'/>
<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
</head> </head>
<body> <body>
<h1>Description</h1> <h1>Description</h1>
@ -15,20 +13,11 @@
</p> </p>
<button id='vib'>Vibrate!</button> <button id='vib'>Vibrate!</button>
<div id='log'></div> <div id='log'></div>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script> <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
<script> <script>
if (undefined !== navigator.vibrate) { document.getElementById("vib").onclick = function () {
setup({explicit_done:true}); navigator.vibrate([2000]);
var t = async_test("Tests that vibrate returns true"); };
document.getElementById("vib").onclick = t.step_func(function () {
assert_true(navigator.vibrate([2000]), "vibrate() returns a boolean");
t.done();
done();
}, "Calling vibrate returns true");
}
</script> </script>
</body> </body>
</html> </html>

View File

@ -24,3 +24,8 @@ mode: compatibility
[ios-driver] [ios-driver]
capabilities: {"browserName": "iphone"} capabilities: {"browserName": "iphone"}
mode: compatibility mode: compatibility
[blackberry]
url: http://169.254.0.1:1338
capabilities: {"browserName": "blackberry"}
mode: compatibility

View File

@ -1,6 +1,6 @@
<!-- <!--
onmessage = function(e) { onmessage = function(e) {
postMessage(e.ports === null); postMessage(e.ports instanceof Array && e.ports.length === 0);
} }
/* /*
--> -->

View File

@ -25,7 +25,7 @@ function compare_primitive(actual, input, test_obj) {
if (test_obj) if (test_obj)
test_obj.done(); test_obj.done();
} }
function compare_Array(callback) { function compare_Array(callback, callback_is_async) {
return function(actual, input, test_obj) { return function(actual, input, test_obj) {
if (typeof actual === 'string') if (typeof actual === 'string')
assert_unreached(actual); assert_unreached(actual);
@ -33,12 +33,12 @@ function compare_Array(callback) {
assert_not_equals(actual, input); assert_not_equals(actual, input);
assert_equals(actual.length, input.length, 'length'); assert_equals(actual.length, input.length, 'length');
callback(actual, input); callback(actual, input);
if (test_obj) if (test_obj && !callback_is_async)
test_obj.done(); test_obj.done();
} }
} }
function compare_Object(callback) { function compare_Object(callback, callback_is_async) {
return function(actual, input, test_obj) { return function(actual, input, test_obj) {
if (typeof actual === 'string') if (typeof actual === 'string')
assert_unreached(actual); assert_unreached(actual);
@ -46,15 +46,15 @@ function compare_Object(callback) {
assert_false(actual instanceof Array, 'instanceof Array'); assert_false(actual instanceof Array, 'instanceof Array');
assert_not_equals(actual, input); assert_not_equals(actual, input);
callback(actual, input); callback(actual, input);
if (test_obj) if (test_obj && !callback_is_async)
test_obj.done(); test_obj.done();
} }
} }
function enumerate_props(compare_func) { function enumerate_props(compare_func, test_obj) {
return function(actual, input) { return function(actual, input) {
for (var x in input) { for (var x in input) {
compare_func(actual[x], input[x]); compare_func(actual[x], input[x], test_obj);
} }
}; };
} }
@ -339,41 +339,41 @@ function func_Blob_NUL() {
check('Blob NUL', func_Blob_NUL, compare_Blob); check('Blob NUL', func_Blob_NUL, compare_Blob);
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, [test_obj.step(func_Blob_basic)], compare_Array(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, [test_obj.step(func_Blob_basic)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Array Blob object, Blob basic'); }, 'Array Blob object, Blob basic');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800]))], compare_Array(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)'); }, 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, [test_obj.step(func_Blob_bytes([0xDC00]))], compare_Array(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, [test_obj.step(func_Blob_bytes([0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)'); }, 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))], compare_Array(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Array Blob object, Blob paired surrogates (invalid utf-8)'); }, 'Array Blob object, Blob paired surrogates (invalid utf-8)');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, [test_obj.step(func_Blob_empty)], compare_Array(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, [test_obj.step(func_Blob_empty)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Array Blob object, Blob empty'); }, 'Array Blob object, Blob empty');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, [test_obj.step(func_Blob_NUL)], compare_Array(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, [test_obj.step(func_Blob_NUL)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Array Blob object, Blob NUL'); }, 'Array Blob object, Blob NUL');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, {'x':test_obj.step(func_Blob_basic)}, compare_Object(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, {'x':test_obj.step(func_Blob_basic)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Object Blob object, Blob basic'); }, 'Object Blob object, Blob basic');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800]))}, compare_Object(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)'); }, 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xDC00]))}, compare_Object(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)'); }, 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))}, compare_Object(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Object Blob object, Blob paired surrogates (invalid utf-8)'); }, 'Object Blob object, Blob paired surrogates (invalid utf-8)');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, {'x':test_obj.step(func_Blob_empty)}, compare_Object(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, {'x':test_obj.step(func_Blob_empty)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Object Blob object, Blob empty'); }, 'Object Blob object, Blob empty');
async_test(function(test_obj) { async_test(function(test_obj) {
check(test_obj.name, {'x':test_obj.step(func_Blob_NUL)}, compare_Object(enumerate_props(compare_Blob)), test_obj); check(test_obj.name, {'x':test_obj.step(func_Blob_NUL)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
}, 'Object Blob object, Blob NUL'); }, 'Object Blob object, Blob NUL');
function compare_File(actual, input, test_obj) { function compare_File(actual, input, test_obj) {

View File

@ -9,8 +9,9 @@ function check_true(actual, msg) {
return true; return true;
} }
function check_Blob(msg, input, port, expect_File) { function check_Blob(msg, input, port, expect_File, orig_input) {
expect_File = !!expect_File; expect_File = !!expect_File;
orig_input = orig_input || input;
try { try {
var expected; var expected;
switch (msg) { switch (msg) {
@ -64,7 +65,7 @@ function check_Blob(msg, input, port, expect_File) {
check_true(view.getUint8(i) === expected[i], 'view.getUint8('+i+') === expected['+i+']') check_true(view.getUint8(i) === expected[i], 'view.getUint8('+i+') === expected['+i+']')
} }
if (log.length === 0) { if (log.length === 0) {
port.postMessage(input); port.postMessage(orig_input);
} else { } else {
port.postMessage('FAIL '+log); port.postMessage('FAIL '+log);
} }
@ -724,7 +725,7 @@ function check(input, port) {
case 'Array Blob object, Blob NUL': case 'Array Blob object, Blob NUL':
if (check_true(input instanceof Array, 'input instanceof Array') && if (check_true(input instanceof Array, 'input instanceof Array') &&
check_true(input.length === 1, 'input.length === 1')) { check_true(input.length === 1, 'input.length === 1')) {
check_Blob(msg.substr('Array Blob object, '.length), input[0], port); check_Blob(msg.substr('Array Blob object, '.length), input[0], port, false, input);
// no postMessage or close here, check_Blob takes care of that // no postMessage or close here, check_Blob takes care of that
} }
break; break;
@ -742,7 +743,7 @@ function check(input, port) {
i++; i++;
} }
if (check_true(i === 1, 'i === 1')) { if (check_true(i === 1, 'i === 1')) {
check_Blob(msg.substr('Object Blob object, '.length), input['x'], port); check_Blob(msg.substr('Object Blob object, '.length), input['x'], port, false, input);
// no postMessage or close here, check_Blob takes care of that // no postMessage or close here, check_Blob takes care of that
} }
} }