| OLD | NEW |
| 1 | 1 |
| 2 let testNumber = 1; | 2 let testNumber = 1; |
| 3 | 3 |
| 4 function defineNewCustomElement(observedAttributes) { | |
| 5 let log = []; | |
| 6 let name = 'custom-element-' + testNumber++; | |
| 7 | |
| 8 class CustomElement extends HTMLElement { | |
| 9 constructor() { | |
| 10 super(); | |
| 11 log.push({type: 'constructed', element: this}); | |
| 12 } | |
| 13 attributeChangedCallback(name, oldValue, newValue, namespace) { | |
| 14 log.push({type: 'attributeChanged', element: this, name: name, oldVa
lue: oldValue, newValue: newValue, namespace: namespace}); | |
| 15 } | |
| 16 connectedCallback() { log.push({type: 'connected', element: this}); } | |
| 17 disconnectedCallback() { log.push({type: 'disconnected', element: this})
; } | |
| 18 adoptedCallback(oldDocument, newDocument) { log.push({type: 'adopted', e
lement: this, oldDocument: oldDocument, newDocument: newDocument}); } | |
| 19 } | |
| 20 CustomElement.observedAttributes = observedAttributes || ['id', 'title']; | |
| 21 | |
| 22 customElements.define(name, CustomElement); | |
| 23 | |
| 24 return { | |
| 25 name: name, | |
| 26 log: function () { | |
| 27 let currentLog = log; log = []; | |
| 28 return { | |
| 29 types: () => currentLog.map((entry) => entry.type), | |
| 30 log: (i) => currentLog[i == undefined ? currentLog.length - 1 :
i], | |
| 31 } | |
| 32 } | |
| 33 }; | |
| 34 } | |
| 35 | |
| 36 function testNodeConnector(testFunction, name) { | 4 function testNodeConnector(testFunction, name) { |
| 37 let container = document.createElement('div'); | 5 let container = document.createElement('div'); |
| 38 container.appendChild(document.createElement('div')); | 6 container.appendChild(document.createElement('div')); |
| 39 document.body.appendChild(container); | 7 document.body.appendChild(container); |
| 40 | 8 |
| 41 test(function () { | 9 test(function () { |
| 42 var element = defineNewCustomElement(); | 10 var element = define_new_custom_element(); |
| 43 var instance = document.createElement(element.name); | 11 var instance = document.createElement(element.name); |
| 44 assert_array_equals(element.log().types(), ['constructed']); | 12 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 45 testFunction(container, instance); | 13 testFunction(container, instance); |
| 46 assert_array_equals(element.log().types(), ['connected']); | 14 assert_array_equals(element.takeLog().types(), ['connected']); |
| 47 }, name + ' must enqueue a connected reaction'); | 15 }, name + ' must enqueue a connected reaction'); |
| 48 | 16 |
| 49 test(function () { | 17 test(function () { |
| 50 var element = defineNewCustomElement(); | 18 var element = define_new_custom_element(); |
| 51 var instance = document.createElement(element.name); | 19 var instance = document.createElement(element.name); |
| 52 assert_array_equals(element.log().types(), ['constructed']); | 20 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 53 var newDoc = document.implementation.createHTMLDocument(); | 21 var newDoc = document.implementation.createHTMLDocument(); |
| 54 testFunction(container, instance); | 22 testFunction(container, instance); |
| 55 assert_array_equals(element.log().types(), ['connected']); | 23 assert_array_equals(element.takeLog().types(), ['connected']); |
| 56 testFunction(newDoc.documentElement, instance); | 24 testFunction(newDoc.documentElement, instance); |
| 57 assert_array_equals(element.log().types(), ['disconnected', 'adopted', '
connected']); | 25 assert_array_equals(element.takeLog().types(), ['disconnected', 'adopted
', 'connected']); |
| 58 }, name + ' must enqueue a disconnected reaction, an adopted reaction, and a
connected reaction when the custom element was in another document'); | 26 }, name + ' must enqueue a disconnected reaction, an adopted reaction, and a
connected reaction when the custom element was in another document'); |
| 59 | 27 |
| 60 container.parentNode.removeChild(container); | 28 container.parentNode.removeChild(container); |
| 61 } | 29 } |
| 62 | 30 |
| 63 function testNodeDisconnector(testFunction, name) { | 31 function testNodeDisconnector(testFunction, name) { |
| 64 let container = document.createElement('div'); | 32 let container = document.createElement('div'); |
| 65 container.appendChild(document.createElement('div')); | 33 container.appendChild(document.createElement('div')); |
| 66 document.body.appendChild(container); | 34 document.body.appendChild(container); |
| 67 | 35 |
| 68 test(function () { | 36 test(function () { |
| 69 var element = defineNewCustomElement(); | 37 var element = define_new_custom_element(); |
| 70 var instance = document.createElement(element.name); | 38 var instance = document.createElement(element.name); |
| 71 assert_array_equals(element.log().types(), ['constructed']); | 39 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 72 container.appendChild(instance); | 40 container.appendChild(instance); |
| 73 assert_array_equals(element.log().types(), ['connected']); | 41 assert_array_equals(element.takeLog().types(), ['connected']); |
| 74 testFunction(instance); | 42 testFunction(instance); |
| 75 assert_array_equals(element.log().types(), ['disconnected']); | 43 assert_array_equals(element.takeLog().types(), ['disconnected']); |
| 76 }, name + ' must enqueue a disconnected reaction'); | 44 }, name + ' must enqueue a disconnected reaction'); |
| 77 | 45 |
| 78 container.parentNode.removeChild(container); | 46 container.parentNode.removeChild(container); |
| 79 } | 47 } |
| 80 | 48 |
| 49 function testCloner(testFunction, name) { |
| 50 let container = document.createElement('div'); |
| 51 container.appendChild(document.createElement('div')); |
| 52 document.body.appendChild(container); |
| 53 |
| 54 test(function () { |
| 55 var element = define_new_custom_element(['id']); |
| 56 var instance = document.createElement(element.name); |
| 57 container.appendChild(instance); |
| 58 |
| 59 instance.setAttribute('id', 'foo'); |
| 60 assert_array_equals(element.takeLog().types(), ['constructed', 'connecte
d', 'attributeChanged']); |
| 61 var newInstance = testFunction(instance); |
| 62 var logEntries = element.takeLog(); |
| 63 assert_array_equals(logEntries.types(), ['constructed', 'attributeChange
d']); |
| 64 assert_attribute_log_entry(logEntries.last(), {name: 'id', oldValue: nul
l, newValue: 'foo', namespace: null}); |
| 65 }, name + ' must enqueue an attributeChanged reaction when cloning an elemen
t with an observed attribute'); |
| 66 |
| 67 test(function () { |
| 68 var element = define_new_custom_element(['id']); |
| 69 var instance = document.createElement(element.name); |
| 70 container.appendChild(instance); |
| 71 |
| 72 instance.setAttribute('lang', 'en'); |
| 73 assert_array_equals(element.takeLog().types(), ['constructed', 'connecte
d']); |
| 74 var newInstance = testFunction(instance); |
| 75 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 76 }, name + ' must not enqueue an attributeChanged reaction when cloning an el
ement with an unobserved attribute'); |
| 77 |
| 78 test(function () { |
| 79 var element = define_new_custom_element(['title', 'class']); |
| 80 var instance = document.createElement(element.name); |
| 81 container.appendChild(instance); |
| 82 |
| 83 instance.setAttribute('lang', 'en'); |
| 84 instance.className = 'foo'; |
| 85 instance.setAttribute('title', 'hello world'); |
| 86 assert_array_equals(element.takeLog().types(), ['constructed', 'connecte
d', 'attributeChanged', 'attributeChanged']); |
| 87 var newInstance = testFunction(instance); |
| 88 var logEntries = element.takeLog(); |
| 89 assert_array_equals(logEntries.types(), ['constructed', 'attributeChange
d', 'attributeChanged']); |
| 90 assert_attribute_log_entry(logEntries[1], {name: 'class', oldValue: null
, newValue: 'foo', namespace: null}); |
| 91 assert_attribute_log_entry(logEntries[2], {name: 'title', oldValue: null
, newValue: 'hello world', namespace: null}); |
| 92 }, name + ' must enqueue an attributeChanged reaction when cloning an elemen
t only for observed attributes'); |
| 93 } |
| 94 |
| 81 function testReflectAttribute(jsAttributeName, contentAttributeName, validValue1
, validValue2, name) { | 95 function testReflectAttribute(jsAttributeName, contentAttributeName, validValue1
, validValue2, name) { |
| 82 test(function () { | 96 test(function () { |
| 83 var element = defineNewCustomElement([contentAttributeName]); | 97 var element = define_new_custom_element([contentAttributeName]); |
| 84 var instance = document.createElement(element.name); | 98 var instance = document.createElement(element.name); |
| 85 assert_array_equals(element.log().types(), ['constructed']); | 99 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 86 instance[jsAttributeName] = validValue1; | 100 instance[jsAttributeName] = validValue1; |
| 87 var logEntries = element.log(); | 101 var logEntries = element.takeLog(); |
| 88 assert_array_equals(logEntries.types(), ['attributeChanged']); | 102 assert_array_equals(logEntries.types(), ['attributeChanged']); |
| 89 assert_equals(logEntries.log().name, contentAttributeName); | 103 assert_attribute_log_entry(logEntries.last(), {name: contentAttributeNam
e, oldValue: null, newValue: validValue1, namespace: null}); |
| 90 assert_equals(logEntries.log().oldValue, null); | 104 }, name + ' must enqueue an attributeChanged reaction when adding ' + conten
tAttributeName + ' content attribute'); |
| 91 assert_equals(logEntries.log().newValue, validValue1); | |
| 92 assert_equals(logEntries.log().namespace, null); | |
| 93 }, name + ' must enqueue a attributeChanged reaction when adding ' + content
AttributeName + ' content attribute'); | |
| 94 | 105 |
| 95 test(function () { | 106 test(function () { |
| 96 var element = defineNewCustomElement([contentAttributeName]); | 107 var element = define_new_custom_element([contentAttributeName]); |
| 97 var instance = document.createElement(element.name); | 108 var instance = document.createElement(element.name); |
| 98 instance[jsAttributeName] = validValue1; | 109 instance[jsAttributeName] = validValue1; |
| 99 assert_array_equals(element.log().types(), ['constructed', 'attributeCha
nged']); | 110 assert_array_equals(element.takeLog().types(), ['constructed', 'attribut
eChanged']); |
| 100 instance[jsAttributeName] = validValue2; | 111 instance[jsAttributeName] = validValue2; |
| 101 var logEntries = element.log(); | 112 var logEntries = element.takeLog(); |
| 102 assert_array_equals(logEntries.types(), ['attributeChanged']); | 113 assert_array_equals(logEntries.types(), ['attributeChanged']); |
| 103 assert_equals(logEntries.log().name, contentAttributeName); | 114 assert_attribute_log_entry(logEntries.last(), {name: contentAttributeNam
e, oldValue: validValue1, newValue: validValue2, namespace: null}); |
| 104 assert_equals(logEntries.log().oldValue, validValue1); | 115 }, name + ' must enqueue an attributeChanged reaction when replacing an exis
ting attribute'); |
| 105 assert_equals(logEntries.log().newValue, validValue2); | |
| 106 assert_equals(logEntries.log().namespace, null); | |
| 107 }, name + ' must enqueue a attributeChanged reaction when replacing an exist
ing attribute'); | |
| 108 } | 116 } |
| 109 | 117 |
| 110 function testAttributeAdder(testFunction, name) { | 118 function testAttributeAdder(testFunction, name) { |
| 111 test(function () { | 119 test(function () { |
| 112 var element = defineNewCustomElement(); | 120 var element = define_new_custom_element(['id']); |
| 113 var instance = document.createElement(element.name); | 121 var instance = document.createElement(element.name); |
| 114 assert_array_equals(element.log().types(), ['constructed']); | 122 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 115 testFunction(instance, 'id', 'foo'); | 123 testFunction(instance, 'id', 'foo'); |
| 116 var logEntries = element.log(); | 124 var logEntries = element.takeLog(); |
| 117 assert_array_equals(logEntries.types(), ['attributeChanged']); | 125 assert_array_equals(logEntries.types(), ['attributeChanged']); |
| 118 assert_equals(logEntries.log().name, 'id'); | 126 assert_attribute_log_entry(logEntries.last(), {name: 'id', oldValue: nul
l, newValue: 'foo', namespace: null}); |
| 119 assert_equals(logEntries.log().oldValue, null); | 127 }, name + ' must enqueue an attributeChanged reaction when adding an attribu
te'); |
| 120 assert_equals(logEntries.log().newValue, 'foo'); | |
| 121 assert_equals(logEntries.log().namespace, null); | |
| 122 }, name + ' must enqueue a attributeChanged reaction when adding an attribut
e'); | |
| 123 | 128 |
| 124 test(function () { | 129 test(function () { |
| 125 var element = defineNewCustomElement(); | 130 var element = define_new_custom_element(['class']); |
| 126 var instance = document.createElement(element.name); | 131 var instance = document.createElement(element.name); |
| 127 assert_array_equals(element.log().types(), ['constructed']); | 132 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 128 testFunction(instance, 'data-lang', 'en'); | 133 testFunction(instance, 'data-lang', 'en'); |
| 129 assert_array_equals(element.log().types(), []); | 134 assert_array_equals(element.takeLog().types(), []); |
| 130 }, name + ' must not enqueue a attributeChanged reaction when adding an unob
served attribute'); | 135 }, name + ' must not enqueue an attributeChanged reaction when adding an uno
bserved attribute'); |
| 131 | 136 |
| 132 test(function () { | 137 test(function () { |
| 133 var element = defineNewCustomElement(); | 138 var element = define_new_custom_element(['title']); |
| 134 var instance = document.createElement(element.name); | 139 var instance = document.createElement(element.name); |
| 135 instance.setAttribute('title', 'hello'); | 140 instance.setAttribute('title', 'hello'); |
| 136 assert_array_equals(element.log().types(), ['constructed', 'attributeCha
nged']); | 141 assert_array_equals(element.takeLog().types(), ['constructed', 'attribut
eChanged']); |
| 137 testFunction(instance, 'title', 'world'); | 142 testFunction(instance, 'title', 'world'); |
| 138 var logEntries = element.log(); | 143 var logEntries = element.takeLog(); |
| 139 assert_array_equals(logEntries.types(), ['attributeChanged']); | 144 assert_array_equals(logEntries.types(), ['attributeChanged']); |
| 140 assert_equals(logEntries.log().name, 'title'); | 145 assert_attribute_log_entry(logEntries.last(), {name: 'title', oldValue:
'hello', newValue: 'world', namespace: null}); |
| 141 assert_equals(logEntries.log().oldValue, 'hello'); | 146 }, name + ' must enqueue an attributeChanged reaction when replacing an exis
ting attribute'); |
| 142 assert_equals(logEntries.log().newValue, 'world'); | |
| 143 assert_equals(logEntries.log().namespace, null); | |
| 144 }, name + ' must enqueue a attributeChanged reaction when replacing an exist
ing attribute'); | |
| 145 | 147 |
| 146 test(function () { | 148 test(function () { |
| 147 var element = defineNewCustomElement(); | 149 var element = define_new_custom_element([]); |
| 148 var instance = document.createElement(element.name); | 150 var instance = document.createElement(element.name); |
| 149 instance.setAttribute('data-lang', 'zh'); | 151 instance.setAttribute('data-lang', 'zh'); |
| 150 assert_array_equals(element.log().types(), ['constructed']); | 152 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 151 testFunction(instance, 'data-lang', 'en'); | 153 testFunction(instance, 'data-lang', 'en'); |
| 152 assert_array_equals(element.log().types(), []); | 154 assert_array_equals(element.takeLog().types(), []); |
| 153 }, name + ' must enqueue a attributeChanged reaction when replacing an exist
ing unobserved attribute'); | 155 }, name + ' must enqueue an attributeChanged reaction when replacing an exis
ting unobserved attribute'); |
| 154 } | 156 } |
| 155 | 157 |
| 156 function testAttributeMutator(testFunction, name) { | 158 function testAttributeMutator(testFunction, name) { |
| 157 test(function () { | 159 test(function () { |
| 158 var element = defineNewCustomElement(); | 160 var element = define_new_custom_element(['title']); |
| 159 var instance = document.createElement(element.name); | 161 var instance = document.createElement(element.name); |
| 160 instance.setAttribute('title', 'hello'); | 162 instance.setAttribute('title', 'hello'); |
| 161 assert_array_equals(element.log().types(), ['constructed', 'attributeCha
nged']); | 163 assert_array_equals(element.takeLog().types(), ['constructed', 'attribut
eChanged']); |
| 162 testFunction(instance, 'title', 'world'); | 164 testFunction(instance, 'title', 'world'); |
| 163 var logEntries = element.log(); | 165 var logEntries = element.takeLog(); |
| 164 assert_array_equals(logEntries.types(), ['attributeChanged']); | 166 assert_array_equals(logEntries.types(), ['attributeChanged']); |
| 165 assert_equals(logEntries.log().name, 'title'); | 167 assert_attribute_log_entry(logEntries.last(), {name: 'title', oldValue:
'hello', newValue: 'world', namespace: null}); |
| 166 assert_equals(logEntries.log().oldValue, 'hello'); | 168 }, name + ' must enqueue an attributeChanged reaction when replacing an exis
ting attribute'); |
| 167 assert_equals(logEntries.log().newValue, 'world'); | |
| 168 assert_equals(logEntries.log().namespace, null); | |
| 169 }, name + ' must enqueue a attributeChanged reaction when replacing an exist
ing attribute'); | |
| 170 | 169 |
| 171 test(function () { | 170 test(function () { |
| 172 var element = defineNewCustomElement(); | 171 var element = define_new_custom_element(['class']); |
| 173 var instance = document.createElement(element.name); | 172 var instance = document.createElement(element.name); |
| 174 instance.setAttribute('data-lang', 'zh'); | 173 instance.setAttribute('data-lang', 'zh'); |
| 175 assert_array_equals(element.log().types(), ['constructed']); | 174 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 176 testFunction(instance, 'data-lang', 'en'); | 175 testFunction(instance, 'data-lang', 'en'); |
| 177 assert_array_equals(element.log().types(), []); | 176 assert_array_equals(element.takeLog().types(), []); |
| 178 }, name + ' must enqueue a attributeChanged reaction when replacing an exist
ing unobserved attribute'); | 177 }, name + ' must not enqueue an attributeChanged reaction when replacing an
existing unobserved attribute'); |
| 179 } | 178 } |
| 180 | 179 |
| 181 function testAttributeRemover(testFunction, name) { | 180 function testAttributeRemover(testFunction, name) { |
| 182 test(function () { | 181 test(function () { |
| 183 var element = defineNewCustomElement(); | 182 var element = define_new_custom_element(['title']); |
| 184 var instance = document.createElement(element.name); | 183 var instance = document.createElement(element.name); |
| 185 assert_array_equals(element.log().types(), ['constructed']); | 184 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 186 testFunction(instance, 'title'); | 185 testFunction(instance, 'title'); |
| 187 assert_array_equals(element.log().types(), []); | 186 assert_array_equals(element.takeLog().types(), []); |
| 188 }, name + ' must not enqueue a attributeChanged reaction when removing an at
tribute that does not exist'); | 187 }, name + ' must not enqueue an attributeChanged reaction when removing an a
ttribute that does not exist'); |
| 189 | 188 |
| 190 test(function () { | 189 test(function () { |
| 191 var element = defineNewCustomElement(); | 190 var element = define_new_custom_element([]); |
| 192 var instance = document.createElement(element.name); | 191 var instance = document.createElement(element.name); |
| 193 instance.setAttribute('data-lang', 'hello'); | 192 instance.setAttribute('data-lang', 'hello'); |
| 194 assert_array_equals(element.log().types(), ['constructed']); | 193 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 195 testFunction(instance, 'data-lang'); | 194 testFunction(instance, 'data-lang'); |
| 196 assert_array_equals(element.log().types(), []); | 195 assert_array_equals(element.takeLog().types(), []); |
| 197 }, name + ' must not enqueue a attributeChanged reaction when removing an un
observed attribute that does not exist'); | 196 }, name + ' must not enqueue an attributeChanged reaction when removing an u
nobserved attribute'); |
| 198 | 197 |
| 199 test(function () { | 198 test(function () { |
| 200 var element = defineNewCustomElement(); | 199 var element = define_new_custom_element(['title']); |
| 201 var instance = document.createElement(element.name); | 200 var instance = document.createElement(element.name); |
| 202 instance.setAttribute('title', 'hello'); | 201 instance.setAttribute('title', 'hello'); |
| 203 assert_array_equals(element.log().types(), ['constructed', 'attributeCha
nged']); | 202 assert_array_equals(element.takeLog().types(), ['constructed', 'attribut
eChanged']); |
| 204 testFunction(instance, 'title'); | 203 testFunction(instance, 'title'); |
| 205 var logEntries = element.log(); | 204 var logEntries = element.takeLog(); |
| 206 assert_array_equals(logEntries.types(), ['attributeChanged']); | 205 assert_array_equals(logEntries.types(), ['attributeChanged']); |
| 207 assert_equals(logEntries.log().name, 'title'); | 206 assert_attribute_log_entry(logEntries.last(), {name: 'title', oldValue:
'hello', newValue: null, namespace: null}); |
| 208 assert_equals(logEntries.log().oldValue, 'hello'); | 207 }, name + ' must enqueue an attributeChanged reaction when removing an exist
ing attribute'); |
| 209 assert_equals(logEntries.log().newValue, null); | |
| 210 assert_equals(logEntries.log().namespace, null); | |
| 211 }, name + ' must enqueue a attributeChanged reaction when removing an existi
ng attribute'); | |
| 212 | 208 |
| 213 test(function () { | 209 test(function () { |
| 214 var element = defineNewCustomElement(); | 210 var element = define_new_custom_element([]); |
| 215 var instance = document.createElement(element.name); | 211 var instance = document.createElement(element.name); |
| 216 instance.setAttribute('data-lang', 'ja'); | 212 instance.setAttribute('data-lang', 'ja'); |
| 217 assert_array_equals(element.log().types(), ['constructed']); | 213 assert_array_equals(element.takeLog().types(), ['constructed']); |
| 218 testFunction(instance, 'data-lang'); | 214 testFunction(instance, 'data-lang'); |
| 219 assert_array_equals(element.log().types(), []); | 215 assert_array_equals(element.takeLog().types(), []); |
| 220 }, name + ' must not enqueue a attributeChanged reaction when removing an ex
isting unobserved attribute'); | 216 }, name + ' must not enqueue an attributeChanged reaction when removing an e
xisting unobserved attribute'); |
| 221 } | 217 } |
| OLD | NEW |