diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html')
-rw-r--r-- | dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html b/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html new file mode 100644 index 000000000..9db9afbf4 --- /dev/null +++ b/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html @@ -0,0 +1,402 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=783129 +--> +<head> + <title>Test for document.registerElement lifecycle callback</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a> +<div id="container"> + <x-hello id="hello"></x-hello> + <button id="extbutton" is="x-button"></button> +</div> +<script> + +var container = document.getElementById("container"); + +// Tests callbacks after registering element type that is already in the document. +// create element in document -> register -> remove from document +function testRegisterUnresolved() { + var helloElem = document.getElementById("hello"); + + var createdCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; + + var p = Object.create(HTMLElement.prototype); + p.createdCallback = function() { + is(helloElem.__proto__, p, "Prototype should be adjusted just prior to invoking the created callback."); + is(createdCallbackCalled, false, "Created callback should only be called once in this tests."); + is(this, helloElem, "The 'this' value should be the custom element."); + createdCallbackCalled = true; + }; + + p.attachedCallback = function() { + is(createdCallbackCalled, true, "Created callback should be called before attached"); + is(attachedCallbackCalled, false, "attached callback should only be called once in this test."); + is(this, helloElem, "The 'this' value should be the custom element."); + attachedCallbackCalled = true; + }; + + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); + detachedCallbackCalled = true; + is(this, helloElem, "The 'this' value should be the custom element."); + runNextTest(); + }; + + p.attributeChangedCallback = function(name, oldValue, newValue) { + ok(false, "attributeChanged callback should never be called in this test."); + }; + + document.registerElement("x-hello", { prototype: p }); + is(createdCallbackCalled, true, "created callback should be called when control returns to script from user agent code"); + + // Remove element from document to trigger detached callback. + container.removeChild(helloElem); +} + +// Tests callbacks after registering an extended element type that is already in the document. +// create element in document -> register -> remove from document +function testRegisterUnresolvedExtended() { + var buttonElem = document.getElementById("extbutton"); + + var createdCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; + + var p = Object.create(HTMLButtonElement.prototype); + p.createdCallback = function() { + is(buttonElem.__proto__, p, "Prototype should be adjusted just prior to invoking the created callback."); + is(createdCallbackCalled, false, "Created callback should only be called once in this tests."); + is(this, buttonElem, "The 'this' value should be the custom element."); + createdCallbackCalled = true; + }; + + p.attachedCallback = function() { + is(createdCallbackCalled, true, "Created callback should be called before attached"); + is(attachedCallbackCalled, false, "attached callback should only be called once in this test."); + is(this, buttonElem, "The 'this' value should be the custom element."); + attachedCallbackCalled = true; + }; + + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); + detachedCallbackCalled = true; + is(this, buttonElem, "The 'this' value should be the custom element."); + runNextTest(); + }; + + p.attributeChangedCallback = function(name, oldValue, newValue) { + ok(false, "attributeChanged callback should never be called in this test."); + }; + + document.registerElement("x-button", { prototype: p, extends: "button" }); + is(createdCallbackCalled, true, "created callback should be called when control returns to script from user agent code"); + + // Remove element from document to trigger detached callback. + container.removeChild(buttonElem); +} + +function testInnerHTML() { + var createdCallbackCalled = false; + + var p = Object.create(HTMLElement.prototype); + p.createdCallback = function() { + is(createdCallbackCalled, false, "created callback should only be called once in this test."); + createdCallbackCalled = true; + }; + + document.registerElement("x-inner-html", { prototype: p }); + var div = document.createElement(div); + div.innerHTML = '<x-inner-html></x-inner-html>'; + is(createdCallbackCalled, true, "created callback should be called after setting innerHTML."); + runNextTest(); +} + +function testInnerHTMLExtended() { + var createdCallbackCalled = false; + + var p = Object.create(HTMLButtonElement.prototype); + p.createdCallback = function() { + is(createdCallbackCalled, false, "created callback should only be called once in this test."); + createdCallbackCalled = true; + }; + + document.registerElement("x-inner-html-extended", { prototype: p, extends: "button" }); + var div = document.createElement(div); + div.innerHTML = '<button is="x-inner-html-extended"></button>'; + is(createdCallbackCalled, true, "created callback should be called after setting innerHTML."); + runNextTest(); +} + +function testInnerHTMLUpgrade() { + var createdCallbackCalled = false; + + var div = document.createElement(div); + div.innerHTML = '<x-inner-html-upgrade></x-inner-html-upgrade>'; + + var p = Object.create(HTMLElement.prototype); + p.createdCallback = function() { + is(createdCallbackCalled, false, "created callback should only be called once in this test."); + createdCallbackCalled = true; + }; + + document.registerElement("x-inner-html-upgrade", { prototype: p }); + is(createdCallbackCalled, true, "created callback should be called after registering."); + runNextTest(); +} + +function testInnerHTMLExtendedUpgrade() { + var createdCallbackCalled = false; + + var div = document.createElement(div); + div.innerHTML = '<button is="x-inner-html-extended-upgrade"></button>'; + + var p = Object.create(HTMLButtonElement.prototype); + p.createdCallback = function() { + is(createdCallbackCalled, false, "created callback should only be called once in this test."); + createdCallbackCalled = true; + }; + + document.registerElement("x-inner-html-extended-upgrade", { prototype: p, extends: "button" }); + is(createdCallbackCalled, true, "created callback should be called after registering."); + runNextTest(); +} + +// Test callback when creating element after registering an element type. +// register -> create element -> insert into document -> remove from document +function testRegisterResolved() { + var createdCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; + + var createdCallbackThis; + + var p = Object.create(HTMLElement.prototype); + p.createdCallback = function() { + is(createdCallbackCalled, false, "Created callback should only be called once in this test."); + createdCallbackThis = this; + createdCallbackCalled = true; + }; + + p.attachedCallback = function() { + is(createdCallbackCalled, true, "created callback should be called before attached callback."); + is(attachedCallbackCalled, false, "attached callback should only be called on in this test."); + is(this, createdElement, "The 'this' value should be the custom element."); + attachedCallbackCalled = true; + }; + + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); + is(this, createdElement, "The 'this' value should be the custom element."); + detachedCallbackCalled = true; + runNextTest(); + }; + + p.attributeChangedCallback = function() { + ok(false, "attributeChanged callback should never be called in this test."); + }; + + document.registerElement("x-resolved", { prototype: p }); + is(createdCallbackCalled, false, "Created callback should not be called when custom element instance has not been created."); + + var createdElement = document.createElement("x-resolved"); + is(createdCallbackThis, createdElement, "The 'this' value in the created callback should be the custom element."); + is(createdElement.__proto__, p, "Prototype of custom element should be the registered prototype."); + + // Insert element into document to trigger attached callback. + container.appendChild(createdElement); + + // Remove element from document to trigger detached callback. + container.removeChild(createdElement); +} + +// Callbacks should always be the same ones when registered. +function testChangingCallback() { + var p = Object.create(HTMLElement.prototype); + var callbackCalled = false; + p.attributeChangedCallback = function(name, oldValue, newValue) { + is(callbackCalled, false, "Callback should only be called once in this test."); + callbackCalled = true; + runNextTest(); + }; + + document.registerElement("x-test-callback", { prototype: p }); + + p.attributeChangedCallback = function(name, oldValue, newValue) { + ok(false, "Only callbacks at registration should be called."); + }; + + var elem = document.createElement("x-test-callback"); + elem.setAttribute("foo", "bar"); +} + +function testAttributeChanged() { + var createdCallbackCalled = false; + + var createdElement; + var createdCallbackThis; + + var p = Object.create(HTMLElement.prototype); + p.createdCallback = function() { + is(createdCallbackCalled, false, "Created callback should only be called once in this test."); + createdCallbackThis = this; + createdCallbackCalled = true; + }; + + // Sequence of callback arguments that we expect from attribute changed callback + // after changing attributes values in a specific order. + var expectedCallbackArguments = [ + // [oldValue, newValue] + [null, "newvalue"], // Setting the attribute value to "newvalue" + ["newvalue", "nextvalue"], // Changing the attribute value from "newvalue" to "nextvalue" + ["nextvalue", ""], // Changing the attribute value from "nextvalue" to empty string + ["", null], // Removing the attribute. + ]; + + p.attributeChangedCallback = function(name, oldValue, newValue) { + is(createdCallbackCalled, true, "created callback should be called before attribute changed."); + is(this, createdElement, "The 'this' value should be the custom element."); + ok(expectedCallbackArguments.length > 0, "Attribute changed callback should not be called more than expected."); + + is(name, "changeme", "name arugment in attribute changed callback should be the name of the changed attribute."); + + var expectedArgs = expectedCallbackArguments.shift(); + is(oldValue, expectedArgs[0], "The old value argument should match the expected value."); + is(newValue, expectedArgs[1], "The new value argument should match the expected value."); + + if (expectedCallbackArguments.length === 0) { + // Done with the attribute changed callback test. + runNextTest(); + } + }; + + document.registerElement("x-attrchange", { prototype: p }); + + var createdElement = document.createElement("x-attrchange"); + is(createdCallbackThis, createdElement, "The 'this' value in the created callback should be the custom element."); + createdElement.setAttribute("changeme", "newvalue"); + createdElement.setAttribute("changeme", "nextvalue"); + createdElement.setAttribute("changeme", ""); + createdElement.removeAttribute("changeme"); +} + +function testAttributeChangedExtended() { + var p = Object.create(HTMLButtonElement.prototype); + var callbackCalled = false; + p.attributeChangedCallback = function(name, oldValue, newValue) { + is(callbackCalled, false, "Callback should only be called once in this test."); + callbackCalled = true; + runNextTest(); + }; + + document.registerElement("x-extended-attribute-change", { prototype: p, extends: "button" }); + + var elem = document.createElement("button", {is: "x-extended-attribute-change"}); + elem.setAttribute("foo", "bar"); +} + +// Creates a custom element that is an upgrade candidate (no registration) +// and mutate the element in ways that would call callbacks for registered +// elements. +function testUpgradeCandidate() { + var createdElement = document.createElement("x-upgrade-candidate"); + container.appendChild(createdElement); + createdElement.setAttribute("foo", "bar"); + container.removeChild(createdElement); + ok(true, "Nothing bad should happen when trying to mutating upgrade candidates."); + runNextTest(); +} + +function testNotInDocEnterLeave() { + var p = Object.create(HTMLElement.prototype); + + p.attached = function() { + ok(false, "attached should not be called when not entering the document."); + }; + + p.detached = function() { + ok(false, "leaveView should not be called when not leaving the document."); + }; + + var createdElement = document.createElement("x-destined-for-fragment"); + + document.registerElement("x-destined-for-fragment", { prototype: p }); + + var fragment = new DocumentFragment(); + fragment.appendChild(createdElement); + fragment.removeChild(createdElement); + + var divNotInDoc = document.createElement("div"); + divNotInDoc.appendChild(createdElement); + divNotInDoc.removeChild(createdElement); + + runNextTest(); +} + +function testEnterLeaveView() { + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; + + var p = Object.create(HTMLElement.prototype); + p.attachedCallback = function() { + is(attachedCallbackCalled, false, "attached callback should only be called on in this test."); + attachedCallbackCalled = true; + }; + + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); + detachedCallbackCalled = true; + runNextTest(); + }; + + var div = document.createElement("div"); + document.registerElement("x-element-in-div", { prototype: p }); + var customElement = document.createElement("x-element-in-div"); + div.appendChild(customElement); + is(attachedCallbackCalled, false, "Appending a custom element to a node that is not in the document should not call the attached callback."); + + container.appendChild(div); + container.removeChild(div); +} + +var testFunctions = [ + testRegisterUnresolved, + testRegisterUnresolvedExtended, + testInnerHTML, + testInnerHTMLExtended, + testInnerHTMLUpgrade, + testInnerHTMLExtendedUpgrade, + testRegisterResolved, + testAttributeChanged, + testAttributeChangedExtended, + testUpgradeCandidate, + testChangingCallback, + testNotInDocEnterLeave, + testEnterLeaveView, + SimpleTest.finish +]; + +function runNextTest() { + if (testFunctions.length > 0) { + var nextTestFunction = testFunctions.shift(); + nextTestFunction(); + } +} + +SimpleTest.waitForExplicitFinish(); + +runNextTest(); + +</script> +</body> +</html> |