| 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 class Foo extends HtmlElement { | 15 class Foo extends HtmlElement { |
| 16 factory Foo() => null; | 16 factory Foo() => null; |
| 17 Foo.created() : super.created() { | 17 Foo.created() : super.created() { |
| 18 invocations.add('created'); | 18 invocations.add('created'); |
| 19 } | 19 } |
| 20 | 20 |
| 21 void attached() { |
| 22 invocations.add('attached'); |
| 23 } |
| 24 |
| 25 void enteredView() { |
| 26 // Deprecated name. Should never be called since we override "attached". |
| 27 invocations.add('enteredView'); |
| 28 } |
| 29 |
| 30 void detached() { |
| 31 invocations.add('detached'); |
| 32 } |
| 33 |
| 34 void leftView() { |
| 35 // Deprecated name. Should never be called since we override "detached". |
| 36 invocations.add('leftView'); |
| 37 } |
| 38 |
| 39 void attributeChanged(String name, String oldValue, String newValue) { |
| 40 invocations.add('attribute changed'); |
| 41 } |
| 42 } |
| 43 |
| 44 |
| 45 // Test that the deprecated callbacks still work. |
| 46 class FooOldCallbacks extends HtmlElement { |
| 47 factory FooOldCallbacks() => null; |
| 48 FooOldCallbacks.created() : super.created() { |
| 49 invocations.add('created'); |
| 50 } |
| 51 |
| 21 void enteredView() { | 52 void enteredView() { |
| 22 invocations.add('entered'); | 53 invocations.add('enteredView'); |
| 23 } | 54 } |
| 24 | 55 |
| 25 void leftView() { | 56 void leftView() { |
| 26 invocations.add('left'); | 57 invocations.add('leftView'); |
| 27 } | 58 } |
| 28 | 59 |
| 29 void attributeChanged(String name, String oldValue, String newValue) { | 60 void attributeChanged(String name, String oldValue, String newValue) { |
| 30 invocations.add('attribute changed'); | 61 invocations.add('attribute changed'); |
| 31 } | 62 } |
| 32 } | 63 } |
| 33 | 64 |
| 34 main() { | 65 main() { |
| 35 useHtmlIndividualConfiguration(); | 66 useHtmlIndividualConfiguration(); |
| 36 | 67 |
| 37 // Adapted from Blink's | 68 // Adapted from Blink's |
| 38 // fast/dom/custom/entered-left-document.html test. | 69 // fast/dom/custom/attached-detached-document.html test. |
| 39 | 70 |
| 40 var docA = document; | 71 var docA = document; |
| 41 var docB = document.implementation.createHtmlDocument(''); | 72 var docB = document.implementation.createHtmlDocument(''); |
| 42 | 73 |
| 43 var nullSanitizer = new NullTreeSanitizer(); | 74 var nullSanitizer = new NullTreeSanitizer(); |
| 44 | 75 |
| 45 var registeredTypes = false; | 76 var registeredTypes = false; |
| 46 setUp(() => customElementsReady.then((_) { | 77 setUp(() => customElementsReady.then((_) { |
| 47 if (registeredTypes) return; | 78 if (registeredTypes) return; |
| 48 registeredTypes = true; | 79 registeredTypes = true; |
| 49 document.register('x-a', Foo); | 80 document.register('x-a', Foo); |
| 81 document.register('x-a-old', FooOldCallbacks); |
| 50 })); | 82 })); |
| 51 | 83 |
| 52 group('standard_events', () { | 84 group('standard_events', () { |
| 53 var a; | 85 var a; |
| 54 setUp(() { | 86 setUp(() { |
| 55 invocations = []; | 87 invocations = []; |
| 56 }); | 88 }); |
| 57 | 89 |
| 58 test('Created', () { | 90 test('Created', () { |
| 59 a = new Element.tag('x-a'); | 91 a = new Element.tag('x-a'); |
| 60 expect(invocations, ['created']); | 92 expect(invocations, ['created']); |
| 61 }); | 93 }); |
| 62 | 94 |
| 63 test('entered', () { | 95 test('attached', () { |
| 64 document.body.append(a); | 96 document.body.append(a); |
| 65 customElementsTakeRecords(); | 97 customElementsTakeRecords(); |
| 66 expect(invocations, ['entered']); | 98 expect(invocations, ['attached']); |
| 67 }); | 99 }); |
| 68 | 100 |
| 69 test('left', () { | 101 test('detached', () { |
| 70 a.remove(); | 102 a.remove(); |
| 71 customElementsTakeRecords(); | 103 customElementsTakeRecords(); |
| 72 expect(invocations, ['left']); | 104 expect(invocations, ['detached']); |
| 73 }); | 105 }); |
| 74 | 106 |
| 75 var div = new DivElement(); | 107 var div = new DivElement(); |
| 76 test('nesting does not trigger entered', () { | 108 test('nesting does not trigger attached', () { |
| 77 div.append(a); | 109 div.append(a); |
| 78 customElementsTakeRecords(); | 110 customElementsTakeRecords(); |
| 79 expect(invocations, []); | 111 expect(invocations, []); |
| 80 }); | 112 }); |
| 81 | 113 |
| 82 test('nested entering triggers entered', () { | 114 test('nested entering triggers attached', () { |
| 83 document.body.append(div); | 115 document.body.append(div); |
| 84 customElementsTakeRecords(); | 116 customElementsTakeRecords(); |
| 85 expect(invocations, ['entered']); | 117 expect(invocations, ['attached']); |
| 86 }); | 118 }); |
| 87 | 119 |
| 88 test('nested leaving triggers left', () { | 120 test('nested leaving triggers detached', () { |
| 89 div.remove(); | 121 div.remove(); |
| 90 customElementsTakeRecords(); | 122 customElementsTakeRecords(); |
| 91 expect(invocations, ['left']); | 123 expect(invocations, ['detached']); |
| 92 }); | 124 }); |
| 93 }); | 125 }); |
| 94 | 126 |
| 127 |
| 128 // TODO(jmesserly): remove after deprecation period. |
| 129 group('standard_events -- old callback names', () { |
| 130 var a; |
| 131 setUp(() { |
| 132 invocations = []; |
| 133 }); |
| 134 |
| 135 test('Created', () { |
| 136 a = new Element.tag('x-a-old'); |
| 137 expect(invocations, ['created']); |
| 138 }); |
| 139 |
| 140 test('enteredView', () { |
| 141 document.body.append(a); |
| 142 customElementsTakeRecords(); |
| 143 expect(invocations, ['enteredView']); |
| 144 }); |
| 145 |
| 146 test('leftView', () { |
| 147 a.remove(); |
| 148 customElementsTakeRecords(); |
| 149 expect(invocations, ['leftView']); |
| 150 }); |
| 151 |
| 152 var div = new DivElement(); |
| 153 test('nesting does not trigger enteredView', () { |
| 154 div.append(a); |
| 155 customElementsTakeRecords(); |
| 156 expect(invocations, []); |
| 157 }); |
| 158 |
| 159 test('nested entering triggers enteredView', () { |
| 160 document.body.append(div); |
| 161 customElementsTakeRecords(); |
| 162 expect(invocations, ['enteredView']); |
| 163 }); |
| 164 |
| 165 test('nested leaving triggers leftView', () { |
| 166 div.remove(); |
| 167 customElementsTakeRecords(); |
| 168 expect(invocations, ['leftView']); |
| 169 }); |
| 170 }); |
| 171 |
| 172 |
| 95 group('viewless_document', () { | 173 group('viewless_document', () { |
| 96 var a; | 174 var a; |
| 97 setUp(() { | 175 setUp(() { |
| 98 invocations = []; | 176 invocations = []; |
| 99 }); | 177 }); |
| 100 | 178 |
| 101 test('Created, owned by a document without a view', () { | 179 test('Created, owned by a document without a view', () { |
| 102 a = docB.createElement('x-a'); | 180 a = docB.createElement('x-a'); |
| 103 expect(a.ownerDocument, docB, | 181 expect(a.ownerDocument, docB, |
| 104 reason:'new instance should be owned by the document the definition ' | 182 reason:'new instance should be owned by the document the definition ' |
| 105 'was registered with'); | 183 'was registered with'); |
| 106 expect(invocations, ['created'], | 184 expect(invocations, ['created'], |
| 107 reason: 'calling the constructor should invoke the created callback'); | 185 reason: 'calling the constructor should invoke the created callback'); |
| 108 }); | 186 }); |
| 109 | 187 |
| 110 test('Entered document without a view', () { | 188 test('Entered document without a view', () { |
| 111 docB.body.append(a); | 189 docB.body.append(a); |
| 112 expect(invocations, [], | 190 expect(invocations, [], |
| 113 reason: 'entered callback should not be invoked when entering a ' | 191 reason: 'attached callback should not be invoked when entering a ' |
| 114 'document without a view'); | 192 'document without a view'); |
| 115 }); | 193 }); |
| 116 | 194 |
| 117 test('Attribute changed in document without a view', () { | 195 test('Attribute changed in document without a view', () { |
| 118 a.setAttribute('data-foo', 'bar'); | 196 a.setAttribute('data-foo', 'bar'); |
| 119 expect(invocations, ['attribute changed'], | 197 expect(invocations, ['attribute changed'], |
| 120 reason: 'changing an attribute should invoke the callback, even in a ' | 198 reason: 'changing an attribute should invoke the callback, even in a ' |
| 121 'document without a view'); | 199 'document without a view'); |
| 122 }); | 200 }); |
| 123 | 201 |
| 124 test('Entered document with a view', () { | 202 test('Entered document with a view', () { |
| 125 document.body.append(a); | 203 document.body.append(a); |
| 126 customElementsTakeRecords(); | 204 customElementsTakeRecords(); |
| 127 expect(invocations, ['entered'], | 205 expect(invocations, ['attached'], |
| 128 reason: 'entered callback should be invoked when entering a document ' | 206 reason: 'attached callback should be invoked when entering a document
' |
| 129 'with a view'); | 207 'with a view'); |
| 130 }); | 208 }); |
| 131 | 209 |
| 132 test('Left document with a view', () { | 210 test('Left document with a view', () { |
| 133 a.remove(); | 211 a.remove(); |
| 134 customElementsTakeRecords(); | 212 customElementsTakeRecords(); |
| 135 expect(invocations, ['left'], | 213 expect(invocations, ['detached'], |
| 136 reason: 'left callback should be invoked when leaving a document ' | 214 reason: 'detached callback should be invoked when leaving a document ' |
| 137 'with a view'); | 215 'with a view'); |
| 138 }); | 216 }); |
| 139 | 217 |
| 140 test('Created in a document without a view', () { | 218 test('Created in a document without a view', () { |
| 141 docB.body.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); | 219 docB.body.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); |
| 142 upgradeCustomElements(docB.body); | 220 upgradeCustomElements(docB.body); |
| 143 | 221 |
| 144 expect(invocations, ['created'], | 222 expect(invocations, ['created'], |
| 145 reason: 'only created callback should be invoked when parsing a ' | 223 reason: 'only created callback should be invoked when parsing a ' |
| 146 'custom element in a document without a view'); | 224 'custom element in a document without a view'); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 158 | 236 |
| 159 tearDown(() { | 237 tearDown(() { |
| 160 customElementsTakeRecords(); | 238 customElementsTakeRecords(); |
| 161 }); | 239 }); |
| 162 | 240 |
| 163 test('Created in Shadow DOM that is not in a document', () { | 241 test('Created in Shadow DOM that is not in a document', () { |
| 164 s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); | 242 s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); |
| 165 upgradeCustomElements(s); | 243 upgradeCustomElements(s); |
| 166 | 244 |
| 167 expect(invocations, ['created'], | 245 expect(invocations, ['created'], |
| 168 reason: 'the entered callback should not be invoked when entering a ' | 246 reason: 'the attached callback should not be invoked when entering a ' |
| 169 'Shadow DOM subtree not in the document'); | 247 'Shadow DOM subtree not in the document'); |
| 170 }); | 248 }); |
| 171 | 249 |
| 172 test('Leaves Shadow DOM that is not in a document', () { | 250 test('Leaves Shadow DOM that is not in a document', () { |
| 173 s.innerHtml = ''; | 251 s.innerHtml = ''; |
| 174 expect(invocations, [], | 252 expect(invocations, [], |
| 175 reason: 'the left callback should not be invoked when leaving a ' | 253 reason: 'the detached callback should not be invoked when leaving a ' |
| 176 'Shadow DOM subtree not in the document'); | 254 'Shadow DOM subtree not in the document'); |
| 177 }); | 255 }); |
| 178 | 256 |
| 179 test('Enters a document with a view as a constituent of Shadow DOM', () { | 257 test('Enters a document with a view as a constituent of Shadow DOM', () { |
| 180 s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); | 258 s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); |
| 181 upgradeCustomElements(s); | 259 upgradeCustomElements(s); |
| 182 | 260 |
| 183 document.body.append(div); | 261 document.body.append(div); |
| 184 customElementsTakeRecords(); | 262 customElementsTakeRecords(); |
| 185 expect(invocations, ['created', 'entered'], | 263 expect(invocations, ['created', 'attached'], |
| 186 reason: 'the entered callback should be invoked when inserted into ' | 264 reason: 'the attached callback should be invoked when inserted into
' |
| 187 'a document with a view as part of Shadow DOM'); | 265 'a document with a view as part of Shadow DOM'); |
| 188 | 266 |
| 189 div.remove(); | 267 div.remove(); |
| 190 customElementsTakeRecords(); | 268 customElementsTakeRecords(); |
| 191 | 269 |
| 192 expect(invocations, ['created', 'entered', 'left'], | 270 expect(invocations, ['created', 'attached', 'detached'], |
| 193 reason: 'the left callback should be invoked when removed from a ' | 271 reason: 'the detached callback should be invoked when removed from a ' |
| 194 'document with a view as part of Shadow DOM'); | 272 'document with a view as part of Shadow DOM'); |
| 195 }); | 273 }); |
| 196 }); | 274 }); |
| 197 | 275 |
| 198 | 276 |
| 199 group('disconnected_subtree', () { | 277 group('disconnected_subtree', () { |
| 200 var div = new DivElement(); | 278 var div = new DivElement(); |
| 201 | 279 |
| 202 setUp(() { | 280 setUp(() { |
| 203 invocations = []; | 281 invocations = []; |
| 204 }); | 282 }); |
| 205 | 283 |
| 206 test('Enters a disconnected subtree of DOM', () { | 284 test('Enters a disconnected subtree of DOM', () { |
| 207 div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); | 285 div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); |
| 208 upgradeCustomElements(div); | 286 upgradeCustomElements(div); |
| 209 | 287 |
| 210 expect(invocations, ['created'], | 288 expect(invocations, ['created'], |
| 211 reason: 'the entered callback should not be invoked when inserted ' | 289 reason: 'the attached callback should not be invoked when inserted ' |
| 212 'into a disconnected subtree'); | 290 'into a disconnected subtree'); |
| 213 }); | 291 }); |
| 214 | 292 |
| 215 test('Leaves a disconnected subtree of DOM', () { | 293 test('Leaves a disconnected subtree of DOM', () { |
| 216 div.innerHtml = ''; | 294 div.innerHtml = ''; |
| 217 expect(invocations, [], | 295 expect(invocations, [], |
| 218 reason: 'the left callback should not be invoked when removed from a ' | 296 reason: 'the detached callback should not be invoked when removed from
a ' |
| 219 'disconnected subtree'); | 297 'disconnected subtree'); |
| 220 }); | 298 }); |
| 221 | 299 |
| 222 test('Enters a document with a view as a constituent of a subtree', () { | 300 test('Enters a document with a view as a constituent of a subtree', () { |
| 223 div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); | 301 div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer); |
| 224 upgradeCustomElements(div); | 302 upgradeCustomElements(div); |
| 225 invocations = []; | 303 invocations = []; |
| 226 document.body.append(div); | 304 document.body.append(div); |
| 227 customElementsTakeRecords(); | 305 customElementsTakeRecords(); |
| 228 expect(invocations, ['entered'], | 306 expect(invocations, ['attached'], |
| 229 reason: 'the entered callback should be invoked when inserted into a ' | 307 reason: 'the attached callback should be invoked when inserted into a
' |
| 230 'document with a view as part of a subtree'); | 308 'document with a view as part of a subtree'); |
| 231 }); | 309 }); |
| 232 }); | 310 }); |
| 233 } | 311 } |
| OLD | NEW |