Skip to content

Commit

Permalink
Add tests for the document promises
Browse files Browse the repository at this point in the history
Introduced in whatwg/html#1936.
  • Loading branch information
domenic committed Nov 4, 2016
1 parent a99ba66 commit 8cffc77
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Support document to load in an iframe</title>
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>document.interactive, document.contentLoaded, and document.loaded with document.open()</title>
<link rel="author" title="Domenic Denicola" href="mailto:[email protected]">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-interactive">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-contentloaded">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-loaded">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<iframe src="document-promises-with-document-open-support.html"></iframe>

<script>
"use strict";

const loadPromise = new Promise(resolve => window.onload = resolve);

function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

promise_test(() => {
let contentDoc, interactiveBefore, contentLoadedBefore, loadedBefore;
const fulfilled = [];

return loadPromise.then(() => {
contentDoc = frames[0].document;

interactiveBefore = contentDoc.interactive;
contentLoadedBefore = contentDoc.contentLoaded;
loadedBefore = contentDoc.loaded;

// Sanity check: they all work
return Promise.all([interactiveBefore, contentLoadedBefore, loadedBefore]);
})
.then(() => {
contentDoc.open();

assert_equals(contentDoc.readyState, "loading", "After document.open(), readyState must be loading");

assert_not_equals(contentDoc.interactive, interactiveBefore, "document.open() must reset document.interactive");
assert_not_equals(contentDoc.contentLoaded, contentLoadedBefore,
"document.open() must reset document.contentLoaded");
assert_not_equals(contentDoc.loaded, loadedBefore, "document.open() must reset document.loaded");

contentDoc.interactive.then(() => {
fulfilled.push("interactive");
});
contentDoc.contentLoaded.then(() => {
fulfilled.push("contentLoaded");
});
contentDoc.loaded.then(() => {
fulfilled.push("loaded");
});

return delay(10);
})
.then(() => {
assert_array_equals(fulfilled, [], "None of the promises should be fulfilled 10 ms after document.open()");

contentDoc.close();

return Promise.all([contentDoc.interactive, contentDoc.contentLoaded, contentDoc.loaded]);
});
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>document.interactive, document.contentLoaded, and document.loaded</title>
<link rel="author" title="Domenic Denicola" href="mailto:[email protected]">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-interactive">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-contentloaded">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-loaded">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
"use strict";

let onDomContentLoadedFired = false;
let onLoadFired = false;

let interactiveFulfilled = false;
let contentLoadedFulfilled = false;
let loadedFulfilled = false;

let interactiveAssertions, contentLoadedAssertions, loadedAssertions;

test(() => {
document.addEventListener("DOMContentLoaded", () => {
onDomContentLoadedFired = true;
});

window.addEventListener("load", () => {
onLoadFired = true;
});

// A note on timing:
// The event handler function must execute before the promise fulfillment callback does, because the sequence goes:
// - UA code resolves the promise, thus enqueuing a microtask to call the onFulfilled
// - UA code fires an event
// - Eventually this uses Web IDL to invoke the callback
// (https://heycam.github.io/webidl/#call-a-user-objects-operation)
// - *After* the callback runs, we perform a microtask checkpoint
// - The microtask checkpoint calls onFulfilled

interactiveAssertions = document.interactive.then(value => {
interactiveFulfilled = true;

assert_equals(value, undefined, "The document.interactive promise must fulfill with undefined");
assert_equals(document.readyState, "interactive",
"Inside the document.interactive fulfillment handler, readyState must be interactive");
});

contentLoadedAssertions = document.contentLoaded.then(value => {
contentLoadedFulfilled = true;

assert_equals(value, undefined, "The document.contentLoaded promise must fulfill with undefined");
assert_equals(document.readyState, "interactive",
"Inside the document.contentLoaded fulfillment handler, readyState must be interactive");
assert_equals(interactiveFulfilled, true,
"Inside the document.contentLoaded fulfillment handler, document.interactive must have already fulfilled");
assert_equals(onDomContentLoadedFired, true,
"Inside the document.contentLoaded fulfillment handler, DOMContentLoaded must have already fired");
});

loadedAssertions = document.loaded.then(value => {
loadedFulfilled = true;

assert_equals(value, undefined, "The document.loaded promise must fulfill with undefined");
assert_equals(document.readyState, "complete",
"Inside the document.loaded fulfillment handler, readyState must be complete");
assert_equals(interactiveFulfilled, true,
"Inside the document.loaded fulfillment handler, document.interactive must have already fulfilled");
assert_equals(contentLoadedFulfilled, true,
"Inside the document.loaded fulfillment handler, document.contentLoaded must have already fulfilled");
assert_equals(onDomContentLoadedFired, true,
"Inside the document.loaded fulfillment handler, DOMContentLoaded must have already fired");
assert_equals(onLoadFired, true,
"Inside the document.loaded fulfillment handler, load must have already fired");
});
}, "Setup code");

promise_test(() => interactiveAssertions, "document.interactive");
promise_test(() => contentLoadedAssertions, "document.contentLoaded");
promise_test(() => loadedAssertions, "document.loaded");
</script>
9 changes: 6 additions & 3 deletions html/dom/interfaces.html
Original file line number Diff line number Diff line change
Expand Up @@ -915,14 +915,17 @@ <h1>HTML IDL tests</h1>
typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;

[OverrideBuiltins]
partial /*sealed*/ interface Document {
partial interface Document {
// resource metadata management
[PutForwards=href, Unforgeable] readonly attribute Location? location;
attribute USVString domain;
attribute USVString domain;
readonly attribute USVString referrer;
attribute USVString cookie;
attribute USVString cookie;
readonly attribute DOMString lastModified;
readonly attribute DocumentReadyState readyState;
[Unscopable] readonly attribute Promise<void> interactive;
[Unscopable] readonly attribute Promise<void> contentLoaded;
[Unscopable] readonly attribute Promise<void> loaded;

// DOM tree accessors
getter object (DOMString name);
Expand Down

0 comments on commit 8cffc77

Please sign in to comment.