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 |