Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: pkg/mdv/test/template_element_test.dart

Issue 19771010: implement dirty checking for @observable objects (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 template_element_test; 5 library template_element_test;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 import 'dart:html'; 9 import 'dart:html';
10 import 'dart:math' as math; 10 import 'dart:math' as math;
11 import 'package:mdv/mdv.dart' as mdv; 11 import 'package:mdv/mdv.dart' as mdv;
12 import 'package:observe/observe.dart'; 12 import 'package:observe/observe.dart';
13 import 'package:unittest/html_config.dart'; 13 import 'package:unittest/html_config.dart';
14 import 'package:unittest/unittest.dart'; 14 import 'package:unittest/unittest.dart';
15 import 'observe_utils.dart'; 15 import 'mdv_test_utils.dart';
16 16
17 // Note: this file ported from 17 // Note: this file ported from
18 // https://github.com/toolkitchen/mdv/blob/master/tests/template_element.js 18 // https://github.com/toolkitchen/mdv/blob/master/tests/template_element.js
19 // TODO(jmesserly): submit a small cleanup patch to original. I fixed some 19 // TODO(jmesserly): submit a small cleanup patch to original. I fixed some
20 // cases where "div" and "t" were unintentionally using the JS global scope; 20 // cases where "div" and "t" were unintentionally using the JS global scope;
21 // look for "assertNodesAre". 21 // look for "assertNodesAre".
22 22
23 main() { 23 main() {
24 mdv.initialize(); 24 mdv.initialize();
25 useHtmlConfiguration(); 25 useHtmlConfiguration();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 recursivelySetTemplateModel(element, model) { 66 recursivelySetTemplateModel(element, model) {
67 for (var node in element.queryAll('*')) { 67 for (var node in element.queryAll('*')) {
68 if (node.isTemplate) node.model = model; 68 if (node.isTemplate) node.model = model;
69 } 69 }
70 } 70 }
71 71
72 dispatchEvent(type, target) { 72 dispatchEvent(type, target) {
73 target.dispatchEvent(new Event(type, cancelable: false)); 73 target.dispatchEvent(new Event(type, cancelable: false));
74 } 74 }
75 75
76 var expando = new Expando('test'); 76 var expando = new Expando('observeTest');
77 void addExpandos(node) { 77 void addExpandos(node) {
78 while (node != null) { 78 while (node != null) {
79 expando[node] = node.text; 79 expando[node] = node.text;
80 node = node.nextNode; 80 node = node.nextNode;
81 } 81 }
82 } 82 }
83 83
84 void checkExpandos(node) { 84 void checkExpandos(node) {
85 expect(node, isNotNull); 85 expect(node, isNotNull);
86 while (node != null) { 86 while (node != null) {
87 expect(expando[node], node.text); 87 expect(expando[node], node.text);
88 node = node.nextNode; 88 node = node.nextNode;
89 } 89 }
90 } 90 }
91 91
92 test('Template', () { 92 observeTest('Template', () {
93 var div = createTestHtml('<template bind={{}}>text</template>'); 93 var div = createTestHtml('<template bind={{}}>text</template>');
94 recursivelySetTemplateModel(div, null); 94 recursivelySetTemplateModel(div, null);
95 deliverChangeRecords(); 95 performMicrotaskCheckpoint();
96 expect(div.nodes.length, 2); 96 expect(div.nodes.length, 2);
97 expect(div.nodes.last.text, 'text'); 97 expect(div.nodes.last.text, 'text');
98 }); 98 });
99 99
100 test('Template bind, no parent', () { 100 observeTest('Template bind, no parent', () {
101 var div = createTestHtml('<template bind>text</template>'); 101 var div = createTestHtml('<template bind>text</template>');
102 var template = div.nodes[0]; 102 var template = div.nodes[0];
103 template.remove(); 103 template.remove();
104 104
105 recursivelySetTemplateModel(template, toSymbolMap({})); 105 recursivelySetTemplateModel(template, toSymbolMap({}));
106 deliverChangeRecords(); 106 performMicrotaskCheckpoint();
107 expect(template.nodes.length, 0); 107 expect(template.nodes.length, 0);
108 expect(template.nextNode, null); 108 expect(template.nextNode, null);
109 // TODO(jmesserly): the JS tests assert that observer callbacks had no 109 // TODO(jmesserly): the JS tests assert that observer callbacks had no
110 // exceptions. How do we replicate this? 110 // exceptions. How do we replicate this?
111 }); 111 });
112 112
113 test('Template bind, no defaultView', () { 113 observeTest('Template bind, no defaultView', () {
114 var div = createTestHtml('<template bind>text</template>'); 114 var div = createTestHtml('<template bind>text</template>');
115 var template = div.nodes[0]; 115 var template = div.nodes[0];
116 var doc = document.implementation.createHtmlDocument(''); 116 var doc = document.implementation.createHtmlDocument('');
117 doc.adoptNode(div); 117 doc.adoptNode(div);
118 recursivelySetTemplateModel(template, toSymbolMap({})); 118 recursivelySetTemplateModel(template, toSymbolMap({}));
119 deliverChangeRecords(); 119 performMicrotaskCheckpoint();
120 expect(div.nodes.length, 1); 120 expect(div.nodes.length, 1);
121 // TODO(jmesserly): the JS tests assert that observer callbacks had no 121 // TODO(jmesserly): the JS tests assert that observer callbacks had no
122 // exceptions. How do we replicate this? 122 // exceptions. How do we replicate this?
123 }); 123 });
124 124
125 test('Template-Empty Bind', () { 125 observeTest('Template-Empty Bind', () {
126 var div = createTestHtml('<template bind>text</template>'); 126 var div = createTestHtml('<template bind>text</template>');
127 recursivelySetTemplateModel(div, null); 127 recursivelySetTemplateModel(div, null);
128 deliverChangeRecords(); 128 performMicrotaskCheckpoint();
129 expect(div.nodes.length, 2); 129 expect(div.nodes.length, 2);
130 expect(div.nodes.last.text, 'text'); 130 expect(div.nodes.last.text, 'text');
131 }); 131 });
132 132
133 test('TextTemplateWithNullStringBinding', () { 133 observeTest('TextTemplateWithNullStringBinding', () {
134 var div = createTestHtml('<template bind={{}}>a{{b}}c</template>'); 134 var div = createTestHtml('<template bind={{}}>a{{b}}c</template>');
135 var model = toSymbolMap({'b': 'B'}); 135 var model = toSymbolMap({'b': 'B'});
136 recursivelySetTemplateModel(div, model); 136 recursivelySetTemplateModel(div, model);
137 137
138 deliverChanges(model); 138 deliverChanges(model);
139 expect(div.nodes.length, 2); 139 expect(div.nodes.length, 2);
140 expect(div.nodes.last.text, 'aBc'); 140 expect(div.nodes.last.text, 'aBc');
141 141
142 model[sym('b')] = 'b'; 142 model[sym('b')] = 'b';
143 deliverChanges(model); 143 deliverChanges(model);
144 expect(div.nodes.last.text, 'abc'); 144 expect(div.nodes.last.text, 'abc');
145 145
146 model[sym('b')] = null; 146 model[sym('b')] = null;
147 deliverChanges(model); 147 deliverChanges(model);
148 expect(div.nodes.last.text, 'ac'); 148 expect(div.nodes.last.text, 'ac');
149 149
150 model = null; 150 model = null;
151 deliverChanges(model); 151 deliverChanges(model);
152 // setting model isn't observable. 152 // setting model isn't observable.
153 expect(div.nodes.last.text, 'ac'); 153 expect(div.nodes.last.text, 'ac');
154 }); 154 });
155 155
156 test('TextTemplateWithBindingPath', () { 156 observeTest('TextTemplateWithBindingPath', () {
157 var div = createTestHtml( 157 var div = createTestHtml(
158 '<template bind="{{ data }}">a{{b}}c</template>'); 158 '<template bind="{{ data }}">a{{b}}c</template>');
159 var model = toSymbolMap({ 'data': {'b': 'B'} }); 159 var model = toSymbolMap({ 'data': {'b': 'B'} });
160 recursivelySetTemplateModel(div, model); 160 recursivelySetTemplateModel(div, model);
161 161
162 deliverChanges(model); 162 deliverChanges(model);
163 expect(div.nodes.length, 2); 163 expect(div.nodes.length, 2);
164 expect(div.nodes.last.text, 'aBc'); 164 expect(div.nodes.last.text, 'aBc');
165 165
166 model[sym('data')][sym('b')] = 'b'; 166 model[sym('data')][sym('b')] = 'b';
167 deliverChanges(model); 167 deliverChanges(model);
168 expect(div.nodes.last.text, 'abc'); 168 expect(div.nodes.last.text, 'abc');
169 169
170 model[sym('data')] = toSymbols({'b': 'X'}); 170 model[sym('data')] = toSymbols({'b': 'X'});
171 deliverChanges(model); 171 deliverChanges(model);
172 expect(div.nodes.last.text, 'aXc'); 172 expect(div.nodes.last.text, 'aXc');
173 173
174 model[sym('data')] = null; 174 model[sym('data')] = null;
175 deliverChanges(model); 175 deliverChanges(model);
176 expect(div.nodes.last.text, 'ac'); 176 expect(div.nodes.last.text, 'ac');
177 }); 177 });
178 178
179 test('TextTemplateWithBindingAndConditional', () { 179 observeTest('TextTemplateWithBindingAndConditional', () {
180 var div = createTestHtml( 180 var div = createTestHtml(
181 '<template bind="{{}}" if="{{ d }}">a{{b}}c</template>'); 181 '<template bind="{{}}" if="{{ d }}">a{{b}}c</template>');
182 var model = toSymbolMap({'b': 'B', 'd': 1}); 182 var model = toSymbolMap({'b': 'B', 'd': 1});
183 recursivelySetTemplateModel(div, model); 183 recursivelySetTemplateModel(div, model);
184 184
185 deliverChanges(model); 185 deliverChanges(model);
186 expect(div.nodes.length, 2); 186 expect(div.nodes.length, 2);
187 expect(div.nodes.last.text, 'aBc'); 187 expect(div.nodes.last.text, 'aBc');
188 188
189 model[sym('b')] = 'b'; 189 model[sym('b')] = 'b';
190 deliverChanges(model); 190 deliverChanges(model);
191 expect(div.nodes.last.text, 'abc'); 191 expect(div.nodes.last.text, 'abc');
192 192
193 // TODO(jmesserly): MDV set this to empty string and relies on JS conversion 193 // TODO(jmesserly): MDV set this to empty string and relies on JS conversion
194 // rules. Is that intended? 194 // rules. Is that intended?
195 // See https://github.com/toolkitchen/mdv/issues/59 195 // See https://github.com/toolkitchen/mdv/issues/59
196 model[sym('d')] = null; 196 model[sym('d')] = null;
197 deliverChanges(model); 197 deliverChanges(model);
198 expect(div.nodes.length, 1); 198 expect(div.nodes.length, 1);
199 199
200 model[sym('d')] = 'here'; 200 model[sym('d')] = 'here';
201 model[sym('b')] = 'd'; 201 model[sym('b')] = 'd';
202 202
203 deliverChanges(model); 203 deliverChanges(model);
204 expect(div.nodes.length, 2); 204 expect(div.nodes.length, 2);
205 expect(div.nodes.last.text, 'adc'); 205 expect(div.nodes.last.text, 'adc');
206 }); 206 });
207 207
208 test('TemplateWithTextBinding2', () { 208 observeTest('TemplateWithTextBinding2', () {
209 var div = createTestHtml( 209 var div = createTestHtml(
210 '<template bind="{{ b }}">a{{value}}c</template>'); 210 '<template bind="{{ b }}">a{{value}}c</template>');
211 expect(div.nodes.length, 1); 211 expect(div.nodes.length, 1);
212 var model = toSymbolMap({'b': {'value': 'B'}}); 212 var model = toSymbolMap({'b': {'value': 'B'}});
213 recursivelySetTemplateModel(div, model); 213 recursivelySetTemplateModel(div, model);
214 214
215 deliverChanges(model); 215 deliverChanges(model);
216 expect(div.nodes.length, 2); 216 expect(div.nodes.length, 2);
217 expect(div.nodes.last.text, 'aBc'); 217 expect(div.nodes.last.text, 'aBc');
218 218
219 model[sym('b')] = toSymbols({'value': 'b'}); 219 model[sym('b')] = toSymbols({'value': 'b'});
220 deliverChanges(model); 220 deliverChanges(model);
221 expect(div.nodes.last.text, 'abc'); 221 expect(div.nodes.last.text, 'abc');
222 }); 222 });
223 223
224 test('TemplateWithAttributeBinding', () { 224 observeTest('TemplateWithAttributeBinding', () {
225 var div = createTestHtml( 225 var div = createTestHtml(
226 '<template bind="{{}}">' 226 '<template bind="{{}}">'
227 '<div foo="a{{b}}c"></div>' 227 '<div foo="a{{b}}c"></div>'
228 '</template>'); 228 '</template>');
229 var model = toSymbolMap({'b': 'B'}); 229 var model = toSymbolMap({'b': 'B'});
230 recursivelySetTemplateModel(div, model); 230 recursivelySetTemplateModel(div, model);
231 231
232 deliverChanges(model); 232 deliverChanges(model);
233 expect(div.nodes.length, 2); 233 expect(div.nodes.length, 2);
234 expect(div.nodes.last.attributes['foo'], 'aBc'); 234 expect(div.nodes.last.attributes['foo'], 'aBc');
235 235
236 model[sym('b')] = 'b'; 236 model[sym('b')] = 'b';
237 deliverChanges(model); 237 deliverChanges(model);
238 expect(div.nodes.last.attributes['foo'], 'abc'); 238 expect(div.nodes.last.attributes['foo'], 'abc');
239 239
240 model[sym('b')] = 'X'; 240 model[sym('b')] = 'X';
241 deliverChanges(model); 241 deliverChanges(model);
242 expect(div.nodes.last.attributes['foo'], 'aXc'); 242 expect(div.nodes.last.attributes['foo'], 'aXc');
243 }); 243 });
244 244
245 test('TemplateWithConditionalBinding', () { 245 observeTest('TemplateWithConditionalBinding', () {
246 var div = createTestHtml( 246 var div = createTestHtml(
247 '<template bind="{{}}">' 247 '<template bind="{{}}">'
248 '<div foo?="{{b}}"></div>' 248 '<div foo?="{{b}}"></div>'
249 '</template>'); 249 '</template>');
250 var model = toSymbolMap({'b': 'b'}); 250 var model = toSymbolMap({'b': 'b'});
251 recursivelySetTemplateModel(div, model); 251 recursivelySetTemplateModel(div, model);
252 252
253 deliverChanges(model); 253 deliverChanges(model);
254 expect(div.nodes.length, 2); 254 expect(div.nodes.length, 2);
255 expect(div.nodes.last.attributes['foo'], ''); 255 expect(div.nodes.last.attributes['foo'], '');
256 expect(div.nodes.last.attributes, isNot(contains('foo?'))); 256 expect(div.nodes.last.attributes, isNot(contains('foo?')));
257 257
258 model[sym('b')] = null; 258 model[sym('b')] = null;
259 deliverChanges(model); 259 deliverChanges(model);
260 expect(div.nodes.last.attributes, isNot(contains('foo'))); 260 expect(div.nodes.last.attributes, isNot(contains('foo')));
261 }); 261 });
262 262
263 test('Repeat', () { 263 observeTest('Repeat', () {
264 var div = createTestHtml( 264 var div = createTestHtml(
265 '<template repeat="{{}}"">text</template>'); 265 '<template repeat="{{}}"">text</template>');
266 266
267 var model = toSymbols([0, 1, 2]); 267 var model = toSymbols([0, 1, 2]);
268 recursivelySetTemplateModel(div, model); 268 recursivelySetTemplateModel(div, model);
269 269
270 deliverChanges(model); 270 deliverChanges(model);
271 expect(div.nodes.length, 4); 271 expect(div.nodes.length, 4);
272 272
273 model.length = 1; 273 model.length = 1;
274 deliverChanges(model); 274 deliverChanges(model);
275 expect(div.nodes.length, 2); 275 expect(div.nodes.length, 2);
276 276
277 model.addAll(toSymbols([3, 4])); 277 model.addAll(toSymbols([3, 4]));
278 deliverChanges(model); 278 deliverChanges(model);
279 expect(div.nodes.length, 4); 279 expect(div.nodes.length, 4);
280 280
281 model.removeRange(1, 2); 281 model.removeRange(1, 2);
282 deliverChanges(model); 282 deliverChanges(model);
283 expect(div.nodes.length, 3); 283 expect(div.nodes.length, 3);
284 }); 284 });
285 285
286 test('Repeat - Reuse Instances', () { 286 observeTest('Repeat - Reuse Instances', () {
287 var div = createTestHtml('<template repeat>{{ val }}</template>'); 287 var div = createTestHtml('<template repeat>{{ val }}</template>');
288 288
289 var model = toSymbols([ 289 var model = toSymbols([
290 {'val': 10}, 290 {'val': 10},
291 {'val': 5}, 291 {'val': 5},
292 {'val': 2}, 292 {'val': 2},
293 {'val': 8}, 293 {'val': 8},
294 {'val': 1} 294 {'val': 1}
295 ]); 295 ]);
296 recursivelySetTemplateModel(div, model); 296 recursivelySetTemplateModel(div, model);
(...skipping 20 matching lines...) Expand all
317 } 317 }
318 318
319 deliverChanges(model); 319 deliverChanges(model);
320 expect(div.nodes[1].text, "11"); 320 expect(div.nodes[1].text, "11");
321 expect(div.nodes[2].text, "9"); 321 expect(div.nodes[2].text, "9");
322 expect(div.nodes[3].text, "6"); 322 expect(div.nodes[3].text, "6");
323 expect(div.nodes[4].text, "3"); 323 expect(div.nodes[4].text, "3");
324 expect(div.nodes[5].text, "2"); 324 expect(div.nodes[5].text, "2");
325 }); 325 });
326 326
327 test('Bind - Reuse Instance', () { 327 observeTest('Bind - Reuse Instance', () {
328 var div = createTestHtml( 328 var div = createTestHtml(
329 '<template bind="{{ foo }}">{{ bar }}</template>'); 329 '<template bind="{{ foo }}">{{ bar }}</template>');
330 330
331 var model = toObservable({ 'foo': { 'bar': 5 }}); 331 var model = toObservable({ 'foo': { 'bar': 5 }});
332 recursivelySetTemplateModel(div, model); 332 recursivelySetTemplateModel(div, model);
333 333
334 deliverChanges(model); 334 deliverChanges(model);
335 expect(div.nodes.length, 2); 335 expect(div.nodes.length, 2);
336 var template = div.firstChild; 336 var template = div.firstChild;
337 337
338 addExpandos(template.nextNode); 338 addExpandos(template.nextNode);
339 checkExpandos(template.nextNode); 339 checkExpandos(template.nextNode);
340 340
341 model = toObservable({'foo': model['foo']}); 341 model = toObservable({'foo': model['foo']});
342 recursivelySetTemplateModel(div, model); 342 recursivelySetTemplateModel(div, model);
343 deliverChanges(model); 343 deliverChanges(model);
344 checkExpandos(template.nextNode); 344 checkExpandos(template.nextNode);
345 }); 345 });
346 346
347 test('Repeat-Empty', () { 347 observeTest('Repeat-Empty', () {
348 var div = createTestHtml( 348 var div = createTestHtml(
349 '<template repeat>text</template>'); 349 '<template repeat>text</template>');
350 350
351 var model = toSymbols([0, 1, 2]); 351 var model = toSymbols([0, 1, 2]);
352 recursivelySetTemplateModel(div, model); 352 recursivelySetTemplateModel(div, model);
353 353
354 deliverChanges(model); 354 deliverChanges(model);
355 expect(div.nodes.length, 4); 355 expect(div.nodes.length, 4);
356 356
357 model.length = 1; 357 model.length = 1;
358 deliverChanges(model); 358 deliverChanges(model);
359 expect(div.nodes.length, 2); 359 expect(div.nodes.length, 2);
360 360
361 model.addAll(toSymbols([3, 4])); 361 model.addAll(toSymbols([3, 4]));
362 deliverChanges(model); 362 deliverChanges(model);
363 expect(div.nodes.length, 4); 363 expect(div.nodes.length, 4);
364 364
365 model.removeRange(1, 2); 365 model.removeRange(1, 2);
366 deliverChanges(model); 366 deliverChanges(model);
367 expect(div.nodes.length, 3); 367 expect(div.nodes.length, 3);
368 }); 368 });
369 369
370 test('Removal from iteration needs to unbind', () { 370 observeTest('Removal from iteration needs to unbind', () {
371 var div = createTestHtml( 371 var div = createTestHtml(
372 '<template repeat="{{}}"><a>{{v}}</a></template>'); 372 '<template repeat="{{}}"><a>{{v}}</a></template>');
373 var model = toSymbols([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3}, {'v': 4}]); 373 var model = toSymbols([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3}, {'v': 4}]);
374 recursivelySetTemplateModel(div, model); 374 recursivelySetTemplateModel(div, model);
375 deliverChanges(model); 375 deliverChanges(model);
376 376
377 var nodes = div.nodes.skip(1).toList(); 377 var nodes = div.nodes.skip(1).toList();
378 var vs = model.toList(); 378 var vs = model.toList();
379 379
380 for (var i = 0; i < 5; i++) { 380 for (var i = 0; i < 5; i++) {
381 expect(nodes[i].text, '$i'); 381 expect(nodes[i].text, '$i');
382 } 382 }
383 383
384 model.length = 3; 384 model.length = 3;
385 deliverChanges(model); 385 deliverChanges(model);
386 for (var i = 0; i < 5; i++) { 386 for (var i = 0; i < 5; i++) {
387 expect(nodes[i].text, '$i'); 387 expect(nodes[i].text, '$i');
388 } 388 }
389 389
390 vs[3][sym('v')] = 33; 390 vs[3][sym('v')] = 33;
391 vs[4][sym('v')] = 44; 391 vs[4][sym('v')] = 44;
392 deliverChanges(model); 392 deliverChanges(model);
393 for (var i = 0; i < 5; i++) { 393 for (var i = 0; i < 5; i++) {
394 expect(nodes[i].text, '$i'); 394 expect(nodes[i].text, '$i');
395 } 395 }
396 }); 396 });
397 397
398 test('DOM Stability on Iteration', () { 398 observeTest('DOM Stability on Iteration', () {
399 var div = createTestHtml( 399 var div = createTestHtml(
400 '<template repeat="{{}}">{{}}</template>'); 400 '<template repeat="{{}}">{{}}</template>');
401 var model = toSymbols([1, 2, 3, 4, 5]); 401 var model = toSymbols([1, 2, 3, 4, 5]);
402 recursivelySetTemplateModel(div, model); 402 recursivelySetTemplateModel(div, model);
403 403
404 deliverChanges(model); 404 deliverChanges(model);
405 405
406 // Note: the node at index 0 is the <template>. 406 // Note: the node at index 0 is the <template>.
407 var nodes = div.nodes.toList(); 407 var nodes = div.nodes.toList();
408 expect(nodes.length, 6, reason: 'list has 5 items'); 408 expect(nodes.length, 6, reason: 'list has 5 items');
(...skipping 28 matching lines...) Expand all
437 437
438 expect(div.nodes.length, 7, reason: 'list has 6 items'); 438 expect(div.nodes.length, 7, reason: 'list has 6 items');
439 expect(identical(div.nodes[1], nodes[1]), true); 439 expect(identical(div.nodes[1], nodes[1]), true);
440 expect(identical(div.nodes[2], nodes[2]), true); 440 expect(identical(div.nodes[2], nodes[2]), true);
441 expect(nodes.contains(div.nodes[3]), false, reason: '8 is a new node'); 441 expect(nodes.contains(div.nodes[3]), false, reason: '8 is a new node');
442 expect(identical(div.nodes[4], nodes[3]), true); 442 expect(identical(div.nodes[4], nodes[3]), true);
443 expect(identical(div.nodes[5], nodes[4]), true); 443 expect(identical(div.nodes[5], nodes[4]), true);
444 expect(identical(div.nodes[6], nodes[5]), true); 444 expect(identical(div.nodes[6], nodes[5]), true);
445 }); 445 });
446 446
447 test('Repeat2', () { 447 observeTest('Repeat2', () {
448 var div = createTestHtml( 448 var div = createTestHtml(
449 '<template repeat="{{}}">{{value}}</template>'); 449 '<template repeat="{{}}">{{value}}</template>');
450 expect(div.nodes.length, 1); 450 expect(div.nodes.length, 1);
451 451
452 var model = toSymbols([ 452 var model = toSymbols([
453 {'value': 0}, 453 {'value': 0},
454 {'value': 1}, 454 {'value': 1},
455 {'value': 2} 455 {'value': 2}
456 ]); 456 ]);
457 recursivelySetTemplateModel(div, model); 457 recursivelySetTemplateModel(div, model);
(...skipping 12 matching lines...) Expand all
470 expect(div.nodes[3].text, '2'); 470 expect(div.nodes[3].text, '2');
471 471
472 model.replaceRange(0, 1, toSymbols([{'value': 'Zero'}])); 472 model.replaceRange(0, 1, toSymbols([{'value': 'Zero'}]));
473 deliverChanges(model); 473 deliverChanges(model);
474 expect(div.nodes.length, 4); 474 expect(div.nodes.length, 4);
475 expect(div.nodes[1].text, 'Zero'); 475 expect(div.nodes[1].text, 'Zero');
476 expect(div.nodes[2].text, 'One'); 476 expect(div.nodes[2].text, 'One');
477 expect(div.nodes[3].text, '2'); 477 expect(div.nodes[3].text, '2');
478 }); 478 });
479 479
480 test('TemplateWithInputValue', () { 480 observeTest('TemplateWithInputValue', () {
481 var div = createTestHtml( 481 var div = createTestHtml(
482 '<template bind="{{}}">' 482 '<template bind="{{}}">'
483 '<input value="{{x}}">' 483 '<input value="{{x}}">'
484 '</template>'); 484 '</template>');
485 var model = toSymbolMap({'x': 'hi'}); 485 var model = toSymbolMap({'x': 'hi'});
486 recursivelySetTemplateModel(div, model); 486 recursivelySetTemplateModel(div, model);
487 487
488 deliverChanges(model); 488 deliverChanges(model);
489 expect(div.nodes.length, 2); 489 expect(div.nodes.length, 2);
490 expect(div.nodes.last.value, 'hi'); 490 expect(div.nodes.last.value, 'hi');
491 491
492 model[sym('x')] = 'bye'; 492 model[sym('x')] = 'bye';
493 expect(div.nodes.last.value, 'hi'); 493 expect(div.nodes.last.value, 'hi');
494 deliverChanges(model); 494 deliverChanges(model);
495 expect(div.nodes.last.value, 'bye'); 495 expect(div.nodes.last.value, 'bye');
496 496
497 div.nodes.last.value = 'hello'; 497 div.nodes.last.value = 'hello';
498 dispatchEvent('input', div.nodes.last); 498 dispatchEvent('input', div.nodes.last);
499 expect(model[sym('x')], 'hello'); 499 expect(model[sym('x')], 'hello');
500 deliverChanges(model); 500 deliverChanges(model);
501 expect(div.nodes.last.value, 'hello'); 501 expect(div.nodes.last.value, 'hello');
502 }); 502 });
503 503
504 ////////////////////////////////////////////////////////////////////////////// 504 //////////////////////////////////////////////////////////////////////////////
505 505
506 test('Decorated', () { 506 observeTest('Decorated', () {
507 var div = createTestHtml( 507 var div = createTestHtml(
508 '<template bind="{{ XX }}" id="t1">' 508 '<template bind="{{ XX }}" id="t1">'
509 '<p>Crew member: {{name}}, Job title: {{title}}</p>' 509 '<p>Crew member: {{name}}, Job title: {{title}}</p>'
510 '</template>' 510 '</template>'
511 '<template bind="{{ XY }}" id="t2" ref="t1"></template>'); 511 '<template bind="{{ XY }}" id="t2" ref="t1"></template>');
512 512
513 var model = toSymbolMap({ 513 var model = toSymbolMap({
514 'XX': {'name': 'Leela', 'title': 'Captain'}, 514 'XX': {'name': 'Leela', 'title': 'Captain'},
515 'XY': {'name': 'Fry', 'title': 'Delivery boy'}, 515 'XY': {'name': 'Fry', 'title': 'Delivery boy'},
516 'XZ': {'name': 'Zoidberg', 'title': 'Doctor'} 516 'XZ': {'name': 'Zoidberg', 'title': 'Doctor'}
(...skipping 10 matching lines...) Expand all
527 instance = t2.nextElementSibling; 527 instance = t2.nextElementSibling;
528 expect(instance.text, 'Crew member: Fry, Job title: Delivery boy'); 528 expect(instance.text, 'Crew member: Fry, Job title: Delivery boy');
529 529
530 expect(div.children.length, 4); 530 expect(div.children.length, 4);
531 expect(div.nodes.length, 4); 531 expect(div.nodes.length, 4);
532 532
533 expect(div.nodes[1].tagName, 'P'); 533 expect(div.nodes[1].tagName, 'P');
534 expect(div.nodes[3].tagName, 'P'); 534 expect(div.nodes[3].tagName, 'P');
535 }); 535 });
536 536
537 test('DefaultStyles', () { 537 observeTest('DefaultStyles', () {
538 var t = new Element.tag('template'); 538 var t = new Element.tag('template');
539 TemplateElement.decorate(t); 539 TemplateElement.decorate(t);
540 540
541 document.body.append(t); 541 document.body.append(t);
542 expect(t.getComputedStyle().display, 'none'); 542 expect(t.getComputedStyle().display, 'none');
543 543
544 t.remove(); 544 t.remove();
545 }); 545 });
546 546
547 547
548 test('Bind', () { 548 observeTest('Bind', () {
549 var div = createTestHtml('<template bind="{{}}">Hi {{ name }}</template>'); 549 var div = createTestHtml('<template bind="{{}}">Hi {{ name }}</template>');
550 var model = toSymbolMap({'name': 'Leela'}); 550 var model = toSymbolMap({'name': 'Leela'});
551 recursivelySetTemplateModel(div, model); 551 recursivelySetTemplateModel(div, model);
552 552
553 deliverChanges(model); 553 deliverChanges(model);
554 expect(div.nodes[1].text, 'Hi Leela'); 554 expect(div.nodes[1].text, 'Hi Leela');
555 }); 555 });
556 556
557 test('BindImperative', () { 557 observeTest('BindImperative', () {
558 var div = createTestHtml( 558 var div = createTestHtml(
559 '<template>' 559 '<template>'
560 'Hi {{ name }}' 560 'Hi {{ name }}'
561 '</template>'); 561 '</template>');
562 var t = div.nodes.first; 562 var t = div.nodes.first;
563 563
564 var model = toSymbolMap({'name': 'Leela'}); 564 var model = toSymbolMap({'name': 'Leela'});
565 t.bind('bind', model, ''); 565 t.bind('bind', model, '');
566 566
567 deliverChanges(model); 567 deliverChanges(model);
568 expect(div.nodes[1].text, 'Hi Leela'); 568 expect(div.nodes[1].text, 'Hi Leela');
569 }); 569 });
570 570
571 test('BindPlaceHolderHasNewLine', () { 571 observeTest('BindPlaceHolderHasNewLine', () {
572 var div = createTestHtml('<template bind="{{}}">Hi {{\nname\n}}</template>') ; 572 var div = createTestHtml('<template bind="{{}}">Hi {{\nname\n}}</template>') ;
573 var model = toSymbolMap({'name': 'Leela'}); 573 var model = toSymbolMap({'name': 'Leela'});
574 recursivelySetTemplateModel(div, model); 574 recursivelySetTemplateModel(div, model);
575 575
576 deliverChanges(model); 576 deliverChanges(model);
577 expect(div.nodes[1].text, 'Hi Leela'); 577 expect(div.nodes[1].text, 'Hi Leela');
578 }); 578 });
579 579
580 test('BindWithRef', () { 580 observeTest('BindWithRef', () {
581 var id = 't${new math.Random().nextDouble()}'; 581 var id = 't${new math.Random().nextDouble()}';
582 var div = createTestHtml( 582 var div = createTestHtml(
583 '<template id="$id">' 583 '<template id="$id">'
584 'Hi {{ name }}' 584 'Hi {{ name }}'
585 '</template>' 585 '</template>'
586 '<template ref="$id" bind="{{}}"></template>'); 586 '<template ref="$id" bind="{{}}"></template>');
587 587
588 var t1 = div.nodes.first; 588 var t1 = div.nodes.first;
589 var t2 = div.nodes[1]; 589 var t2 = div.nodes[1];
590 590
591 expect(t2.ref, t1); 591 expect(t2.ref, t1);
592 592
593 var model = toSymbolMap({'name': 'Fry'}); 593 var model = toSymbolMap({'name': 'Fry'});
594 recursivelySetTemplateModel(div, model); 594 recursivelySetTemplateModel(div, model);
595 595
596 deliverChanges(model); 596 deliverChanges(model);
597 expect(t2.nextNode.text, 'Hi Fry'); 597 expect(t2.nextNode.text, 'Hi Fry');
598 }); 598 });
599 599
600 test('BindChanged', () { 600 observeTest('BindChanged', () {
601 var model = toSymbolMap({ 601 var model = toSymbolMap({
602 'XX': {'name': 'Leela', 'title': 'Captain'}, 602 'XX': {'name': 'Leela', 'title': 'Captain'},
603 'XY': {'name': 'Fry', 'title': 'Delivery boy'}, 603 'XY': {'name': 'Fry', 'title': 'Delivery boy'},
604 'XZ': {'name': 'Zoidberg', 'title': 'Doctor'} 604 'XZ': {'name': 'Zoidberg', 'title': 'Doctor'}
605 }); 605 });
606 606
607 var div = createTestHtml( 607 var div = createTestHtml(
608 '<template bind="{{ XX }}">Hi {{ name }}</template>'); 608 '<template bind="{{ XX }}">Hi {{ name }}</template>');
609 609
610 recursivelySetTemplateModel(div, model); 610 recursivelySetTemplateModel(div, model);
(...skipping 14 matching lines...) Expand all
625 assertNodesAre(div, [arguments]) { 625 assertNodesAre(div, [arguments]) {
626 var expectedLength = arguments.length; 626 var expectedLength = arguments.length;
627 expect(div.nodes.length, expectedLength + 1); 627 expect(div.nodes.length, expectedLength + 1);
628 628
629 for (var i = 0; i < arguments.length; i++) { 629 for (var i = 0; i < arguments.length; i++) {
630 var targetNode = div.nodes[i + 1]; 630 var targetNode = div.nodes[i + 1];
631 expect(targetNode.text, arguments[i]); 631 expect(targetNode.text, arguments[i]);
632 } 632 }
633 } 633 }
634 634
635 test('Repeat3', () { 635 observeTest('Repeat3', () {
636 var div = createTestHtml( 636 var div = createTestHtml(
637 '<template repeat="{{ contacts }}">Hi {{ name }}</template>'); 637 '<template repeat="{{ contacts }}">Hi {{ name }}</template>');
638 var t = div.nodes.first; 638 var t = div.nodes.first;
639 639
640 var m = toSymbols({ 640 var m = toSymbols({
641 'contacts': [ 641 'contacts': [
642 {'name': 'Raf'}, 642 {'name': 'Raf'},
643 {'name': 'Arv'}, 643 {'name': 'Arv'},
644 {'name': 'Neal'} 644 {'name': 'Neal'}
645 ] 645 ]
(...skipping 29 matching lines...) Expand all
675 675
676 m[sym('contacts')] = toSymbols([{'name': 'Alex'}]); 676 m[sym('contacts')] = toSymbols([{'name': 'Alex'}]);
677 deliverChanges(m); 677 deliverChanges(m);
678 assertNodesAre(div, ['Hi Alex']); 678 assertNodesAre(div, ['Hi Alex']);
679 679
680 m[sym('contacts')].length = 0; 680 m[sym('contacts')].length = 0;
681 deliverChanges(m); 681 deliverChanges(m);
682 assertNodesAre(div, []); 682 assertNodesAre(div, []);
683 }); 683 });
684 684
685 test('RepeatModelSet', () { 685 observeTest('RepeatModelSet', () {
686 var div = createTestHtml( 686 var div = createTestHtml(
687 '<template repeat="{{ contacts }}">' 687 '<template repeat="{{ contacts }}">'
688 'Hi {{ name }}' 688 'Hi {{ name }}'
689 '</template>'); 689 '</template>');
690 var m = toSymbols({ 690 var m = toSymbols({
691 'contacts': [ 691 'contacts': [
692 {'name': 'Raf'}, 692 {'name': 'Raf'},
693 {'name': 'Arv'}, 693 {'name': 'Arv'},
694 {'name': 'Neal'} 694 {'name': 'Neal'}
695 ] 695 ]
696 }); 696 });
697 recursivelySetTemplateModel(div, m); 697 recursivelySetTemplateModel(div, m);
698 698
699 deliverChanges(m); 699 deliverChanges(m);
700 var t = div.nodes.first; 700 var t = div.nodes.first;
701 701
702 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); 702 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']);
703 }); 703 });
704 704
705 test('RepeatEmptyPath', () { 705 observeTest('RepeatEmptyPath', () {
706 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ; 706 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ;
707 var t = div.nodes.first; 707 var t = div.nodes.first;
708 708
709 var m = toSymbols([ 709 var m = toSymbols([
710 {'name': 'Raf'}, 710 {'name': 'Raf'},
711 {'name': 'Arv'}, 711 {'name': 'Arv'},
712 {'name': 'Neal'} 712 {'name': 'Neal'}
713 ]); 713 ]);
714 recursivelySetTemplateModel(div, m); 714 recursivelySetTemplateModel(div, m);
715 715
(...skipping 20 matching lines...) Expand all
736 m.replaceRange(0, 1, toSymbols([{'name': 'Tab'}, {'name': 'Neal'}])); 736 m.replaceRange(0, 1, toSymbols([{'name': 'Tab'}, {'name': 'Neal'}]));
737 deliverChanges(m); 737 deliverChanges(m);
738 assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri', 'Hi Alex' ]); 738 assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri', 'Hi Alex' ]);
739 739
740 m.length = 0; 740 m.length = 0;
741 m.add(toSymbols({'name': 'Alex'})); 741 m.add(toSymbols({'name': 'Alex'}));
742 deliverChanges(m); 742 deliverChanges(m);
743 assertNodesAre(div, ['Hi Alex']); 743 assertNodesAre(div, ['Hi Alex']);
744 }); 744 });
745 745
746 test('RepeatNullModel', () { 746 observeTest('RepeatNullModel', () {
747 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ; 747 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ;
748 var t = div.nodes.first; 748 var t = div.nodes.first;
749 749
750 var m = null; 750 var m = null;
751 recursivelySetTemplateModel(div, m); 751 recursivelySetTemplateModel(div, m);
752 752
753 expect(div.nodes.length, 1); 753 expect(div.nodes.length, 1);
754 754
755 t.attributes['iterate'] = ''; 755 t.attributes['iterate'] = '';
756 m = toSymbols({}); 756 m = toSymbols({});
757 recursivelySetTemplateModel(div, m); 757 recursivelySetTemplateModel(div, m);
758 758
759 deliverChanges(m); 759 deliverChanges(m);
760 expect(div.nodes.length, 1); 760 expect(div.nodes.length, 1);
761 }); 761 });
762 762
763 test('RepeatReuse', () { 763 observeTest('RepeatReuse', () {
764 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ; 764 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ;
765 var t = div.nodes.first; 765 var t = div.nodes.first;
766 766
767 var m = toSymbols([ 767 var m = toSymbols([
768 {'name': 'Raf'}, 768 {'name': 'Raf'},
769 {'name': 'Arv'}, 769 {'name': 'Arv'},
770 {'name': 'Neal'} 770 {'name': 'Neal'}
771 ]); 771 ]);
772 recursivelySetTemplateModel(div, m); 772 recursivelySetTemplateModel(div, m);
773 deliverChanges(m); 773 deliverChanges(m);
(...skipping 12 matching lines...) Expand all
786 reason: 'Should not reuse when replacing'); 786 reason: 'Should not reuse when replacing');
787 expect(div.nodes[3], node3, 787 expect(div.nodes[3], node3,
788 reason: 'model[2] did not change so the node should not have changed'); 788 reason: 'model[2] did not change so the node should not have changed');
789 789
790 node2 = div.nodes[2]; 790 node2 = div.nodes[2];
791 m.insert(0, toSymbols({'name': 'Alex'})); 791 m.insert(0, toSymbols({'name': 'Alex'}));
792 deliverChanges(m); 792 deliverChanges(m);
793 assertNodesAre(div, ['Hi Alex', 'Hi Raf', 'Hi Erik', 'Hi Neal']); 793 assertNodesAre(div, ['Hi Alex', 'Hi Raf', 'Hi Erik', 'Hi Neal']);
794 }); 794 });
795 795
796 test('TwoLevelsDeepBug', () { 796 observeTest('TwoLevelsDeepBug', () {
797 var div = createTestHtml( 797 var div = createTestHtml(
798 '<template bind="{{}}"><span><span>{{ foo }}</span></span></template>'); 798 '<template bind="{{}}"><span><span>{{ foo }}</span></span></template>');
799 799
800 var model = toSymbolMap({'foo': 'bar'}); 800 var model = toSymbolMap({'foo': 'bar'});
801 recursivelySetTemplateModel(div, model); 801 recursivelySetTemplateModel(div, model);
802 deliverChanges(model); 802 deliverChanges(model);
803 803
804 expect(div.nodes[1].nodes[0].nodes[0].text, 'bar'); 804 expect(div.nodes[1].nodes[0].nodes[0].text, 'bar');
805 }); 805 });
806 806
807 test('Checked', () { 807 observeTest('Checked', () {
808 var div = createTestHtml( 808 var div = createTestHtml(
809 '<template>' 809 '<template>'
810 '<input type="checkbox" checked="{{a}}">' 810 '<input type="checkbox" checked="{{a}}">'
811 '</template>'); 811 '</template>');
812 var t = div.nodes.first; 812 var t = div.nodes.first;
813 var m = toSymbols({ 813 var m = toSymbols({
814 'a': true 814 'a': true
815 }); 815 });
816 t.bind('bind', m, ''); 816 t.bind('bind', m, '');
817 deliverChanges(m); 817 deliverChanges(m);
(...skipping 28 matching lines...) Expand all
846 846
847 m[sym('a')][sym('b')] = 11; 847 m[sym('a')][sym('b')] = 11;
848 deliverChanges(m); 848 deliverChanges(m);
849 expect(div.nodes[start].text, '11'); 849 expect(div.nodes[start].text, '11');
850 850
851 m[sym('a')][sym('c')] = toSymbols({'d': 22}); 851 m[sym('a')][sym('c')] = toSymbols({'d': 22});
852 deliverChanges(m); 852 deliverChanges(m);
853 expect(div.nodes[start + 2].text, '22'); 853 expect(div.nodes[start + 2].text, '22');
854 } 854 }
855 855
856 test('Nested', () { 856 observeTest('Nested', () {
857 nestedHelper( 857 nestedHelper(
858 '<template bind="{{a}}">' 858 '<template bind="{{a}}">'
859 '{{b}}' 859 '{{b}}'
860 '<template bind="{{c}}">' 860 '<template bind="{{c}}">'
861 '{{d}}' 861 '{{d}}'
862 '</template>' 862 '</template>'
863 '</template>', 1); 863 '</template>', 1);
864 }); 864 });
865 865
866 test('NestedWithRef', () { 866 observeTest('NestedWithRef', () {
867 nestedHelper( 867 nestedHelper(
868 '<template id="inner">{{d}}</template>' 868 '<template id="inner">{{d}}</template>'
869 '<template id="outer" bind="{{a}}">' 869 '<template id="outer" bind="{{a}}">'
870 '{{b}}' 870 '{{b}}'
871 '<template ref="inner" bind="{{c}}"></template>' 871 '<template ref="inner" bind="{{c}}"></template>'
872 '</template>', 2); 872 '</template>', 2);
873 }); 873 });
874 874
875 nestedIterateInstantiateHelper(s, start) { 875 nestedIterateInstantiateHelper(s, start) {
876 var div = createTestHtml(s); 876 var div = createTestHtml(s);
(...skipping 25 matching lines...) Expand all
902 m[sym('a')][1] = toSymbols({ 902 m[sym('a')][1] = toSymbols({
903 'b': 3, 903 'b': 3,
904 'c': {'d': 33} 904 'c': {'d': 33}
905 }); 905 });
906 906
907 deliverChanges(m); 907 deliverChanges(m);
908 expect(div.nodes[start + 3].text, '3'); 908 expect(div.nodes[start + 3].text, '3');
909 expect(div.nodes[start + 5].text, '33'); 909 expect(div.nodes[start + 5].text, '33');
910 } 910 }
911 911
912 test('NestedRepeatBind', () { 912 observeTest('NestedRepeatBind', () {
913 nestedIterateInstantiateHelper( 913 nestedIterateInstantiateHelper(
914 '<template repeat="{{a}}">' 914 '<template repeat="{{a}}">'
915 '{{b}}' 915 '{{b}}'
916 '<template bind="{{c}}">' 916 '<template bind="{{c}}">'
917 '{{d}}' 917 '{{d}}'
918 '</template>' 918 '</template>'
919 '</template>', 1); 919 '</template>', 1);
920 }); 920 });
921 921
922 test('NestedRepeatBindWithRef', () { 922 observeTest('NestedRepeatBindWithRef', () {
923 nestedIterateInstantiateHelper( 923 nestedIterateInstantiateHelper(
924 '<template id="inner">' 924 '<template id="inner">'
925 '{{d}}' 925 '{{d}}'
926 '</template>' 926 '</template>'
927 '<template repeat="{{a}}">' 927 '<template repeat="{{a}}">'
928 '{{b}}' 928 '{{b}}'
929 '<template ref="inner" bind="{{c}}"></template>' 929 '<template ref="inner" bind="{{c}}"></template>'
930 '</template>', 2); 930 '</template>', 2);
931 }); 931 });
932 932
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
965 }); 965 });
966 966
967 i = start + 4; 967 i = start + 4;
968 deliverChanges(m); 968 deliverChanges(m);
969 expect(div.nodes[start + 4].text, '3'); 969 expect(div.nodes[start + 4].text, '3');
970 expect(div.nodes[start + 6].text, '31'); 970 expect(div.nodes[start + 6].text, '31');
971 expect(div.nodes[start + 7].text, '32'); 971 expect(div.nodes[start + 7].text, '32');
972 expect(div.nodes[start + 8].text, '33'); 972 expect(div.nodes[start + 8].text, '33');
973 } 973 }
974 974
975 test('NestedRepeatBind', () { 975 observeTest('NestedRepeatBind', () {
976 nestedIterateIterateHelper( 976 nestedIterateIterateHelper(
977 '<template repeat="{{a}}">' 977 '<template repeat="{{a}}">'
978 '{{b}}' 978 '{{b}}'
979 '<template repeat="{{c}}">' 979 '<template repeat="{{c}}">'
980 '{{d}}' 980 '{{d}}'
981 '</template>' 981 '</template>'
982 '</template>', 1); 982 '</template>', 1);
983 }); 983 });
984 984
985 test('NestedRepeatRepeatWithRef', () { 985 observeTest('NestedRepeatRepeatWithRef', () {
986 nestedIterateIterateHelper( 986 nestedIterateIterateHelper(
987 '<template id="inner">' 987 '<template id="inner">'
988 '{{d}}' 988 '{{d}}'
989 '</template>' 989 '</template>'
990 '<template repeat="{{a}}">' 990 '<template repeat="{{a}}">'
991 '{{b}}' 991 '{{b}}'
992 '<template ref="inner" repeat="{{c}}"></template>' 992 '<template ref="inner" repeat="{{c}}"></template>'
993 '</template>', 2); 993 '</template>', 2);
994 }); 994 });
995 995
996 test('NestedRepeatSelfRef', () { 996 observeTest('NestedRepeatSelfRef', () {
997 var div = createTestHtml( 997 var div = createTestHtml(
998 '<template id="t" repeat="{{}}">' 998 '<template id="t" repeat="{{}}">'
999 '{{name}}' 999 '{{name}}'
1000 '<template ref="t" repeat="{{items}}"></template>' 1000 '<template ref="t" repeat="{{items}}"></template>'
1001 '</template>'); 1001 '</template>');
1002 1002
1003 var m = toSymbols([ 1003 var m = toSymbols([
1004 { 1004 {
1005 'name': 'Item 1', 1005 'name': 'Item 1',
1006 'items': [ 1006 'items': [
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1040 1040
1041 m[0] = toSymbols({'name': 'Item 1 changed'}); 1041 m[0] = toSymbols({'name': 'Item 1 changed'});
1042 1042
1043 i = 1; 1043 i = 1;
1044 deliverChanges(m); 1044 deliverChanges(m);
1045 expect(div.nodes[i++].text, 'Item 1 changed'); 1045 expect(div.nodes[i++].text, 'Item 1 changed');
1046 expect(div.nodes[i++].tagName, 'TEMPLATE'); 1046 expect(div.nodes[i++].tagName, 'TEMPLATE');
1047 expect(div.nodes[i++].text, 'Item 2'); 1047 expect(div.nodes[i++].text, 'Item 2');
1048 }); 1048 });
1049 1049
1050 test('Attribute Template Option/Optgroup', () { 1050 observeTest('Attribute Template Option/Optgroup', () {
1051 var div = createTestHtml( 1051 var div = createTestHtml(
1052 '<template bind>' 1052 '<template bind>'
1053 '<select selectedIndex="{{ selected }}">' 1053 '<select selectedIndex="{{ selected }}">'
1054 '<optgroup template repeat="{{ groups }}" label="{{ name }}">' 1054 '<optgroup template repeat="{{ groups }}" label="{{ name }}">'
1055 '<option template repeat="{{ items }}">{{ val }}</option>' 1055 '<option template repeat="{{ items }}">{{ val }}</option>'
1056 '</optgroup>' 1056 '</optgroup>'
1057 '</select>' 1057 '</select>'
1058 '</template>'); 1058 '</template>');
1059 1059
1060 var m = toSymbols({ 1060 var m = toSymbols({
(...skipping 19 matching lines...) Expand all
1080 expect(select.nodes[0].ref.content.nodes[0].tagName, 'OPTGROUP'); 1080 expect(select.nodes[0].ref.content.nodes[0].tagName, 'OPTGROUP');
1081 1081
1082 var optgroup = select.nodes[1]; 1082 var optgroup = select.nodes[1];
1083 expect(optgroup.nodes[0].tagName, 'TEMPLATE'); 1083 expect(optgroup.nodes[0].tagName, 'TEMPLATE');
1084 expect(optgroup.nodes[1].tagName, 'OPTION'); 1084 expect(optgroup.nodes[1].tagName, 'OPTION');
1085 expect(optgroup.nodes[1].text, '0'); 1085 expect(optgroup.nodes[1].text, '0');
1086 expect(optgroup.nodes[2].tagName, 'OPTION'); 1086 expect(optgroup.nodes[2].tagName, 'OPTION');
1087 expect(optgroup.nodes[2].text, '1'); 1087 expect(optgroup.nodes[2].text, '1');
1088 }); 1088 });
1089 1089
1090 test('NestedIterateTableMixedSemanticNative', () { 1090 observeTest('NestedIterateTableMixedSemanticNative', () {
1091 if (!TemplateElement.supported) return; 1091 if (!TemplateElement.supported) return;
1092 1092
1093 var div = createTestHtml( 1093 var div = createTestHtml(
1094 '<table><tbody>' 1094 '<table><tbody>'
1095 '<template repeat="{{}}">' 1095 '<template repeat="{{}}">'
1096 '<tr>' 1096 '<tr>'
1097 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>' 1097 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>'
1098 '</tr>' 1098 '</tr>'
1099 '</template>' 1099 '</template>'
1100 '</tbody></table>'); 1100 '</tbody></table>');
(...skipping 20 matching lines...) Expand all
1121 // 1 for the <td template>, 2 * (1 td) 1121 // 1 for the <td template>, 2 * (1 td)
1122 expect(tbody.nodes[2].nodes.length, 3); 1122 expect(tbody.nodes[2].nodes.length, 3);
1123 expect(tbody.nodes[2].nodes[1].text, '2'); 1123 expect(tbody.nodes[2].nodes[1].text, '2');
1124 expect(tbody.nodes[2].nodes[2].text, '3'); 1124 expect(tbody.nodes[2].nodes[2].text, '3');
1125 1125
1126 // Asset the 'class' binding is retained on the semantic template (just 1126 // Asset the 'class' binding is retained on the semantic template (just
1127 // check the last one). 1127 // check the last one).
1128 expect(tbody.nodes[2].nodes[2].attributes["class"], '3'); 1128 expect(tbody.nodes[2].nodes[2].attributes["class"], '3');
1129 }); 1129 });
1130 1130
1131 test('NestedIterateTable', () { 1131 observeTest('NestedIterateTable', () {
1132 var div = createTestHtml( 1132 var div = createTestHtml(
1133 '<table><tbody>' 1133 '<table><tbody>'
1134 '<tr template repeat="{{}}">' 1134 '<tr template repeat="{{}}">'
1135 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>' 1135 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>'
1136 '</tr>' 1136 '</tr>'
1137 '</tbody></table>'); 1137 '</tbody></table>');
1138 1138
1139 var m = toSymbols([ 1139 var m = toSymbols([
1140 [{ 'val': 0 }, { 'val': 1 }], 1140 [{ 'val': 0 }, { 'val': 1 }],
1141 [{ 'val': 2 }, { 'val': 3 }] 1141 [{ 'val': 2 }, { 'val': 3 }]
(...skipping 16 matching lines...) Expand all
1158 // 1 for the <td template>, 2 * (1 td) 1158 // 1 for the <td template>, 2 * (1 td)
1159 expect(tbody.nodes[2].nodes.length, 3); 1159 expect(tbody.nodes[2].nodes.length, 3);
1160 expect(tbody.nodes[2].nodes[1].text, '2'); 1160 expect(tbody.nodes[2].nodes[1].text, '2');
1161 expect(tbody.nodes[2].nodes[2].text, '3'); 1161 expect(tbody.nodes[2].nodes[2].text, '3');
1162 1162
1163 // Asset the 'class' binding is retained on the semantic template (just chec k 1163 // Asset the 'class' binding is retained on the semantic template (just chec k
1164 // the last one). 1164 // the last one).
1165 expect(tbody.nodes[2].nodes[2].attributes['class'], '3'); 1165 expect(tbody.nodes[2].nodes[2].attributes['class'], '3');
1166 }); 1166 });
1167 1167
1168 test('NestedRepeatDeletionOfMultipleSubTemplates', () { 1168 observeTest('NestedRepeatDeletionOfMultipleSubTemplates', () {
1169 var div = createTestHtml( 1169 var div = createTestHtml(
1170 '<ul>' 1170 '<ul>'
1171 '<template repeat="{{}}" id=t1>' 1171 '<template repeat="{{}}" id=t1>'
1172 '<li>{{name}}' 1172 '<li>{{name}}'
1173 '<ul>' 1173 '<ul>'
1174 '<template ref=t1 repaet="{{items}}"></template>' 1174 '<template ref=t1 repaet="{{items}}"></template>'
1175 '</ul>' 1175 '</ul>'
1176 '</li>' 1176 '</li>'
1177 '</template>' 1177 '</template>'
1178 '</ul>'); 1178 '</ul>');
1179 1179
1180 var m = toSymbols([ 1180 var m = toSymbols([
1181 { 1181 {
1182 'name': 'Item 1', 1182 'name': 'Item 1',
1183 'items': [ 1183 'items': [
1184 { 1184 {
1185 'name': 'Item 1.1' 1185 'name': 'Item 1.1'
1186 } 1186 }
1187 ] 1187 ]
1188 } 1188 }
1189 ]); 1189 ]);
1190 1190
1191 recursivelySetTemplateModel(div, m); 1191 recursivelySetTemplateModel(div, m);
1192 1192
1193 deliverChanges(m); 1193 deliverChanges(m);
1194 m.removeAt(0); 1194 m.removeAt(0);
1195 deliverChanges(m); 1195 deliverChanges(m);
1196 }); 1196 });
1197 1197
1198 test('DeepNested', () { 1198 observeTest('DeepNested', () {
1199 var div = createTestHtml( 1199 var div = createTestHtml(
1200 '<template bind="{{a}}">' 1200 '<template bind="{{a}}">'
1201 '<p>' 1201 '<p>'
1202 '<template bind="{{b}}">' 1202 '<template bind="{{b}}">'
1203 '{{ c }}' 1203 '{{ c }}'
1204 '</template>' 1204 '</template>'
1205 '</p>' 1205 '</p>'
1206 '</template>'); 1206 '</template>');
1207 1207
1208 var m = toSymbols({ 1208 var m = toSymbols({
1209 'a': { 1209 'a': {
1210 'b': { 1210 'b': {
1211 'c': 42 1211 'c': 42
1212 } 1212 }
1213 } 1213 }
1214 }); 1214 });
1215 recursivelySetTemplateModel(div, m); 1215 recursivelySetTemplateModel(div, m);
1216 deliverChanges(m); 1216 deliverChanges(m);
1217 1217
1218 expect(div.nodes[1].tagName, 'P'); 1218 expect(div.nodes[1].tagName, 'P');
1219 expect(div.nodes[1].nodes.first.tagName, 'TEMPLATE'); 1219 expect(div.nodes[1].nodes.first.tagName, 'TEMPLATE');
1220 expect(div.nodes[1].nodes[1].text, '42'); 1220 expect(div.nodes[1].nodes[1].text, '42');
1221 }); 1221 });
1222 1222
1223 test('TemplateContentRemoved', () { 1223 observeTest('TemplateContentRemoved', () {
1224 var div = createTestHtml('<template bind="{{}}">{{ }}</template>'); 1224 var div = createTestHtml('<template bind="{{}}">{{ }}</template>');
1225 var model = 42; 1225 var model = 42;
1226 1226
1227 recursivelySetTemplateModel(div, model); 1227 recursivelySetTemplateModel(div, model);
1228 deliverChanges(model); 1228 deliverChanges(model);
1229 expect(div.nodes[1].text, '42'); 1229 expect(div.nodes[1].text, '42');
1230 expect(div.nodes[0].text, ''); 1230 expect(div.nodes[0].text, '');
1231 }); 1231 });
1232 1232
1233 test('TemplateContentRemovedEmptyArray', () { 1233 observeTest('TemplateContentRemovedEmptyArray', () {
1234 var div = createTestHtml('<template iterate>Remove me</template>'); 1234 var div = createTestHtml('<template iterate>Remove me</template>');
1235 var model = toSymbols([]); 1235 var model = toSymbols([]);
1236 1236
1237 recursivelySetTemplateModel(div, model); 1237 recursivelySetTemplateModel(div, model);
1238 deliverChanges(model); 1238 deliverChanges(model);
1239 expect(div.nodes.length, 1); 1239 expect(div.nodes.length, 1);
1240 expect(div.nodes[0].text, ''); 1240 expect(div.nodes[0].text, '');
1241 }); 1241 });
1242 1242
1243 test('TemplateContentRemovedNested', () { 1243 observeTest('TemplateContentRemovedNested', () {
1244 var div = createTestHtml( 1244 var div = createTestHtml(
1245 '<template bind="{{}}">' 1245 '<template bind="{{}}">'
1246 '{{ a }}' 1246 '{{ a }}'
1247 '<template bind="{{}}">' 1247 '<template bind="{{}}">'
1248 '{{ b }}' 1248 '{{ b }}'
1249 '</template>' 1249 '</template>'
1250 '</template>'); 1250 '</template>');
1251 1251
1252 var model = toSymbolMap({ 1252 var model = toSymbolMap({
1253 'a': 1, 1253 'a': 1,
1254 'b': 2 1254 'b': 2
1255 }); 1255 });
1256 recursivelySetTemplateModel(div, model); 1256 recursivelySetTemplateModel(div, model);
1257 deliverChanges(model); 1257 deliverChanges(model);
1258 1258
1259 expect(div.nodes[0].text, ''); 1259 expect(div.nodes[0].text, '');
1260 expect(div.nodes[1].text, '1'); 1260 expect(div.nodes[1].text, '1');
1261 expect(div.nodes[2].text, ''); 1261 expect(div.nodes[2].text, '');
1262 expect(div.nodes[3].text, '2'); 1262 expect(div.nodes[3].text, '2');
1263 }); 1263 });
1264 1264
1265 test('BindWithUndefinedModel', () { 1265 observeTest('BindWithUndefinedModel', () {
1266 var div = createTestHtml( 1266 var div = createTestHtml(
1267 '<template bind="{{}}" if="{{}}">{{ a }}</template>'); 1267 '<template bind="{{}}" if="{{}}">{{ a }}</template>');
1268 1268
1269 var model = toSymbolMap({'a': 42}); 1269 var model = toSymbolMap({'a': 42});
1270 recursivelySetTemplateModel(div, model); 1270 recursivelySetTemplateModel(div, model);
1271 deliverChanges(model); 1271 deliverChanges(model);
1272 expect(div.nodes[1].text, '42'); 1272 expect(div.nodes[1].text, '42');
1273 1273
1274 model = null; 1274 model = null;
1275 recursivelySetTemplateModel(div, model); 1275 recursivelySetTemplateModel(div, model);
1276 deliverChanges(model); 1276 deliverChanges(model);
1277 expect(div.nodes.length, 1); 1277 expect(div.nodes.length, 1);
1278 1278
1279 model = toSymbols({'a': 42}); 1279 model = toSymbols({'a': 42});
1280 recursivelySetTemplateModel(div, model); 1280 recursivelySetTemplateModel(div, model);
1281 deliverChanges(model); 1281 deliverChanges(model);
1282 expect(div.nodes[1].text, '42'); 1282 expect(div.nodes[1].text, '42');
1283 }); 1283 });
1284 1284
1285 test('BindNested', () { 1285 observeTest('BindNested', () {
1286 var div = createTestHtml( 1286 var div = createTestHtml(
1287 '<template bind="{{}}">' 1287 '<template bind="{{}}">'
1288 'Name: {{ name }}' 1288 'Name: {{ name }}'
1289 '<template bind="{{wife}}" if="{{wife}}">' 1289 '<template bind="{{wife}}" if="{{wife}}">'
1290 'Wife: {{ name }}' 1290 'Wife: {{ name }}'
1291 '</template>' 1291 '</template>'
1292 '<template bind="{{child}}" if="{{child}}">' 1292 '<template bind="{{child}}" if="{{child}}">'
1293 'Child: {{ name }}' 1293 'Child: {{ name }}'
1294 '</template>' 1294 '</template>'
1295 '</template>'); 1295 '</template>');
(...skipping 15 matching lines...) Expand all
1311 deliverChanges(m); 1311 deliverChanges(m);
1312 expect(div.nodes.length, 6); 1312 expect(div.nodes.length, 6);
1313 expect(div.nodes[5].text, 'Child: Dwight'); 1313 expect(div.nodes[5].text, 'Child: Dwight');
1314 1314
1315 m.remove(sym('wife')); 1315 m.remove(sym('wife'));
1316 deliverChanges(m); 1316 deliverChanges(m);
1317 expect(div.nodes.length, 5); 1317 expect(div.nodes.length, 5);
1318 expect(div.nodes[4].text, 'Child: Dwight'); 1318 expect(div.nodes[4].text, 'Child: Dwight');
1319 }); 1319 });
1320 1320
1321 test('BindRecursive', () { 1321 observeTest('BindRecursive', () {
1322 var div = createTestHtml( 1322 var div = createTestHtml(
1323 '<template bind="{{}}" if="{{}}" id="t">' 1323 '<template bind="{{}}" if="{{}}" id="t">'
1324 'Name: {{ name }}' 1324 'Name: {{ name }}'
1325 '<template bind="{{friend}}" if="{{friend}}" ref="t"></template>' 1325 '<template bind="{{friend}}" if="{{friend}}" ref="t"></template>'
1326 '</template>'); 1326 '</template>');
1327 1327
1328 var m = toSymbols({ 1328 var m = toSymbols({
1329 'name': 'Fry', 1329 'name': 'Fry',
1330 'friend': { 1330 'friend': {
1331 'name': 'Bender' 1331 'name': 'Bender'
(...skipping 10 matching lines...) Expand all
1342 deliverChanges(m); 1342 deliverChanges(m);
1343 expect(div.nodes.length, 7); 1343 expect(div.nodes.length, 7);
1344 expect(div.nodes[5].text, 'Name: Leela'); 1344 expect(div.nodes[5].text, 'Name: Leela');
1345 1345
1346 m[sym('friend')] = toSymbols({'name': 'Leela'}); 1346 m[sym('friend')] = toSymbols({'name': 'Leela'});
1347 deliverChanges(m); 1347 deliverChanges(m);
1348 expect(div.nodes.length, 5); 1348 expect(div.nodes.length, 5);
1349 expect(div.nodes[3].text, 'Name: Leela'); 1349 expect(div.nodes[3].text, 'Name: Leela');
1350 }); 1350 });
1351 1351
1352 test('ChangeFromBindToRepeat', () { 1352 observeTest('ChangeFromBindToRepeat', () {
1353 var div = createTestHtml( 1353 var div = createTestHtml(
1354 '<template bind="{{a}}">' 1354 '<template bind="{{a}}">'
1355 '{{ length }}' 1355 '{{ length }}'
1356 '</template>'); 1356 '</template>');
1357 var template = div.nodes.first; 1357 var template = div.nodes.first;
1358 1358
1359 // Note: this test data is a little different from the JS version, because 1359 // Note: this test data is a little different from the JS version, because
1360 // we allow binding to the "length" field of the Map in preference to 1360 // we allow binding to the "length" field of the Map in preference to
1361 // binding keys. 1361 // binding keys.
1362 var m = toSymbols({ 1362 var m = toSymbols({
(...skipping 19 matching lines...) Expand all
1382 expect(div.nodes[3].text, '2'); 1382 expect(div.nodes[3].text, '2');
1383 1383
1384 template.unbind('repeat'); 1384 template.unbind('repeat');
1385 template.bind('bind', m, 'a.1.b'); 1385 template.bind('bind', m, 'a.1.b');
1386 1386
1387 deliverChanges(m); 1387 deliverChanges(m);
1388 expect(div.nodes.length, 2); 1388 expect(div.nodes.length, 2);
1389 expect(div.nodes[1].text, '4'); 1389 expect(div.nodes[1].text, '4');
1390 }); 1390 });
1391 1391
1392 test('ChangeRefId', () { 1392 observeTest('ChangeRefId', () {
1393 var div = createTestHtml( 1393 var div = createTestHtml(
1394 '<template id="a">a:{{ }}</template>' 1394 '<template id="a">a:{{ }}</template>'
1395 '<template id="b">b:{{ }}</template>' 1395 '<template id="b">b:{{ }}</template>'
1396 '<template repeat="{{}}">' 1396 '<template repeat="{{}}">'
1397 '<template ref="a" bind="{{}}"></template>' 1397 '<template ref="a" bind="{{}}"></template>'
1398 '</template>'); 1398 '</template>');
1399 var model = toSymbols([]); 1399 var model = toSymbols([]);
1400 recursivelySetTemplateModel(div, model); 1400 recursivelySetTemplateModel(div, model);
1401 deliverChanges(model); 1401 deliverChanges(model);
1402 1402
1403 expect(div.nodes.length, 3); 1403 expect(div.nodes.length, 3);
1404 1404
1405 document.getElementById('a').id = 'old-a'; 1405 document.getElementById('a').id = 'old-a';
1406 document.getElementById('b').id = 'a'; 1406 document.getElementById('b').id = 'a';
1407 1407
1408 model..add(1)..add(2); 1408 model..add(1)..add(2);
1409 deliverChanges(model); 1409 deliverChanges(model);
1410 1410
1411 expect(div.nodes.length, 7); 1411 expect(div.nodes.length, 7);
1412 expect(div.nodes[4].text, 'b:1'); 1412 expect(div.nodes[4].text, 'b:1');
1413 expect(div.nodes[6].text, 'b:2'); 1413 expect(div.nodes[6].text, 'b:2');
1414 }); 1414 });
1415 1415
1416 test('Content', () { 1416 observeTest('Content', () {
1417 var div = createTestHtml( 1417 var div = createTestHtml(
1418 '<template><a></a></template>' 1418 '<template><a></a></template>'
1419 '<template><b></b></template>'); 1419 '<template><b></b></template>');
1420 var templateA = div.nodes.first; 1420 var templateA = div.nodes.first;
1421 var templateB = div.nodes.last; 1421 var templateB = div.nodes.last;
1422 var contentA = templateA.content; 1422 var contentA = templateA.content;
1423 var contentB = templateB.content; 1423 var contentB = templateB.content;
1424 expect(contentA, isNotNull); 1424 expect(contentA, isNotNull);
1425 1425
1426 expect(templateA.document, isNot(equals(contentA.document))); 1426 expect(templateA.document, isNot(equals(contentA.document)));
1427 expect(templateB.document, isNot(equals(contentB.document))); 1427 expect(templateB.document, isNot(equals(contentB.document)));
1428 1428
1429 expect(templateB.document, templateA.document); 1429 expect(templateB.document, templateA.document);
1430 expect(contentB.document, contentA.document); 1430 expect(contentB.document, contentA.document);
1431 1431
1432 expect(templateA.document.window, window); 1432 expect(templateA.document.window, window);
1433 expect(templateB.document.window, window); 1433 expect(templateB.document.window, window);
1434 1434
1435 expect(contentA.document.window, null); 1435 expect(contentA.document.window, null);
1436 expect(contentB.document.window, null); 1436 expect(contentB.document.window, null);
1437 1437
1438 expect(contentA.nodes.last, contentA.nodes.first); 1438 expect(contentA.nodes.last, contentA.nodes.first);
1439 expect(contentA.nodes.first.tagName, 'A'); 1439 expect(contentA.nodes.first.tagName, 'A');
1440 1440
1441 expect(contentB.nodes.last, contentB.nodes.first); 1441 expect(contentB.nodes.last, contentB.nodes.first);
1442 expect(contentB.nodes.first.tagName, 'B'); 1442 expect(contentB.nodes.first.tagName, 'B');
1443 }); 1443 });
1444 1444
1445 test('NestedContent', () { 1445 observeTest('NestedContent', () {
1446 var div = createTestHtml( 1446 var div = createTestHtml(
1447 '<template>' 1447 '<template>'
1448 '<template></template>' 1448 '<template></template>'
1449 '</template>'); 1449 '</template>');
1450 var templateA = div.nodes.first; 1450 var templateA = div.nodes.first;
1451 var templateB = templateA.content.nodes.first; 1451 var templateB = templateA.content.nodes.first;
1452 1452
1453 expect(templateB.document, templateA.content.document); 1453 expect(templateB.document, templateA.content.document);
1454 expect(templateB.content.document, templateA.content.document); 1454 expect(templateB.content.document, templateA.content.document);
1455 }); 1455 });
1456 1456
1457 test('BindShadowDOM', () { 1457 observeTest('BindShadowDOM', () {
1458 if (ShadowRoot.supported) { 1458 if (ShadowRoot.supported) {
1459 var root = createShadowTestHtml( 1459 var root = createShadowTestHtml(
1460 '<template bind="{{}}">Hi {{ name }}</template>'); 1460 '<template bind="{{}}">Hi {{ name }}</template>');
1461 var model = toSymbolMap({'name': 'Leela'}); 1461 var model = toSymbolMap({'name': 'Leela'});
1462 recursivelySetTemplateModel(root, model); 1462 recursivelySetTemplateModel(root, model);
1463 deliverChanges(model); 1463 deliverChanges(model);
1464 expect(root.nodes[1].text, 'Hi Leela'); 1464 expect(root.nodes[1].text, 'Hi Leela');
1465 } 1465 }
1466 }); 1466 });
1467 1467
1468 test('BindShadowDOM bindModel', () { 1468 observeTest('BindShadowDOM bindModel', () {
1469 if (ShadowRoot.supported) { 1469 if (ShadowRoot.supported) {
1470 var root = createShadowTestHtml('Hi {{ name }}'); 1470 var root = createShadowTestHtml('Hi {{ name }}');
1471 var model = toSymbolMap({'name': 'Leela'}); 1471 var model = toSymbolMap({'name': 'Leela'});
1472 mdv.bindModel(root, model); 1472 mdv.bindModel(root, model);
1473 deliverChangeRecords(); 1473 performMicrotaskCheckpoint();
1474 expect(root.text, 'Hi Leela'); 1474 expect(root.text, 'Hi Leela');
1475 } 1475 }
1476 }); 1476 });
1477 1477
1478 test('bindModel to polyfilled shadow root', () { 1478 observeTest('bindModel to polyfilled shadow root', () {
1479 var root = createTestHtml('Hi {{ name }}'); 1479 var root = createTestHtml('Hi {{ name }}');
1480 var model = toSymbolMap({'name': 'Leela'}); 1480 var model = toSymbolMap({'name': 'Leela'});
1481 mdv.bindModel(root, model); 1481 mdv.bindModel(root, model);
1482 deliverChangeRecords(); 1482 performMicrotaskCheckpoint();
1483 expect(root.text, 'Hi Leela'); 1483 expect(root.text, 'Hi Leela');
1484 }); 1484 });
1485 1485
1486 test('BindShadowDOM Template Ref', () { 1486 observeTest('BindShadowDOM Template Ref', () {
1487 if (ShadowRoot.supported) { 1487 if (ShadowRoot.supported) {
1488 var root = createShadowTestHtml( 1488 var root = createShadowTestHtml(
1489 '<template id=foo>Hi</template><template bind ref=foo></template>'); 1489 '<template id=foo>Hi</template><template bind ref=foo></template>');
1490 recursivelySetTemplateModel(root, toSymbolMap({})); 1490 recursivelySetTemplateModel(root, toSymbolMap({}));
1491 deliverChangeRecords(); 1491 performMicrotaskCheckpoint();
1492 expect(root.nodes.length, 3); 1492 expect(root.nodes.length, 3);
1493 } 1493 }
1494 }); 1494 });
1495 1495
1496 // https://github.com/toolkitchen/mdv/issues/8 1496 // https://github.com/toolkitchen/mdv/issues/8
1497 test('UnbindingInNestedBind', () { 1497 observeTest('UnbindingInNestedBind', () {
1498 var div = createTestHtml( 1498 var div = createTestHtml(
1499 '<template bind="{{outer}}" if="{{outer}}" syntax="testHelper">' 1499 '<template bind="{{outer}}" if="{{outer}}" syntax="testHelper">'
1500 '<template bind="{{inner}}" if="{{inner}}">' 1500 '<template bind="{{inner}}" if="{{inner}}">'
1501 '{{ age }}' 1501 '{{ age }}'
1502 '</template>' 1502 '</template>'
1503 '</template>'); 1503 '</template>');
1504 1504
1505 var syntax = new UnbindingInNestedBindSyntax(); 1505 var syntax = new UnbindingInNestedBindSyntax();
1506 TemplateElement.syntax['testHelper'] = syntax; 1506 TemplateElement.syntax['testHelper'] = syntax;
1507 try { 1507 try {
(...skipping 20 matching lines...) Expand all
1528 syntax.expectedAge = 2; 1528 syntax.expectedAge = 2;
1529 1529
1530 deliverChanges(model); 1530 deliverChanges(model);
1531 expect(syntax.count, 2); 1531 expect(syntax.count, 2);
1532 } finally { 1532 } finally {
1533 TemplateElement.syntax.remove('testHelper'); 1533 TemplateElement.syntax.remove('testHelper');
1534 } 1534 }
1535 }); 1535 });
1536 1536
1537 // https://github.com/toolkitchen/mdv/issues/8 1537 // https://github.com/toolkitchen/mdv/issues/8
1538 test('DontCreateInstancesForAbandonedIterators', () { 1538 observeTest('DontCreateInstancesForAbandonedIterators', () {
1539 var div = createTestHtml( 1539 var div = createTestHtml(
1540 '<template bind="{{}} {{}}">' 1540 '<template bind="{{}} {{}}">'
1541 '<template bind="{{}}">Foo' 1541 '<template bind="{{}}">Foo'
1542 '</template>' 1542 '</template>'
1543 '</template>'); 1543 '</template>');
1544 recursivelySetTemplateModel(div, null); 1544 recursivelySetTemplateModel(div, null);
1545 // TODO(jmesserly): how to fix this test? 1545 performMicrotaskCheckpoint();
1546 // Perhaps revive the original?
1547 // https://github.com/toolkitchen/mdv/commit/8bc1e3466aeb6930150c0d3148f0e83 0184bf599#L3R1278
1548 //expect(!!ChangeSummary._errorThrownDuringCallback, false);
1549 }); 1546 });
1550 1547
1551 test('CreateInstance', () { 1548 observeTest('CreateInstance', () {
1552 TemplateElement.syntax['Test'] = new TestBindingSyntax(); 1549 TemplateElement.syntax['Test'] = new TestBindingSyntax();
1553 try { 1550 try {
1554 var div = createTestHtml( 1551 var div = createTestHtml(
1555 '<template bind="{{a}}">' 1552 '<template bind="{{a}}">'
1556 '<template bind="{{b}}">' 1553 '<template bind="{{b}}">'
1557 '{{ foo }}:{{ replaceme }}' 1554 '{{ foo }}:{{ replaceme }}'
1558 '</template>' 1555 '</template>'
1559 '</template>'); 1556 '</template>');
1560 var outer = div.nodes.first; 1557 var outer = div.nodes.first;
1561 var model = toSymbolMap({'b': {'foo': 'bar'}}); 1558 var model = toSymbolMap({'b': {'foo': 'bar'}});
1562 1559
1563 var host = new DivElement(); 1560 var host = new DivElement();
1564 var instance = outer.createInstance(model, 'Test'); 1561 var instance = outer.createInstance(model, 'Test');
1565 expect(outer.content.nodes.first, instance.nodes.first.ref); 1562 expect(outer.content.nodes.first, instance.nodes.first.ref);
1566 expect(instance.firstChild.attributes['syntax'], 'Test'); 1563 expect(instance.firstChild.attributes['syntax'], 'Test');
1567 1564
1568 host.append(instance); 1565 host.append(instance);
1569 deliverChangeRecords(); 1566 performMicrotaskCheckpoint();
1570 expect(host.firstChild.nextNode.text, 'bar:replaced'); 1567 expect(host.firstChild.nextNode.text, 'bar:replaced');
1571 } finally { 1568 } finally {
1572 TemplateElement.syntax.remove('Test'); 1569 TemplateElement.syntax.remove('Test');
1573 } 1570 }
1574 }); 1571 });
1575 1572
1576 test('Bootstrap', () { 1573 observeTest('Bootstrap', () {
1577 var div = new DivElement(); 1574 var div = new DivElement();
1578 div.innerHtml = 1575 div.innerHtml =
1579 '<template>' 1576 '<template>'
1580 '<div></div>' 1577 '<div></div>'
1581 '<template>' 1578 '<template>'
1582 'Hello' 1579 'Hello'
1583 '</template>' 1580 '</template>'
1584 '</template>'; 1581 '</template>';
1585 1582
1586 TemplateElement.bootstrap(div); 1583 TemplateElement.bootstrap(div);
(...skipping 13 matching lines...) Expand all
1600 '</template>'; 1597 '</template>';
1601 1598
1602 TemplateElement.bootstrap(template); 1599 TemplateElement.bootstrap(template);
1603 template2 = template.content.nodes.first; 1600 template2 = template.content.nodes.first;
1604 expect(template2.content.nodes.length, 2); 1601 expect(template2.content.nodes.length, 2);
1605 var template3 = template2.content.nodes.first.nextNode; 1602 var template3 = template2.content.nodes.first.nextNode;
1606 expect(template3.content.nodes.length, 1); 1603 expect(template3.content.nodes.length, 1);
1607 expect(template3.content.nodes.first.text, 'Hello'); 1604 expect(template3.content.nodes.first.text, 'Hello');
1608 }); 1605 });
1609 1606
1610 test('instanceCreated hack', () { 1607 observeTest('instanceCreated hack', () {
1611 var called = false; 1608 var called = false;
1612 var sub = mdv.instanceCreated.listen((node) { 1609 var sub = mdv.instanceCreated.listen((node) {
1613 called = true; 1610 called = true;
1614 expect(node.nodeType, Node.DOCUMENT_FRAGMENT_NODE); 1611 expect(node.nodeType, Node.DOCUMENT_FRAGMENT_NODE);
1615 }); 1612 });
1616 1613
1617 var div = createTestHtml('<template bind="{{}}">Foo</template>'); 1614 var div = createTestHtml('<template bind="{{}}">Foo</template>');
1618 expect(called, false); 1615 expect(called, false);
1619 1616
1620 recursivelySetTemplateModel(div, null); 1617 recursivelySetTemplateModel(div, null);
1621 deliverChangeRecords(); 1618 performMicrotaskCheckpoint();
1622 expect(called, true); 1619 expect(called, true);
1623 1620
1624 sub.cancel(); 1621 sub.cancel();
1625 }); 1622 });
1626 } 1623 }
1627 1624
1628 class TestBindingSyntax extends CustomBindingSyntax { 1625 class TestBindingSyntax extends CustomBindingSyntax {
1629 getBinding(model, String path, name, node) { 1626 getBinding(model, String path, name, node) {
1630 if (path.trim() == 'replaceme') return new ObservableBox('replaced'); 1627 if (path.trim() == 'replaceme') return new ObservableBox('replaced');
1631 return null; 1628 return null;
1632 } 1629 }
1633 } 1630 }
1634 1631
1635 class UnbindingInNestedBindSyntax extends CustomBindingSyntax { 1632 class UnbindingInNestedBindSyntax extends CustomBindingSyntax {
1636 int expectedAge = 42; 1633 int expectedAge = 42;
1637 int count = 0; 1634 int count = 0;
1638 1635
1639 getBinding(model, path, name, node) { 1636 getBinding(model, path, name, node) {
1640 if (name != 'text' || path != 'age') 1637 if (name != 'text' || path != 'age')
1641 return; 1638 return;
1642 1639
1643 expect(model[sym('age')], expectedAge); 1640 expect(model[sym('age')], expectedAge);
1644 count++; 1641 count++;
1645 } 1642 }
1646 } 1643 }
1647 1644
1648 /** Verifies that the model is Observable, then calls [deliverChangeRecords]. */ 1645 /**
1646 * Verifies that the model is Observable, then calls
1647 * [performMicrotaskCheckpoint].
1648 */
1649 void deliverChanges(model) { 1649 void deliverChanges(model) {
1650 expectObservable(model); 1650 expectObservable(model);
1651 deliverChangeRecords(); 1651 performMicrotaskCheckpoint();
1652 } 1652 }
1653 1653
1654 void expectObservable(model) { 1654 void expectObservable(model) {
1655 if (model is! Observable) { 1655 if (model is! Observable) {
1656 // This is here to eagerly catch a bug in the test; it means the test 1656 // This is here to eagerly catch a bug in the test; it means the test
1657 // forgot a toSymbols somewhere. 1657 // forgot a toSymbols somewhere.
1658 expect(identical(toSymbols(model), model), true, 1658 expect(identical(toSymbols(model), model), true,
1659 reason: 'model type "${model.runtimeType}" should be observable'); 1659 reason: 'model type "${model.runtimeType}" should be observable');
1660 return; 1660 return;
1661 } 1661 }
(...skipping 20 matching lines...) Expand all
1682 k = k is String ? sym(k) : _deepToSymbol(k); 1682 k = k is String ? sym(k) : _deepToSymbol(k);
1683 result[k] = _deepToSymbol(v); 1683 result[k] = _deepToSymbol(v);
1684 }); 1684 });
1685 return result; 1685 return result;
1686 } 1686 }
1687 if (value is Iterable) { 1687 if (value is Iterable) {
1688 return value.map(_deepToSymbol).toList(); 1688 return value.map(_deepToSymbol).toList();
1689 } 1689 }
1690 return value; 1690 return value;
1691 } 1691 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698