OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library entered_left_view_test; | 5 library entered_left_view_test; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:html'; | 8 import 'dart:html'; |
9 import 'dart:js' as js; | 9 import 'dart:js' as js; |
10 import 'package:unittest/html_individual_config.dart'; | 10 import 'package:unittest/html_individual_config.dart'; |
11 import 'package:unittest/unittest.dart'; | 11 import 'package:unittest/unittest.dart'; |
12 import '../utils.dart'; | 12 import '../utils.dart'; |
13 | 13 |
14 var invocations = []; | 14 var invocations = []; |
| 15 |
15 class Foo extends HtmlElement { | 16 class Foo extends HtmlElement { |
16 factory Foo() => null; | 17 factory Foo() => null; |
17 Foo.created() : super.created() { | 18 Foo.created() : super.created() { |
18 invocations.add('created'); | 19 invocations.add('created'); |
19 } | 20 } |
20 | 21 |
21 void attached() { | 22 void attached() { |
22 invocations.add('attached'); | 23 invocations.add('attached'); |
23 } | 24 } |
24 | 25 |
25 void enteredView() { | 26 void enteredView() { |
26 // Deprecated name. Should never be called since we override "attached". | 27 // Deprecated name. Should never be called since we override "attached". |
27 invocations.add('enteredView'); | 28 invocations.add('enteredView'); |
28 } | 29 } |
29 | 30 |
30 void detached() { | 31 void detached() { |
31 invocations.add('detached'); | 32 invocations.add('detached'); |
32 } | 33 } |
33 | 34 |
34 void leftView() { | 35 void leftView() { |
35 // Deprecated name. Should never be called since we override "detached". | 36 // Deprecated name. Should never be called since we override "detached". |
36 invocations.add('leftView'); | 37 invocations.add('leftView'); |
37 } | 38 } |
38 | 39 |
39 void attributeChanged(String name, String oldValue, String newValue) { | 40 void attributeChanged(String name, String oldValue, String newValue) { |
40 invocations.add('attribute changed'); | 41 invocations.add('attribute changed'); |
41 } | 42 } |
42 } | 43 } |
43 | 44 |
44 | |
45 // Test that the deprecated callbacks still work. | 45 // Test that the deprecated callbacks still work. |
46 class FooOldCallbacks extends HtmlElement { | 46 class FooOldCallbacks extends HtmlElement { |
47 factory FooOldCallbacks() => null; | 47 factory FooOldCallbacks() => null; |
48 FooOldCallbacks.created() : super.created() { | 48 FooOldCallbacks.created() : super.created() { |
49 invocations.add('created'); | 49 invocations.add('created'); |
50 } | 50 } |
51 | 51 |
52 void enteredView() { | 52 void enteredView() { |
53 invocations.add('enteredView'); | 53 invocations.add('enteredView'); |
54 } | 54 } |
(...skipping 13 matching lines...) Expand all Loading... |
68 // Adapted from Blink's | 68 // Adapted from Blink's |
69 // fast/dom/custom/attached-detached-document.html test. | 69 // fast/dom/custom/attached-detached-document.html test. |
70 | 70 |
71 var docA = document; | 71 var docA = document; |
72 var docB = document.implementation.createHtmlDocument(''); | 72 var docB = document.implementation.createHtmlDocument(''); |
73 | 73 |
74 var nullSanitizer = new NullTreeSanitizer(); | 74 var nullSanitizer = new NullTreeSanitizer(); |
75 | 75 |
76 var registeredTypes = false; | 76 var registeredTypes = false; |
77 setUp(() => customElementsReady.then((_) { | 77 setUp(() => customElementsReady.then((_) { |
78 if (registeredTypes) return; | 78 if (registeredTypes) return; |
79 registeredTypes = true; | 79 registeredTypes = true; |
80 document.registerElement('x-a', Foo); | 80 document.registerElement('x-a', Foo); |
81 document.registerElement('x-a-old', FooOldCallbacks); | 81 document.registerElement('x-a-old', FooOldCallbacks); |
82 })); | 82 })); |
83 | 83 |
84 group('standard_events', () { | 84 group('standard_events', () { |
85 var a; | 85 var a; |
86 setUp(() { | 86 setUp(() { |
87 invocations = []; | 87 invocations = []; |
88 }); | 88 }); |
89 | 89 |
90 test('Created', () { | 90 test('Created', () { |
91 a = new Element.tag('x-a'); | 91 a = new Element.tag('x-a'); |
92 expect(invocations, ['created']); | 92 expect(invocations, ['created']); |
(...skipping 24 matching lines...) Expand all Loading... |
117 expect(invocations, ['attached']); | 117 expect(invocations, ['attached']); |
118 }); | 118 }); |
119 | 119 |
120 test('nested leaving triggers detached', () { | 120 test('nested leaving triggers detached', () { |
121 div.remove(); | 121 div.remove(); |
122 customElementsTakeRecords(); | 122 customElementsTakeRecords(); |
123 expect(invocations, ['detached']); | 123 expect(invocations, ['detached']); |
124 }); | 124 }); |
125 }); | 125 }); |
126 | 126 |
127 | |
128 // TODO(jmesserly): remove after deprecation period. | 127 // TODO(jmesserly): remove after deprecation period. |
129 group('standard_events_old_callback_names', () { | 128 group('standard_events_old_callback_names', () { |
130 var a; | 129 var a; |
131 setUp(() { | 130 setUp(() { |
132 invocations = []; | 131 invocations = []; |
133 }); | 132 }); |
134 | 133 |
135 test('Created', () { | 134 test('Created', () { |
136 a = new Element.tag('x-a-old'); | 135 a = new Element.tag('x-a-old'); |
137 expect(invocations, ['created']); | 136 expect(invocations, ['created']); |
(...skipping 24 matching lines...) Expand all Loading... |
162 expect(invocations, ['enteredView']); | 161 expect(invocations, ['enteredView']); |
163 }); | 162 }); |
164 | 163 |
165 test('nested leaving triggers leftView', () { | 164 test('nested leaving triggers leftView', () { |
166 div.remove(); | 165 div.remove(); |
167 customElementsTakeRecords(); | 166 customElementsTakeRecords(); |
168 expect(invocations, ['leftView']); | 167 expect(invocations, ['leftView']); |
169 }); | 168 }); |
170 }); | 169 }); |
171 | 170 |
172 | |
173 group('viewless_document', () { | 171 group('viewless_document', () { |
174 var a; | 172 var a; |
175 setUp(() { | 173 setUp(() { |
176 invocations = []; | 174 invocations = []; |
177 }); | 175 }); |
178 | 176 |
179 test('Created, owned by a document without a view', () { | 177 test('Created, owned by a document without a view', () { |
180 a = docB.createElement('x-a'); | 178 a = docB.createElement('x-a'); |
181 expect(a.ownerDocument, docB, | 179 expect(a.ownerDocument, docB, |
182 reason:'new instance should be owned by the document the definition ' | 180 reason: 'new instance should be owned by the document the definition ' |
183 'was registered with'); | 181 'was registered with'); |
184 expect(invocations, ['created'], | 182 expect(invocations, ['created'], |
185 reason: 'calling the constructor should invoke the created callback'); | 183 reason: 'calling the constructor should invoke the created callback'); |
186 }); | 184 }); |
187 | 185 |
188 test('Entered document without a view', () { | 186 test('Entered document without a view', () { |
189 docB.body.append(a); | 187 docB.body.append(a); |
190 expect(invocations, [], | 188 expect(invocations, [], |
191 reason: 'attached callback should not be invoked when entering a ' | 189 reason: 'attached callback should not be invoked when entering a ' |
192 'document without a view'); | 190 'document without a view'); |
193 }); | 191 }); |
194 | 192 |
195 test('Attribute changed in document without a view', () { | 193 test('Attribute changed in document without a view', () { |
196 a.setAttribute('data-foo', 'bar'); | 194 a.setAttribute('data-foo', 'bar'); |
197 expect(invocations, ['attribute changed'], | 195 expect(invocations, ['attribute changed'], |
198 reason: 'changing an attribute should invoke the callback, even in a ' | 196 reason: 'changing an attribute should invoke the callback, even in a ' |
199 'document without a view'); | 197 'document without a view'); |
200 }); | 198 }); |
201 | 199 |
202 test('Entered document with a view', () { | 200 test('Entered document with a view', () { |
203 document.body.append(a); | 201 document.body.append(a); |
204 customElementsTakeRecords(); | 202 customElementsTakeRecords(); |
205 expect(invocations, ['attached'], | 203 expect(invocations, ['attached'], |
206 reason: 'attached callback should be invoked when entering a document
' | 204 reason: |
207 'with a view'); | 205 'attached callback should be invoked when entering a document ' |
| 206 'with a view'); |
208 }); | 207 }); |
209 | 208 |
210 test('Left document with a view', () { | 209 test('Left document with a view', () { |
211 a.remove(); | 210 a.remove(); |
212 customElementsTakeRecords(); | 211 customElementsTakeRecords(); |
213 expect(invocations, ['detached'], | 212 expect(invocations, ['detached'], |
214 reason: 'detached callback should be invoked when leaving a document ' | 213 reason: 'detached callback should be invoked when leaving a document ' |
215 'with a view'); | 214 'with a view'); |
216 }); | 215 }); |
217 | 216 |
218 test('Created in a document without a view', () { | 217 test('Created in a document without a view', () { |
219 docB.body.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); | 218 docB.body.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); |
220 upgradeCustomElements(docB.body); | 219 upgradeCustomElements(docB.body); |
221 | 220 |
222 expect(invocations, ['created'], | 221 expect(invocations, ['created'], |
223 reason: 'only created callback should be invoked when parsing a ' | 222 reason: 'only created callback should be invoked when parsing a ' |
224 'custom element in a document without a view'); | 223 'custom element in a document without a view'); |
225 }); | 224 }); |
226 }); | 225 }); |
227 | 226 |
228 group('shadow_dom', () { | 227 group('shadow_dom', () { |
229 var div; | 228 var div; |
230 var s; | 229 var s; |
231 setUp(() { | 230 setUp(() { |
232 invocations = []; | 231 invocations = []; |
233 div = new DivElement(); | 232 div = new DivElement(); |
234 s = div.createShadowRoot(); | 233 s = div.createShadowRoot(); |
235 }); | 234 }); |
236 | 235 |
237 tearDown(() { | 236 tearDown(() { |
238 customElementsTakeRecords(); | 237 customElementsTakeRecords(); |
239 }); | 238 }); |
240 | 239 |
241 test('Created in Shadow DOM that is not in a document', () { | 240 test('Created in Shadow DOM that is not in a document', () { |
242 s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); | 241 s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); |
243 upgradeCustomElements(s); | 242 upgradeCustomElements(s); |
244 | 243 |
245 expect(invocations, ['created'], | 244 expect(invocations, ['created'], |
246 reason: 'the attached callback should not be invoked when entering a ' | 245 reason: 'the attached callback should not be invoked when entering a ' |
247 'Shadow DOM subtree not in the document'); | 246 'Shadow DOM subtree not in the document'); |
248 }); | 247 }); |
249 | 248 |
250 test('Leaves Shadow DOM that is not in a document', () { | 249 test('Leaves Shadow DOM that is not in a document', () { |
251 s.innerHtml = ''; | 250 s.innerHtml = ''; |
252 expect(invocations, [], | 251 expect(invocations, [], |
253 reason: 'the detached callback should not be invoked when leaving a ' | 252 reason: 'the detached callback should not be invoked when leaving a ' |
254 'Shadow DOM subtree not in the document'); | 253 'Shadow DOM subtree not in the document'); |
255 }); | 254 }); |
256 | 255 |
257 test('Enters a document with a view as a constituent of Shadow DOM', () { | 256 test('Enters a document with a view as a constituent of Shadow DOM', () { |
258 s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); | 257 s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); |
259 upgradeCustomElements(s); | 258 upgradeCustomElements(s); |
260 | 259 |
261 document.body.append(div); | 260 document.body.append(div); |
262 customElementsTakeRecords(); | 261 customElementsTakeRecords(); |
263 expect(invocations, ['created', 'attached'], | 262 expect(invocations, ['created', 'attached'], |
264 reason: 'the attached callback should be invoked when inserted into
' | 263 reason: 'the attached callback should be invoked when inserted into ' |
265 'a document with a view as part of Shadow DOM'); | 264 'a document with a view as part of Shadow DOM'); |
266 | 265 |
267 div.remove(); | 266 div.remove(); |
268 customElementsTakeRecords(); | 267 customElementsTakeRecords(); |
269 | 268 |
270 expect(invocations, ['created', 'attached', 'detached'], | 269 expect(invocations, ['created', 'attached', 'detached'], |
271 reason: 'the detached callback should be invoked when removed from a ' | 270 reason: 'the detached callback should be invoked when removed from a ' |
272 'document with a view as part of Shadow DOM'); | 271 'document with a view as part of Shadow DOM'); |
273 }); | 272 }); |
274 }); | 273 }); |
275 | 274 |
276 | |
277 group('disconnected_subtree', () { | 275 group('disconnected_subtree', () { |
278 var div = new DivElement(); | 276 var div = new DivElement(); |
279 | 277 |
280 setUp(() { | 278 setUp(() { |
281 invocations = []; | 279 invocations = []; |
282 }); | 280 }); |
283 | 281 |
284 test('Enters a disconnected subtree of DOM', () { | 282 test('Enters a disconnected subtree of DOM', () { |
285 div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); | 283 div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); |
286 upgradeCustomElements(div); | 284 upgradeCustomElements(div); |
287 | 285 |
288 expect(invocations, ['created'], | 286 expect(invocations, ['created'], |
289 reason: 'the attached callback should not be invoked when inserted ' | 287 reason: 'the attached callback should not be invoked when inserted ' |
290 'into a disconnected subtree'); | 288 'into a disconnected subtree'); |
291 }); | 289 }); |
292 | 290 |
293 test('Leaves a disconnected subtree of DOM', () { | 291 test('Leaves a disconnected subtree of DOM', () { |
294 div.innerHtml = ''; | 292 div.innerHtml = ''; |
295 expect(invocations, [], | 293 expect(invocations, [], |
296 reason: 'the detached callback should not be invoked when removed from
a ' | 294 reason: |
297 'disconnected subtree'); | 295 'the detached callback should not be invoked when removed from a ' |
| 296 'disconnected subtree'); |
298 }); | 297 }); |
299 | 298 |
300 test('Enters a document with a view as a constituent of a subtree', () { | 299 test('Enters a document with a view as a constituent of a subtree', () { |
301 div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); | 300 div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); |
302 upgradeCustomElements(div); | 301 upgradeCustomElements(div); |
303 invocations = []; | 302 invocations = []; |
304 document.body.append(div); | 303 document.body.append(div); |
305 customElementsTakeRecords(); | 304 customElementsTakeRecords(); |
306 expect(invocations, ['attached'], | 305 expect(invocations, ['attached'], |
307 reason: 'the attached callback should be invoked when inserted into a
' | 306 reason: |
308 'document with a view as part of a subtree'); | 307 'the attached callback should be invoked when inserted into a ' |
| 308 'document with a view as part of a subtree'); |
309 }); | 309 }); |
310 }); | 310 }); |
311 } | 311 } |
OLD | NEW |