Skip to content
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

Closed
wants to merge 12 commits into from
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 + ":");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}, 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">
Copy link
Member

Choose a reason for hiding this comment

The 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>
Loading