-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add sectioning tests. #1538
Add sectioning tests. #1538
Changes from 10 commits
75b609c
bac8ae7
584055a
810a2e7
e860c93
6ff0d3c
c6e2167
6d14112
2b8ff1f
725594c
3b86eb9
eec56ec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Body Element</title> | ||
<link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com"> | ||
<link rel="help" href="http://www.w3.org/html/wg/drafts/html/CR/single-page.html#the-body-element"> | ||
<link rel="help" href="http://www.w3.org/html/wg/drafts/html/CR/single-page.html#event-handlers-on-elements,-document-objects,-and-window-objects"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
</head> | ||
<body onblur = "foobar = 0;" | ||
onfocus = "foobar = 1;" | ||
onload = "foobar = 2;" | ||
onscroll = "foobar = 3;" | ||
onerror = "foobar = 4;" | ||
onafterprint = "foobar = 5;" | ||
onbeforeprint = "foobar = 6;" | ||
onbeforeunload = "foobar = 7;" | ||
onhashchange = "foobar = 8;" | ||
onmessage = "foobar = 9;" | ||
onoffline = "foobar = 10;" | ||
ononline = "foobar = 11;" | ||
onpagehide = "foobar = 12;" | ||
onpageshow = "foobar = 13;" | ||
onpopstate = "foobar = 14;" | ||
onresize = "foobar = 15;" | ||
onstorage = "foobar = 16;" | ||
onunload = "foobar = 17;"> | ||
|
||
<h1>Description</h1> | ||
<p>This test checks body element's attributes vis-a-vis content markup, IDL methods, and mirroring by the window object.</p> | ||
|
||
<div id="log"></div> | ||
|
||
<script> | ||
"use strict"; | ||
|
||
// 5.0 Spec lists 18 content attributes for body element and says | ||
// "The body element expose as event handler content attributes a number of the event handlers of the Window object. | ||
// It also mirrors their event handler IDL attributes." | ||
// All 18 content attributes are listed in the third section of | ||
// http://www.w3.org/html/wg/drafts/html/CR/single-page.html#event-handlers-on-elements,-document-objects,-and-window-objects, | ||
// confirming that "a number of" means all eighteen. | ||
|
||
function makeRegEx(strAttr, strArgs, strCode) { | ||
// Spec does not specify if function needs to be named or not, so this test accomodates both | ||
var regEx = /abc/, | ||
strFuncName = "(anonymous|" + strAttr + ")"; | ||
|
||
regEx = new RegExp("^function\\s*" + strFuncName + "\\s*\\(" + strArgs + "\\)\\s*\\{\\s*" + strCode + "?\\s*\\}\\s*$", "m"); | ||
|
||
return regEx; | ||
} | ||
|
||
// note: index of attributes here must match return values of actual markup placeholder functions | ||
var testAttributes = ["onblur", "onfocus", "onload", "onscroll", "onerror", "onafterprint", | ||
"onbeforeprint", "onbeforeunload", "onhashchange", "onmessage", "onoffline", | ||
"ononline", "onpagehide", "onpageshow", "onpopstate", "onresize", "onstorage", "onunload"]; | ||
|
||
var numAttr = 0, | ||
strAttr = "", | ||
strCode = "", | ||
strArgs = "", | ||
strArgsRegEx = "", | ||
regEx = /abc/, | ||
funcExpected = {}, | ||
strCheck = "", | ||
foobar = ""; | ||
|
||
|
||
for (numAttr = 0; numAttr < testAttributes.length; numAttr++) { | ||
strAttr = testAttributes[numAttr]; // name of current attribute to check | ||
strCode = "foobar = " + numAttr + ";"; // expected content of content attribute | ||
// prepare strings needed to create correct event handler (onerror has more arguments than the others) | ||
if (strAttr !== "onerror") { | ||
strArgs = strArgsRegEx = "event"; | ||
} else { | ||
// is onerror. Spec defines exactly four parameters for onerror event, so capturing that in this test. | ||
strArgs = "event, source, lineno, column"; | ||
strArgsRegEx = "((event|source|lineno|column),?\\s*){4}"; // for regExp | ||
} | ||
|
||
// check that content attribute via markup was correctly read into attributes array | ||
test(function () { | ||
assert_equals(document.body.attributes[strAttr].value, strCode, "Content attribute " + strAttr + ":"); | ||
}, strAttr + ": document.body.attributes[" + strAttr + "] populated with content markup for " + strAttr + " attribute"); | ||
|
||
// check that body IDL attribute (document.body[strAttr]) mirrors content attribute | ||
test(function () { | ||
// (As the functions being compared are not the same object, even though the two objects should have the same code, | ||
// we use assert_regexp_match to compare two different function bodies to make sure they are actually the same.) | ||
|
||
funcExpected = new Function(strArgs, strCode); | ||
regEx = makeRegEx(strAttr, strArgsRegEx, strCode); | ||
|
||
if ((typeof document.body[strAttr] === "function") && (document.body[strAttr] !== undefined) | ||
&& (strCheck = document.body[strAttr].toString(), regEx.test(strCheck))) { | ||
|
||
assert_regexp_match(strCheck, regEx, "document.body." + strAttr + ":"); | ||
|
||
} else { | ||
assert_equals(document.body[strAttr], funcExpected, "document.body." + strAttr + ":"); | ||
} | ||
}, strAttr + ": document.body." + strAttr + " populated by content markup for " + strAttr + " attribute"); | ||
|
||
// check that relevant window event handler (window[strAttr]) mirrors content attribute | ||
test(function() { | ||
// (As the functions being compared are not the same object, even though the two objects should have the same code, | ||
// we use assert_regexp_match to compare two different function bodies to make sure they are actually the same.) | ||
|
||
funcExpected = new Function(strArgs, strCode); | ||
regEx = makeRegEx(strAttr, strArgsRegEx, strCode); | ||
|
||
if ((typeof window[strAttr] === "function") && | ||
(window[strAttr] !== undefined) && | ||
(strCheck = window[strAttr].toString(), regEx.test(strCheck))) { | ||
assert_regexp_match(strCheck, regEx, "window." + strAttr + ":"); | ||
} else { | ||
assert_equals(window[strAttr], funcExpected, "window." + strAttr + ":"); | ||
} | ||
}, strAttr + ": window." + strAttr + " populated by content markup for " + strAttr + " attribute"); | ||
|
||
// check that document.body[strAttr] updates itself | ||
test(function() { | ||
// update expectations | ||
strCode = "foobar = " + numAttr + "-" + numAttr + ";"; | ||
funcExpected = new Function(strArgs, strCode); | ||
regEx = makeRegEx(strAttr, strArgsRegEx, strCode); | ||
|
||
// update document.body | ||
document.body[strAttr] = new Function(strArgs, strCode); | ||
|
||
// use the regexp to check two functions' equivalency-despite-being-different-objects | ||
if ((typeof document.body[strAttr] === "function") && | ||
(document.body[strAttr] !== undefined) && | ||
(strCheck = document.body[strAttr].toString(), regEx.test(strCheck))) { | ||
assert_regexp_match(strCheck, regEx, "document.body." + strAttr + ":"); | ||
} else { | ||
assert_equals(document.body[strAttr], funcExpected, "document.body." + strAttr + ":"); | ||
} | ||
}, strAttr + ": changing document.body." + strAttr + " updates document.body." + strAttr); | ||
|
||
// check that document.body[strAttr] updated window.body[strAttr] | ||
test(function() { | ||
assert_equals(window[strAttr], document.body[strAttr], "window." + strAttr + ":"); | ||
}, strAttr + ": changing document.body." + strAttr + " updates window." + strAttr); | ||
|
||
// check that window[strAttr] updates itself | ||
// (probably duplicates other tests, but the last test in file relies on window working, so double-checking) | ||
test(function() { | ||
// update expectations | ||
strCode = "foobar = " + numAttr + "-" + numAttr + "-" + numAttr + ";"; | ||
funcExpected = new Function(strArgs, strCode); | ||
regEx = makeRegEx(strAttr, strArgsRegEx, strCode); | ||
|
||
// update window | ||
window[strAttr] = new Function(strArgs, strCode); | ||
|
||
// use the regexp to check two functions' equivalency-despite-white-space | ||
if ((typeof window[strAttr] === "function") && | ||
(window[strAttr] !== undefined) && | ||
(strCheck = window[strAttr].toString(), regEx.test(strCheck))) { | ||
assert_regexp_match(strCheck, regEx, "window." + strAttr + ":"); | ||
} else { | ||
assert_equals(document.body[strAttr], funcExpected, "window." + strAttr + ":"); | ||
} | ||
|
||
}, strAttr + ": changing window." + strAttr + " updates window." + strAttr); | ||
|
||
// check that window[strAttr] updated document.body[strAttr]. | ||
test(function() { | ||
assert_equals(document.body[strAttr], window[strAttr], "window." + strAttr + ":"); | ||
}, strAttr + ": changing window." + strAttr + " updates document.body." + strAttr); | ||
} | ||
</script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Body Element</title> | ||
<link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com"> | ||
<link rel="help" href="http://www.w3.org/html/wg/drafts/html/CR/single-page.html#the-body-element"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The spec for this and part2 is the places that reference https://html.spec.whatwg.org/#determining-the-target-of-an-event-handler. The model is that setting/getting the content and IDL attribute redirects to the window object, as opposed to the event target order being tweaked during event dispatch. part1 and part2 all pass on Chrome, Edge, Firefox and Safari, except for part1 on Edge. I'm pretty sure that's covered by the Edge failures in https://wpt.fyi/results/html/webappapis/scripting/events/event-handler-attributes-body-window.html?label=stable&aligned=true. With this covered in html/webappapis/scripting/events/, I'll delete these too. |
||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
</head> | ||
<body onerror="myErrors.push('body-content')"> | ||
<h1>Description</h1> | ||
<p>This test validates the behavior of a bubbling onerror event as it passes through document.body (part one - body's event handler as provided by a content attribute is NOT fired when event reaches body, but waits for the event to reach window before firing).</p> | ||
|
||
<div id="log"></div> | ||
|
||
<script> | ||
"use strict"; | ||
|
||
/* The spec discusses 5 of the body element's content attributes specifically: | ||
"The onblur, onerror, onfocus, onload, and onscroll | ||
event handlers of the Window object, exposed on the body element, shadow the generic event handlers | ||
with the same names normally supported by HTML elements. With the exception of onerror, this is actually | ||
implemented by just using the properties of the HTMLElement interface. The onerror attribute has a different type." | ||
|
||
**** QUESTION: Testing the implementation of event handlers as based on which interface is outside the scope of these tests, | ||
but is there a test to be done here re: the type of the onerror attributes? **** | ||
|
||
The spec then says: "Thus, for example, a bubbling error event dispatched on a child of the body element | ||
of a Document would first trigger the onerror event handler content attributes of that element, then | ||
that of the root html element, and only then would it trigger the onerror event handler content attribute | ||
on the body element. This is because the event would bubble from the target, to the body, to the html, | ||
to the Document, to the Window, and the event handler on the body is watching the Window not the body." | ||
*/ | ||
|
||
// Check that, during bubbling of an onerror event, the body.onerror content attribute is fired when the bubble reaches window object | ||
|
||
var myErrors = []; | ||
|
||
test(function() { | ||
var myError = {}; | ||
|
||
// Add event listeners to other elements in chain | ||
window.addEventListener("error", function(event) { myErrors.push("window"); }, false); | ||
document.addEventListener("error", function(event) { myErrors.push("document"); }, false); | ||
document.documentElement.addEventListener("error", function(event) { myErrors.push("html"); }, false); | ||
document.body.firstElementChild.addEventListener("error", function(event) { myErrors.push("child"); }, false); | ||
// (To match spec text, it would have been nice to use "the onerror event handler content attributes of that [child] element" | ||
// for the test, but I don't see any possible child elements that have an onerror CONTENT attribute | ||
// so the child will make do with an event listener) | ||
|
||
// Create an error in child of body element | ||
myError = document.createEvent("Event"); | ||
myError.initEvent("error", true, false); | ||
document.body.firstElementChild.dispatchEvent(myError); | ||
|
||
// Verify that body's onerror content attribute's event handler was fired AFTER the child/html/documents' onerror content attributes, but near window | ||
assert_in_array("body-content", myErrors, "Verify that body's onerror content attribute was fired."); | ||
assert_true(myErrors.indexOf("body-content") > myErrors.lastIndexOf("child"), "Body's onerror content attribute fired after child's onerror event handler(s)."); | ||
assert_true(myErrors.indexOf("body-content") > myErrors.lastIndexOf("html"), "Body's onerror content attribute fired after html's onerror event handler(s)."); | ||
assert_true(myErrors.indexOf("body-content") > myErrors.lastIndexOf("document"), "Body's onerror content attribute fired after document's onerror event handler(s)."); | ||
assert_approx_equals(myErrors.indexOf("body-content"), myErrors.indexOf("window"), 1, "Body's onerror content attribute fired immediately before or after window event handler(s)."); | ||
}, "Body's onerror content attribute's event handler fired as per spec order during bubbling"); | ||
|
||
|
||
</script> | ||
</body> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Body Element</title> | ||
<link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com"> | ||
<link rel="help" href="http://www.w3.org/html/wg/drafts/html/CR/single-page.html#the-body-element"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
</head> | ||
<body> | ||
|
||
<h1>Description</h1> | ||
<p>This test validates the behavior of a bubbling onerror event as it passes through document.body (part two - body's event handler as provided by an event listener is fired when event reaches body, rather than waiting for event to reach window).</p> | ||
|
||
<div id="log"></div> | ||
|
||
<script> | ||
"use strict"; | ||
|
||
// Spec says, in context of a bubbling error event: "A regular event listener attached to the body using addEventListener(), however, would be run when the | ||
// event bubbled through the body and not when it reaches the Window object." | ||
|
||
// Verify that an event handler added onto body through addEventListener runs after body's child's but before html's during a bubbling error event | ||
test(function() { | ||
var myErrors = [], myError = {}; | ||
|
||
// add event listeners | ||
document.documentElement.addEventListener("error", function(event) { myErrors.push("html");}, false); | ||
document.body.addEventListener("error", function(event) { myErrors.push("body-eventListener");}, false); | ||
document.body.firstElementChild.addEventListener("error", function(event) { myErrors.push("child");}, false); | ||
|
||
// Create an error in child of body element | ||
myError = document.createEvent("Event"); | ||
myError.initEvent("error", true, false); | ||
document.body.firstElementChild.dispatchEvent(myError); | ||
|
||
// Verify that body's onerror added event handler was fired AFTER child's and BEFORE html's | ||
assert_in_array("body-eventListener", myErrors, "Verify that body's onerror event handler was fired."); | ||
assert_true(myErrors.indexOf("body-eventListener") > myErrors.lastIndexOf("child"), "Body's onerror event handler fired after child's onerror event handler(s)."); | ||
assert_true(myErrors.lastIndexOf("body-eventListener") < myErrors.indexOf("html"), "Body's onerror event handler fired before html's onerror event handler(s)."); | ||
}, "Body's onerror event listener's event handler fired as per spec order during bubbling"); | ||
</script> | ||
</body> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Body Element</title> | ||
<link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com"> | ||
</head> | ||
<body onbeforeunload="window.opener.myReaction.push('beforeunload-content')" | ||
onblur="window.opener.myReaction.push('blur-content')" | ||
onerror="window.opener.myReaction.push('error-content')" | ||
onfocus="window.opener.myReaction.push('focus-content')" | ||
onhashchange="window.opener.myReaction.push('hashchange-content')" | ||
onmessage="window.opener.myReaction.push('message-content')" | ||
onpagehide="window.opener.myReaction.push('pagehide-content')" | ||
onpageshow="window.opener.myReaction.push('pageshow-content')" | ||
onpopstate="window.opener.myReaction.push('popstate-content')" | ||
onscroll="window.opener.myReaction.push('scroll-content')" | ||
onstorage="window.opener.myReaction.push('storage-content')" | ||
onunload="window.opener.myReaction.push('unload-content')"> | ||
<h1 id="first_hash">Purpose of form</h1> | ||
<p>This new window is here to test that body element's automatable event handlers truly respond to given events.</p> | ||
<p>Please be patient!</p> | ||
<p>There is a long (10 second) interval between the firing of these events and the return to the testing page.</p> | ||
<p>But you will get there eventually.</p> | ||
<h1 id="second_hash">List of Events</h1> | ||
<p>We are going to test:</p> | ||
<ul> | ||
<li>load</li> | ||
<li>pageshow</li> | ||
<li>blur</li> | ||
<li>focus</li> | ||
<li>scroll</li> | ||
<li>popstate</li> | ||
<li>hashchange</li> | ||
<li>message</li> | ||
<li>storage</li> | ||
<li>error</li> | ||
<li>beforeunload</li> | ||
<li>pagehide</li> | ||
<li>unload</li> | ||
</ul> | ||
<a id="first_anchor" href="#first_hash">Purpose</a> | ||
<a id="second_anchor" href="#second_hash">Events</a> | ||
<script> | ||
function runEvents() { | ||
// LOAD event occurred, that is how this function is called | ||
// (no code needed) | ||
|
||
// PAGESHOW event should also occur after load event for this new document | ||
|
||
// The BLUR and FOCUS events happen thanks to this new window | ||
// pulling the action away from the main test page for this interval | ||
|
||
// SCROLL in window | ||
window.scrollBy(2,2); | ||
window.scrollBy(-2,-2);; | ||
|
||
// change hashtags -- this should generate both POPSTATE and HASHCHANGE events | ||
var myAnchor = document.getElementById("second_anchor"); | ||
myAnchor.click(); | ||
myAnchor = document.getElementById("first_anchor"); | ||
myAnchor.click(); | ||
|
||
// send some MESSAGEs | ||
window.postMessage("message for you", "*"); | ||
window.opener.postMessage("message for you", "*"); | ||
|
||
// use STORAGE | ||
localStorage.clear(); | ||
localStorage["key1"] = "value1"; | ||
localStorage["key2"] = "value2"; | ||
localStorage.clear(); | ||
|
||
// cause an ERROR | ||
var myError = document.createEvent("Event"); | ||
myError.initEvent("error", true, false); | ||
document.body.dispatchEvent(myError); | ||
|
||
// closing this window after this function returns should generate | ||
// BEFOREUNLOAD, PAGEHIDE, and UNLOAD events | ||
} | ||
|
||
// run events | ||
window.onload = function() { | ||
runEvents(); | ||
// wait, then close window | ||
step_timeout(window.close, 10000); | ||
} | ||
</script> | ||
<body> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and all other
assert_equals
involvingfuncExpected
are broken because it assumes the function object survives the mirroring, but it does not. The spec for this is https://html.spec.whatwg.org/#window-reflecting-body-element-event-handler-set and from that I found existing tests:https://wpt.fyi/results/html/webappapis/scripting/events/event-handler-attributes-body-window.html?label=experimental
https://wpt.fyi/results/html/webappapis/scripting/events/event-handler-attributes-window-body.html?label=experimental
https://wpt.fyi/results/html/webappapis/scripting/events/event-handler-attributes-windowless-body.html?label=experimental
I'll delete this test from the PR and keep reviewing.