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 created_callback_test; | 5 library created_callback_test; |
6 import 'package:unittest/unittest.dart'; | 6 import 'package:unittest/unittest.dart'; |
7 import 'package:unittest/html_config.dart'; | 7 import 'package:unittest/html_config.dart'; |
8 import 'dart:html'; | 8 import 'dart:html'; |
9 import '../utils.dart'; | 9 import '../utils.dart'; |
10 | 10 |
11 class A extends HtmlElement { | 11 class A extends HtmlElement { |
12 static final tag = 'x-a'; | 12 static final tag = 'x-a'; |
13 factory A() => new Element.tag(tag); | 13 factory A() => new Element.tag(tag); |
| 14 A.created(): super.created(); |
14 | 15 |
15 static int createdInvocations = 0; | 16 static int createdInvocations = 0; |
16 | 17 |
17 void created() { | 18 void createdCallback() { |
18 createdInvocations++; | 19 createdInvocations++; |
19 } | 20 } |
20 } | 21 } |
21 | 22 |
22 class B extends HtmlElement { | 23 class B extends HtmlElement { |
23 static final tag = 'x-b'; | 24 static final tag = 'x-b'; |
24 factory B() => new Element.tag(tag); | 25 factory B() => new Element.tag(tag); |
| 26 B.created(): super.created(); |
25 } | 27 } |
26 | 28 |
27 class C extends HtmlElement { | 29 class C extends HtmlElement { |
28 static final tag = 'x-c'; | 30 static final tag = 'x-c'; |
29 factory C() => new Element.tag(tag); | 31 factory C() => new Element.tag(tag); |
| 32 C.created(): super.created(); |
30 | 33 |
31 static int createdInvocations = 0; | 34 static int createdInvocations = 0; |
32 static var div; | 35 static var div; |
33 | 36 |
34 void created() { | 37 void createdCallback() { |
35 createdInvocations++; | 38 createdInvocations++; |
36 | 39 |
37 if (this.id != 'u') { | 40 if (this.id != 'u') { |
38 return; | 41 return; |
39 } | 42 } |
40 | 43 |
41 var t = div.query('#t'); | 44 var t = div.query('#t'); |
42 var v = div.query('#v'); | 45 var v = div.query('#v'); |
43 var w = div.query('#w'); | 46 var w = div.query('#w'); |
44 | 47 |
45 expect(query('x-b:not(:unresolved)'), this); | 48 expect(query('x-b:not(:unresolved)'), this); |
46 expect(queryAll(':unresolved'), [v, w]); | 49 expect(queryAll(':unresolved'), [v, w]); |
47 | 50 |
48 // As per: | 51 // As per: |
49 // http://www.w3.org/TR/2013/WD-custom-elements-20130514/#serializing-and-pa
rsing | 52 // http://www.w3.org/TR/2013/WD-custom-elements-20130514/#serializing-and-pa
rsing |
50 // creation order is t, u, v, w (postorder). | 53 // creation order is t, u, v, w (postorder). |
51 expect(t is C, isTrue); | 54 expect(t is C, isTrue); |
52 // Note, this is different from JavaScript where this would be false. | 55 // Note, this is different from JavaScript where this would be false. |
53 expect(v is C, isTrue); | 56 expect(v is C, isTrue); |
54 } | 57 } |
55 } | 58 } |
56 | 59 |
57 main() { | 60 main() { |
58 useHtmlConfiguration(); | 61 useHtmlConfiguration(); |
59 | 62 |
60 // Adapted from Blink's | 63 // Adapted from Blink's |
61 // fast/dom/custom/created-callback test. | 64 // fast/dom/custom/created-callback test. |
62 | 65 |
63 setUp(loadPolyfills); | 66 var registered = false; |
| 67 setUp(() { |
| 68 return loadPolyfills().then((_) { |
| 69 if (!registered) { |
| 70 registered = true; |
| 71 document.register(B.tag, B); |
| 72 document.register(C.tag, C); |
| 73 ErrorConstructorElement.register(); |
| 74 } |
| 75 }); |
| 76 }); |
64 | 77 |
65 test('transfer created callback', () { | 78 test('transfer created callback', () { |
66 document.register(A.tag, A); | 79 document.register(A.tag, A); |
67 var x = new A(); | 80 var x = new A(); |
68 expect(A.createdInvocations, 1); | 81 expect(A.createdInvocations, 1); |
69 }); | 82 }); |
70 | 83 |
71 test(':unresolved and created callback timing', () { | 84 test('unresolved and created callback timing', () { |
72 document.register(B.tag, B); | |
73 document.register(C.tag, C); | |
74 | |
75 var div = new DivElement(); | 85 var div = new DivElement(); |
76 C.div = div; | 86 C.div = div; |
77 div.setInnerHtml(""" | 87 div.setInnerHtml(""" |
78 <x-c id="t"></x-c> | 88 <x-c id="t"></x-c> |
79 <x-b id="u"></x-b> | 89 <x-b id="u"></x-b> |
80 <x-c id="v"></x-c> | 90 <x-c id="v"></x-c> |
81 <x-b id="w"></x-b> | 91 <x-b id="w"></x-b> |
82 """, treeSanitizer: new NullTreeSanitizer()); | 92 """, treeSanitizer: new NullTreeSanitizer()); |
83 | 93 |
84 Platform.upgradeCustomElements(div); | 94 Platform.upgradeCustomElements(div); |
85 | 95 |
86 expect(C.createdInvocations, 2); | 96 expect(C.createdInvocations, 2); |
87 expect(div.query('#w') is B, isTrue); | 97 expect(div.query('#w') is B, isTrue); |
88 }); | 98 }); |
89 | 99 |
| 100 test('nesting of constructors', NestedElement.test); |
| 101 |
| 102 test('access while upgrading gets unupgraded element', |
| 103 AccessWhileUpgradingElement.test); |
| 104 |
| 105 test('cannot call created constructor', () { |
| 106 expect(() { |
| 107 new B.created(); |
| 108 }, throws); |
| 109 }); |
| 110 |
| 111 test('cannot register without created', () { |
| 112 expect(() { |
| 113 document.register(MissingCreatedElement.tag, MissingCreatedElement); |
| 114 }, throws); |
| 115 }); |
| 116 |
| 117 test('throw on createElement does not upgrade', () { |
| 118 ErrorConstructorElement.callCount = 0; |
| 119 |
| 120 var e = new Element.tag(ErrorConstructorElement.tag); |
| 121 expect(ErrorConstructorElement.callCount, 1); |
| 122 expect(e is HtmlElement, isTrue); |
| 123 expect(e is ErrorConstructorElement, isFalse); |
| 124 |
| 125 var dummy = new DivElement(); |
| 126 dummy.append(e); |
| 127 e = dummy.firstChild; |
| 128 expect(ErrorConstructorElement.callCount, 1); |
| 129 }); |
| 130 |
| 131 test('throw on innerHtml does not upgrade', () { |
| 132 ErrorConstructorElement.callCount = 0; |
| 133 |
| 134 var dummy = new DivElement(); |
| 135 var tag = ErrorConstructorElement.tag; |
| 136 dummy.setInnerHtml('<$tag></$tag>', |
| 137 treeSanitizer: new NullTreeSanitizer()); |
| 138 |
| 139 expect(ErrorConstructorElement.callCount, 1); |
| 140 |
| 141 var e = dummy.firstChild; |
| 142 // Accessing should not re-run the constructor. |
| 143 expect(ErrorConstructorElement.callCount, 1); |
| 144 expect(e is HtmlElement, isTrue); |
| 145 expect(e is ErrorConstructorElement, isFalse); |
| 146 }); |
| 147 |
| 148 |
90 // TODO(vsm): Port additional test from upstream here: | 149 // TODO(vsm): Port additional test from upstream here: |
91 // http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/dom/custom/crea
ted-callback.html?r1=156141&r2=156185 | 150 // http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/dom/custom/crea
ted-callback.html?r1=156141&r2=156185 |
92 } | 151 } |
| 152 |
| 153 |
| 154 class NestedElement extends HtmlElement { |
| 155 static final tag = 'x-nested'; |
| 156 |
| 157 final Element b = new B(); |
| 158 |
| 159 factory NestedElement() => new Element.tag(tag); |
| 160 NestedElement.created(): super.created(); |
| 161 |
| 162 static void register() { |
| 163 document.register(tag, NestedElement); |
| 164 } |
| 165 |
| 166 static void test() { |
| 167 register(); |
| 168 |
| 169 var e = new NestedElement(); |
| 170 expect(e.b, isNotNull); |
| 171 expect(e.b is B, isTrue); |
| 172 expect(e is NestedElement, isTrue); |
| 173 } |
| 174 } |
| 175 |
| 176 |
| 177 class AccessWhileUpgradingElement extends HtmlElement { |
| 178 static final tag = 'x-access-while-upgrading'; |
| 179 |
| 180 static Element upgradingContext; |
| 181 static Element upgradingContextChild; |
| 182 |
| 183 final foo = runInitializerCode(); |
| 184 |
| 185 factory AccessWhileUpgradingElement() => new Element.tag(tag); |
| 186 AccessWhileUpgradingElement.created(): super.created(); |
| 187 |
| 188 static runInitializerCode() { |
| 189 upgradingContextChild = upgradingContext.firstChild; |
| 190 |
| 191 return 666; |
| 192 } |
| 193 |
| 194 static void register() { |
| 195 document.register(tag, AccessWhileUpgradingElement); |
| 196 } |
| 197 |
| 198 static void test() { |
| 199 register(); |
| 200 |
| 201 upgradingContext = new DivElement(); |
| 202 upgradingContext.setInnerHtml('<$tag></$tag>', |
| 203 treeSanitizer: new NullTreeSanitizer()); |
| 204 var child = upgradingContext.firstChild; |
| 205 |
| 206 expect(child.foo, 666); |
| 207 expect(upgradingContextChild is HTMLElement, isTrue); |
| 208 expect(upgradingContextChild is AccessWhileUpgradingElement, isFalse, |
| 209 reason: 'Elements accessed while upgrading should not be upgraded.'); |
| 210 } |
| 211 } |
| 212 |
| 213 class MissingCreatedElement extends HtmlElement { |
| 214 static final tag = 'x-missing-created'; |
| 215 |
| 216 factory MissingCreatedElement() => new Element.tag(tag); |
| 217 } |
| 218 |
| 219 class ErrorConstructorElement extends HtmlElement { |
| 220 static final tag = 'x-throws-in-constructor'; |
| 221 static int callCount = 0; |
| 222 |
| 223 factory ErrorConstructorElement() => new Element.tag(tag); |
| 224 |
| 225 ErrorConstructorElement.created(): super.created() { |
| 226 print('here!!'); |
| 227 ++callCount; |
| 228 throw new Exception('Just messin with ya'); |
| 229 } |
| 230 |
| 231 static void register() { |
| 232 document.register(tag, ErrorConstructorElement); |
| 233 } |
| 234 } |
OLD | NEW |