| 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 |