test_custom_element_set_element_creation_callback.html (6793B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=1460815 5 --> 6 <head> 7 <title>Test for customElements.setElementCreationCallback</title> 8 <script src="/tests/SimpleTest/SimpleTest.js"></script> 9 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 10 </head> 11 <body> 12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1460815">Bug 1460815</a> 13 <div> 14 </div> 15 16 <script> 17 18 let registry = SpecialPowers.wrap(customElements); 19 20 function simpleTest() { 21 let callbackCalled = false; 22 class XObjElement extends HTMLElement {}; 23 registry.setElementCreationCallback("x-html-obj-elem", (type) => { 24 if (callbackCalled) { 25 ok(false, "Callback should not be invoked more than once."); 26 } 27 callbackCalled = true; 28 is(type, "x-html-obj-elem", "Type is passed to the callback."); 29 customElements.define("x-html-obj-elem", XObjElement); 30 }); 31 ok(!callbackCalled, "Callback should not be called."); 32 let el = document.createElement("x-html-obj-elem"); 33 ok(callbackCalled, "Callback should be called."); 34 is(Object.getPrototypeOf(el), XObjElement.prototype, "Created element should have the prototype of the custom type."); 35 } 36 37 function multipleDefinitionTest() { 38 let callbackCalled = false; 39 class XObjElement1 extends HTMLElement {}; 40 class XObjElement2 extends HTMLElement {}; 41 let callback = (type) => { 42 if (callbackCalled) { 43 ok(false, "Callback should not be invoked more than once."); 44 } 45 callbackCalled = true; 46 is(type, "x-html-obj-elem1", "Type is passed to the callback."); 47 customElements.define("x-html-obj-elem1", XObjElement1); 48 customElements.define("x-html-obj-elem2", XObjElement2); 49 }; 50 registry.setElementCreationCallback("x-html-obj-elem1", callback); 51 registry.setElementCreationCallback("x-html-obj-elem2", callback); 52 ok(!callbackCalled, "Callback should not be called."); 53 let el1 = document.createElement("x-html-obj-elem1"); 54 ok(callbackCalled, "Callback should be called."); 55 is(Object.getPrototypeOf(el1), XObjElement1.prototype, "Created element should have the prototype of the custom type."); 56 let el2 = document.createElement("x-html-obj-elem2"); 57 is(Object.getPrototypeOf(el2), XObjElement2.prototype, "Created element should have the prototype of the custom type."); 58 } 59 60 function throwIfDefined() { 61 let callbackCalled = false; 62 class XObjElement3 extends HTMLElement {}; 63 customElements.define("x-html-obj-elem3", XObjElement3); 64 try { 65 registry.setElementCreationCallback( 66 "x-html-obj-elem3", () => callbackCalled = true); 67 } catch (e) { 68 ok(true, "Set a callback on defined type should throw."); 69 } 70 ok(!callbackCalled, "Callback should not be called."); 71 } 72 73 function throwIfSetTwice() { 74 let callbackCalled = false; 75 registry.setElementCreationCallback( 76 "x-html-obj-elem4", () => callbackCalled = true); 77 try { 78 registry.setElementCreationCallback( 79 "x-html-obj-elem4", () => callbackCalled = true); 80 } catch (e) { 81 ok(true, "Callack shouldn't be set twice on the same type."); 82 } 83 ok(!callbackCalled, "Callback should not be called."); 84 } 85 86 function simpleExtendedTest() { 87 let callbackCalled = false; 88 class ExtendButton extends HTMLButtonElement {}; 89 registry.setElementCreationCallback("x-extended-button", (type) => { 90 if (callbackCalled) { 91 ok(false, "Callback should not be invoked more than once."); 92 } 93 callbackCalled = true; 94 customElements.define("x-extended-button", ExtendButton, { extends: "button" }); 95 is(type, "x-extended-button", "Type is passed to the callback."); 96 }); 97 ok(!callbackCalled, "Callback should not be called."); 98 let el = document.createElement("button", { is: "x-extended-button"}); 99 ok(callbackCalled, "Callback should be called."); 100 is(Object.getPrototypeOf(el), ExtendButton.prototype, "Created element should have the prototype of the extended type."); 101 is(el.getAttribute("is"), null, "The |is| attribute of the created element should not be the extended type."); 102 } 103 104 function simpleInnerHTMLTest() { 105 let callbackCalled = false; 106 class XObjElement4 extends HTMLElement {}; 107 registry.setElementCreationCallback("x-html-obj-elem5", (type) => { 108 if (callbackCalled) { 109 ok(false, "Callback should not be invoked more than once."); 110 } 111 callbackCalled = true; 112 is(type, "x-html-obj-elem5", "Type is passed to the callback."); 113 customElements.define("x-html-obj-elem5", XObjElement4); 114 }); 115 ok(!callbackCalled, "Callback should not be called."); 116 let p = document.createElement("p"); 117 p.innerHTML = "<x-html-obj-elem5></x-html-obj-elem5>"; 118 let el = p.firstChild; 119 ok(callbackCalled, "Callback should be called."); 120 is(Object.getPrototypeOf(el), XObjElement4.prototype, "Created element should have the prototype of the custom type."); 121 } 122 123 function twoElementInnerHTMLTest() { 124 let callbackCalled = false; 125 class XObjElement5 extends HTMLElement {}; 126 registry.setElementCreationCallback("x-html-obj-elem6", (type) => { 127 if (callbackCalled) { 128 ok(false, "Callback should not be invoked more than once."); 129 } 130 callbackCalled = true; 131 is(type, "x-html-obj-elem6", "Type is passed to the callback."); 132 customElements.define("x-html-obj-elem6", XObjElement5); 133 }); 134 ok(!callbackCalled, "Callback should not be called."); 135 let p = document.createElement("p"); 136 p.innerHTML = 137 "<x-html-obj-elem6></x-html-obj-elem6><x-html-obj-elem6></x-html-obj-elem6>"; 138 let el1 = p.firstChild; 139 let el2 = p.lastChild; 140 ok(callbackCalled, "Callback should be called."); 141 is(Object.getPrototypeOf(el1), XObjElement5.prototype, "Created element should have the prototype of the custom type."); 142 is(Object.getPrototypeOf(el2), XObjElement5.prototype, "Created element should have the prototype of the custom type."); 143 } 144 145 function setElementCreationCallbackUpgradesExistingTest() { 146 class UpdradeDuringSetCallback extends HTMLElement {} 147 let p = document.createElement("p"); 148 p.innerHTML = "<upgrade-during-set-callback></upgrade-during-set-callback>"; 149 document.body.append(p); 150 151 let element = p.firstChild; 152 ok(!(element instanceof UpdradeDuringSetCallback), "Element defined before type is not upgraded"); 153 154 registry.setElementCreationCallback( 155 "upgrade-during-set-callback", 156 () => customElements.define("upgrade-during-set-callback", UpdradeDuringSetCallback) 157 ); 158 ok(element instanceof UpdradeDuringSetCallback, "setElementCreationCallback called automatically to upgrade candidate component"); 159 p.remove(); 160 } 161 162 function startTest() { 163 simpleTest(); 164 multipleDefinitionTest(); 165 throwIfDefined(); 166 throwIfSetTwice(); 167 simpleExtendedTest(); 168 simpleInnerHTMLTest(); 169 twoElementInnerHTMLTest(); 170 setElementCreationCallbackUpgradesExistingTest(); 171 } 172 173 startTest(); 174 175 </script> 176 </body> 177 </html>