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 bindings_test; | 5 library bindings_test; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:html'; | 8 import 'dart:html'; |
9 | 9 |
10 import 'package:observe/observe.dart'; | 10 import 'package:observe/observe.dart'; |
11 import 'package:observe/mirrors_used.dart'; // make test smaller. | 11 import 'package:observe/mirrors_used.dart'; // make test smaller. |
12 import 'package:observe/src/dirty_check.dart' show dirtyCheckZone; | 12 import 'package:observe/src/dirty_check.dart' show dirtyCheckZone; |
13 import 'package:polymer_expressions/polymer_expressions.dart'; | 13 import 'package:polymer_expressions/polymer_expressions.dart'; |
14 import 'package:template_binding/template_binding.dart' show templateBind; | 14 import 'package:smoke/mirrors.dart' as smoke; |
| 15 import 'package:template_binding/template_binding.dart' show |
| 16 TemplateBindExtension, templateBind; |
15 import 'package:unittest/html_config.dart'; | 17 import 'package:unittest/html_config.dart'; |
| 18 |
16 import 'package:unittest/unittest.dart'; | 19 import 'package:unittest/unittest.dart'; |
17 | 20 |
18 var testDiv; | 21 var testDiv; |
19 | 22 |
20 main() => dirtyCheckZone().run(() { | 23 main() => dirtyCheckZone().run(() { |
21 useHtmlConfiguration(); | 24 useHtmlConfiguration(); |
22 | 25 |
23 group('bindings', () { | 26 group('bindings', () { |
24 var stop = null; | 27 var stop = null; |
25 setUp(() { | 28 setUp(() { |
(...skipping 11 matching lines...) Expand all Loading... |
37 .prepareBinding('x', null, null)(model, null, false); | 40 .prepareBinding('x', null, null)(model, null, false); |
38 expect(binding.value, isNull); | 41 expect(binding.value, isNull); |
39 model.x = "hi"; | 42 model.x = "hi"; |
40 return new Future(() { | 43 return new Future(() { |
41 expect(binding.value, 'hi'); | 44 expect(binding.value, 'hi'); |
42 }); | 45 }); |
43 }); | 46 }); |
44 | 47 |
45 test('should update text content when data changes', () { | 48 test('should update text content when data changes', () { |
46 var model = new NotifyModel('abcde'); | 49 var model = new NotifyModel('abcde'); |
47 var template = templateBind(new Element.html( | 50 var tag = new Element.html( |
48 '<template><span>{{x}}</span></template>')); | 51 '<template><span>{{x}}</span></template>'); |
| 52 TemplateBindExtension.bootstrap(tag); |
| 53 var template = templateBind(tag); |
49 testDiv.append(template.createInstance(model, new PolymerExpressions())); | 54 testDiv.append(template.createInstance(model, new PolymerExpressions())); |
50 | 55 |
51 var el; | 56 var el; |
52 return new Future(() { | 57 return new Future(() { |
53 el = testDiv.query("span"); | 58 el = testDiv.query("span"); |
54 expect(el.text, 'abcde'); | 59 expect(el.text, 'abcde'); |
55 expect(model.x, 'abcde'); | 60 expect(model.x, 'abcde'); |
56 model.x = '___'; | 61 model.x = '___'; |
57 }).then(_nextMicrotask).then((_) { | 62 }).then(_nextMicrotask).then((_) { |
58 expect(model.x, '___'); | 63 expect(model.x, '___'); |
59 expect(el.text, '___'); | 64 expect(el.text, '___'); |
60 }); | 65 }); |
61 }); | 66 }); |
62 | 67 |
63 test('should log eval exceptions', () { | 68 test('should log eval exceptions', () { |
64 var model = new NotifyModel('abcde'); | 69 var model = new NotifyModel('abcde'); |
65 var completer = new Completer(); | 70 var completer = new Completer(); |
66 runZoned(() { | 71 runZoned(() { |
67 var template = templateBind(new Element.html( | 72 var tag = new Element.html( |
68 '<template><span>{{foo}}</span></template>')); | 73 '<template><span>{{foo}}</span></template>'); |
| 74 TemplateBindExtension.bootstrap(tag); |
| 75 var template = templateBind(tag); |
69 testDiv.append(template.createInstance(model, | 76 testDiv.append(template.createInstance(model, |
70 new PolymerExpressions())); | 77 new PolymerExpressions())); |
71 | 78 |
72 return _nextMicrotask(null); | 79 return _nextMicrotask(null); |
73 }, onError: (e) { | 80 }, onError: (e) { |
74 expect('$e', startsWith("Error evaluating expression 'foo':")); | 81 expect('$e', startsWith("Error evaluating expression 'foo':")); |
75 completer.complete(true); | 82 completer.complete(true); |
76 }); | 83 }); |
77 return completer.future; | 84 return completer.future; |
78 }); | 85 }); |
79 | 86 |
80 test('detects changes to ObservableList', () { | 87 test('detects changes to ObservableList', () { |
81 var list = new ObservableList.from([1, 2, 3]); | 88 var list = new ObservableList.from([1, 2, 3]); |
82 var template = templateBind(new Element.html( | 89 |
83 '<template>{{x[1]}}</template>')); | 90 var tag = new Element.html('<template>{{x[1]}}</template>'); |
| 91 TemplateBindExtension.bootstrap(tag); |
| 92 var template = templateBind(tag); |
| 93 |
84 var model = new NotifyModel(list); | 94 var model = new NotifyModel(list); |
85 testDiv.append(template.createInstance(model, new PolymerExpressions())); | 95 testDiv.append(template.createInstance(model, new PolymerExpressions())); |
86 | 96 |
87 return new Future(() { | 97 return new Future(() { |
88 expect(testDiv.text, '2'); | 98 expect(testDiv.text, '2'); |
89 list[1] = 10; | 99 list[1] = 10; |
90 }).then(_nextMicrotask).then((_) { | 100 }).then(_nextMicrotask).then((_) { |
91 expect(testDiv.text, '10'); | 101 expect(testDiv.text, '10'); |
92 list[1] = 11; | 102 list[1] = 11; |
93 }).then(_nextMicrotask).then((_) { | 103 }).then(_nextMicrotask).then((_) { |
94 expect(testDiv.text, '11'); | 104 expect(testDiv.text, '11'); |
95 list[0] = 9; | 105 list[0] = 9; |
96 }).then(_nextMicrotask).then((_) { | 106 }).then(_nextMicrotask).then((_) { |
97 expect(testDiv.text, '11'); | 107 expect(testDiv.text, '11'); |
98 list.removeAt(0); | 108 list.removeAt(0); |
99 }).then(_nextMicrotask).then((_) { | 109 }).then(_nextMicrotask).then((_) { |
100 expect(testDiv.text, '3'); | 110 expect(testDiv.text, '3'); |
101 list.add(90); | 111 list.add(90); |
102 list.removeAt(0); | 112 list.removeAt(0); |
103 }).then(_nextMicrotask).then((_) { | 113 }).then(_nextMicrotask).then((_) { |
104 expect(testDiv.text, '90'); | 114 expect(testDiv.text, '90'); |
105 }); | 115 }); |
106 }); | 116 }); |
107 | 117 |
108 test('detects changes to ObservableMap keys/values', () { | 118 test('detects changes to ObservableMap keys/values', () { |
109 var map = new ObservableMap.from({'a': 1, 'b': 2}); | 119 var map = new ObservableMap.from({'a': 1, 'b': 2}); |
110 var template = templateBind(new Element.html('<template>' | 120 |
| 121 var tag = new Element.html('<template>' |
111 '<template repeat="{{k in x.keys}}">{{k}}:{{x[k]}},</template>' | 122 '<template repeat="{{k in x.keys}}">{{k}}:{{x[k]}},</template>' |
112 '</template>')); | 123 '</template>'); |
| 124 TemplateBindExtension.bootstrap(tag); |
| 125 var template = templateBind(tag); |
| 126 |
113 var model = new NotifyModel(map); | 127 var model = new NotifyModel(map); |
114 testDiv.append(template.createInstance(model, new PolymerExpressions())); | 128 testDiv.append(template.createInstance(model, new PolymerExpressions())); |
115 | 129 |
116 return new Future(() { | 130 return new Future(() { |
117 expect(testDiv.text, 'a:1,b:2,'); | 131 expect(testDiv.text, 'a:1,b:2,'); |
118 map.remove('b'); | 132 map.remove('b'); |
119 map['c'] = 3; | 133 map['c'] = 3; |
120 }).then(_nextMicrotask).then((_) { | 134 }).then(_nextMicrotask).then((_) { |
121 expect(testDiv.text, 'a:1,c:3,'); | 135 expect(testDiv.text, 'a:1,c:3,'); |
122 map['a'] = 4; | 136 map['a'] = 4; |
(...skipping 24 matching lines...) Expand all Loading... |
147 _initialSelectTest('{{i in y}}', '{{i}}', true); | 161 _initialSelectTest('{{i in y}}', '{{i}}', true); |
148 _updateSelectTest('{{i in y}}', '{{i}}', true); | 162 _updateSelectTest('{{i in y}}', '{{i}}', true); |
149 }); | 163 }); |
150 }); | 164 }); |
151 }); | 165 }); |
152 | 166 |
153 | 167 |
154 _cursorPositionTest(bool usePolymer) { | 168 _cursorPositionTest(bool usePolymer) { |
155 test('should preserve the cursor position', () { | 169 test('should preserve the cursor position', () { |
156 var model = new NotifyModel('abcde'); | 170 var model = new NotifyModel('abcde'); |
157 var template = templateBind(new Element.html( | 171 |
158 '<template><input id="i1" value={{x}}></template>')); | 172 var tag = new Element.html( |
| 173 '<template><input id="i1" value={{x}}></template>'); |
| 174 TemplateBindExtension.bootstrap(tag); |
| 175 var template = templateBind(tag); |
| 176 |
159 var delegate = usePolymer ? new PolymerExpressions() : null; | 177 var delegate = usePolymer ? new PolymerExpressions() : null; |
160 testDiv.append(template.createInstance(model, delegate)); | 178 testDiv.append(template.createInstance(model, delegate)); |
161 | 179 |
162 var el; | 180 var el; |
163 return new Future(() { | 181 return new Future(() { |
164 el = testDiv.query("#i1"); | 182 el = testDiv.query("#i1"); |
165 var subscription = el.onInput.listen(expectAsync((_) {}, count: 1)); | 183 var subscription = el.onInput.listen(expectAsync((_) {}, count: 1)); |
166 el.focus(); | 184 el.focus(); |
167 | 185 |
168 expect(el.value, 'abcde'); | 186 expect(el.value, 'abcde'); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 // ... or later. | 222 // ... or later. |
205 expect(el.selectionStart, 4); | 223 expect(el.selectionStart, 4); |
206 expect(el.selectionEnd, 4); | 224 expect(el.selectionEnd, 4); |
207 }); | 225 }); |
208 }); | 226 }); |
209 } | 227 } |
210 | 228 |
211 _initialSelectTest(String repeatExp, String valueExp, bool usePolymer) { | 229 _initialSelectTest(String repeatExp, String valueExp, bool usePolymer) { |
212 test('initial select value is set correctly', () { | 230 test('initial select value is set correctly', () { |
213 var list = const ['a', 'b']; | 231 var list = const ['a', 'b']; |
214 var template = templateBind(new Element.html('<template>' | 232 |
| 233 var tag = new Element.html('<template>' |
215 '<select value="{{x}}">' | 234 '<select value="{{x}}">' |
216 '<option template repeat="$repeatExp" value="$valueExp">item $valueExp' | 235 '<option template repeat="$repeatExp" value="$valueExp">item $valueExp' |
217 '</option></select></template>', | 236 '</option></select></template>', |
218 treeSanitizer: _nullTreeSanitizer)); | 237 treeSanitizer: _nullTreeSanitizer); |
| 238 TemplateBindExtension.bootstrap(tag); |
| 239 var template = templateBind(tag); |
| 240 |
219 var model = new NotifyModel('b', list); | 241 var model = new NotifyModel('b', list); |
220 var delegate = usePolymer ? new PolymerExpressions() : null; | 242 var delegate = usePolymer ? new PolymerExpressions() : null; |
221 testDiv.append(template.createInstance(model, delegate)); | 243 testDiv.append(template.createInstance(model, delegate)); |
222 | 244 |
223 expect(testDiv.querySelector('select').value, 'b'); | 245 expect(testDiv.querySelector('select').value, 'b'); |
224 return new Future(() { | 246 return new Future(() { |
225 expect(model.x, 'b'); | 247 expect(model.x, 'b'); |
226 expect(testDiv.querySelector('select').value, 'b'); | 248 expect(testDiv.querySelector('select').value, 'b'); |
227 }); | 249 }); |
228 }); | 250 }); |
229 } | 251 } |
230 | 252 |
231 _updateSelectTest(String repeatExp, String valueExp, bool usePolymer) { | 253 _updateSelectTest(String repeatExp, String valueExp, bool usePolymer) { |
232 test('updates to select value propagate correctly', () { | 254 test('updates to select value propagate correctly', () { |
233 var list = const ['a', 'b']; | 255 var list = const ['a', 'b']; |
234 var template = templateBind(new Element.html('<template>' | 256 |
| 257 var tag = new Element.html('<template>' |
235 '<select value="{{x}}">' | 258 '<select value="{{x}}">' |
236 '<option template repeat="$repeatExp" value="$valueExp">item $valueExp' | 259 '<option template repeat="$repeatExp" value="$valueExp">item $valueExp' |
237 '</option></select></template>', | 260 '</option></select></template>', |
238 treeSanitizer: _nullTreeSanitizer)); | 261 treeSanitizer: _nullTreeSanitizer); |
| 262 TemplateBindExtension.bootstrap(tag); |
| 263 var template = templateBind(tag); |
| 264 |
239 var model = new NotifyModel('a', list); | 265 var model = new NotifyModel('a', list); |
240 var delegate = usePolymer ? new PolymerExpressions() : null; | 266 var delegate = usePolymer ? new PolymerExpressions() : null; |
241 testDiv.append(template.createInstance(model, delegate)); | 267 testDiv.append(template.createInstance(model, delegate)); |
242 | 268 |
243 expect(testDiv.querySelector('select').value, 'a'); | 269 expect(testDiv.querySelector('select').value, 'a'); |
244 return new Future(() { | 270 return new Future(() { |
245 expect(testDiv.querySelector('select').value, 'a'); | 271 expect(testDiv.querySelector('select').value, 'a'); |
246 model.x = 'b'; | 272 model.x = 'b'; |
247 }).then(_nextMicrotask).then((_) { | 273 }).then(_nextMicrotask).then((_) { |
248 expect(testDiv.querySelector('select').value, 'b'); | 274 expect(testDiv.querySelector('select').value, 'b'); |
(...skipping 18 matching lines...) Expand all Loading... |
267 get y => _y; | 293 get y => _y; |
268 set y(value) { | 294 set y(value) { |
269 _y = notifyPropertyChange(#y, _y, value); | 295 _y = notifyPropertyChange(#y, _y, value); |
270 } | 296 } |
271 } | 297 } |
272 | 298 |
273 class _NullTreeSanitizer implements NodeTreeSanitizer { | 299 class _NullTreeSanitizer implements NodeTreeSanitizer { |
274 void sanitizeTree(Node node) {} | 300 void sanitizeTree(Node node) {} |
275 } | 301 } |
276 final _nullTreeSanitizer = new _NullTreeSanitizer(); | 302 final _nullTreeSanitizer = new _NullTreeSanitizer(); |
OLD | NEW |