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

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

Issue 27618002: package:observe fix various api issues (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 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
« no previous file with comments | « pkg/mdv/test/node_bindings_test.dart ('k') | pkg/observe/lib/html.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 performMicrotaskCheckpoint(); 85 performMicrotaskCheckpoint();
86 expect(div.nodes.length, 2); 86 expect(div.nodes.length, 2);
87 expect(div.nodes.last.text, 'text'); 87 expect(div.nodes.last.text, 'text');
88 }); 88 });
89 89
90 observeTest('Template bind, no parent', () { 90 observeTest('Template bind, no parent', () {
91 var div = createTestHtml('<template bind>text</template>'); 91 var div = createTestHtml('<template bind>text</template>');
92 var template = div.nodes[0]; 92 var template = div.nodes[0];
93 template.remove(); 93 template.remove();
94 94
95 recursivelySetTemplateModel(template, toSymbolMap({})); 95 recursivelySetTemplateModel(template, toObservable({}));
96 performMicrotaskCheckpoint(); 96 performMicrotaskCheckpoint();
97 expect(template.nodes.length, 0); 97 expect(template.nodes.length, 0);
98 expect(template.nextNode, null); 98 expect(template.nextNode, null);
99 }); 99 });
100 100
101 observeTest('Template bind, no defaultView', () { 101 observeTest('Template bind, no defaultView', () {
102 var div = createTestHtml('<template bind>text</template>'); 102 var div = createTestHtml('<template bind>text</template>');
103 var template = div.nodes[0]; 103 var template = div.nodes[0];
104 var doc = document.implementation.createHtmlDocument(''); 104 var doc = document.implementation.createHtmlDocument('');
105 doc.adoptNode(div); 105 doc.adoptNode(div);
106 recursivelySetTemplateModel(template, toSymbolMap({})); 106 recursivelySetTemplateModel(template, toObservable({}));
107 performMicrotaskCheckpoint(); 107 performMicrotaskCheckpoint();
108 expect(div.nodes.length, 1); 108 expect(div.nodes.length, 1);
109 }); 109 });
110 110
111 observeTest('Template-Empty Bind', () { 111 observeTest('Template-Empty Bind', () {
112 var div = createTestHtml('<template bind>text</template>'); 112 var div = createTestHtml('<template bind>text</template>');
113 recursivelySetTemplateModel(div, null); 113 recursivelySetTemplateModel(div, null);
114 performMicrotaskCheckpoint(); 114 performMicrotaskCheckpoint();
115 expect(div.nodes.length, 2); 115 expect(div.nodes.length, 2);
116 expect(div.nodes.last.text, 'text'); 116 expect(div.nodes.last.text, 'text');
117 }); 117 });
118 118
119 observeTest('Template Bind If', () { 119 observeTest('Template Bind If', () {
120 var div = createTestHtml('<template bind if="{{ foo }}">text</template>'); 120 var div = createTestHtml('<template bind if="{{ foo }}">text</template>');
121 // Note: changed this value from 0->null because zero is not falsey in Dart. 121 // Note: changed this value from 0->null because zero is not falsey in Dart.
122 // See https://code.google.com/p/dart/issues/detail?id=11956 122 // See https://code.google.com/p/dart/issues/detail?id=11956
123 var m = toSymbolMap({ 'foo': null }); 123 var m = toObservable({ 'foo': null });
124 recursivelySetTemplateModel(div, m); 124 recursivelySetTemplateModel(div, m);
125 performMicrotaskCheckpoint(); 125 performMicrotaskCheckpoint();
126 expect(div.nodes.length, 1); 126 expect(div.nodes.length, 1);
127 127
128 m[#foo] = 1; 128 m['foo'] = 1;
129 performMicrotaskCheckpoint(); 129 performMicrotaskCheckpoint();
130 expect(div.nodes.length, 2); 130 expect(div.nodes.length, 2);
131 expect(div.lastChild.text, 'text'); 131 expect(div.lastChild.text, 'text');
132 }); 132 });
133 133
134 observeTest('Template Bind If, 2', () { 134 observeTest('Template Bind If, 2', () {
135 var div = createTestHtml( 135 var div = createTestHtml(
136 '<template bind="{{ foo }}" if="{{ bar }}">{{ bat }}</template>'); 136 '<template bind="{{ foo }}" if="{{ bar }}">{{ bat }}</template>');
137 var m = toSymbolMap({ 'bar': null, 'foo': { 'bat': 'baz' } }); 137 var m = toObservable({ 'bar': null, 'foo': { 'bat': 'baz' } });
138 recursivelySetTemplateModel(div, m); 138 recursivelySetTemplateModel(div, m);
139 performMicrotaskCheckpoint(); 139 performMicrotaskCheckpoint();
140 expect(div.nodes.length, 1); 140 expect(div.nodes.length, 1);
141 141
142 m[#bar] = 1; 142 m['bar'] = 1;
143 performMicrotaskCheckpoint(); 143 performMicrotaskCheckpoint();
144 expect(div.nodes.length, 2); 144 expect(div.nodes.length, 2);
145 expect(div.lastChild.text, 'baz'); 145 expect(div.lastChild.text, 'baz');
146 }); 146 });
147 147
148 observeTest('Template If', () { 148 observeTest('Template If', () {
149 var div = createTestHtml('<template if="{{ foo }}">{{ value }}</template>'); 149 var div = createTestHtml('<template if="{{ foo }}">{{ value }}</template>');
150 // Note: changed this value from 0->null because zero is not falsey in Dart. 150 // Note: changed this value from 0->null because zero is not falsey in Dart.
151 // See https://code.google.com/p/dart/issues/detail?id=11956 151 // See https://code.google.com/p/dart/issues/detail?id=11956
152 var m = toSymbolMap({ 'foo': null, 'value': 'foo' }); 152 var m = toObservable({ 'foo': null, 'value': 'foo' });
153 recursivelySetTemplateModel(div, m); 153 recursivelySetTemplateModel(div, m);
154 performMicrotaskCheckpoint(); 154 performMicrotaskCheckpoint();
155 expect(div.nodes.length, 1); 155 expect(div.nodes.length, 1);
156 156
157 m[#foo] = 1; 157 m['foo'] = 1;
158 performMicrotaskCheckpoint(); 158 performMicrotaskCheckpoint();
159 expect(div.nodes.length, 2); 159 expect(div.nodes.length, 2);
160 expect(div.lastChild.text, 'foo'); 160 expect(div.lastChild.text, 'foo');
161 }); 161 });
162 162
163 observeTest('Template Repeat If', () { 163 observeTest('Template Repeat If', () {
164 var div = createTestHtml( 164 var div = createTestHtml(
165 '<template repeat="{{ foo }}" if="{{ bar }}">{{ }}</template>'); 165 '<template repeat="{{ foo }}" if="{{ bar }}">{{ }}</template>');
166 // Note: changed this value from 0->null because zero is not falsey in Dart. 166 // Note: changed this value from 0->null because zero is not falsey in Dart.
167 // See https://code.google.com/p/dart/issues/detail?id=11956 167 // See https://code.google.com/p/dart/issues/detail?id=11956
168 var m = toSymbolMap({ 'bar': null, 'foo': [1, 2, 3] }); 168 var m = toObservable({ 'bar': null, 'foo': [1, 2, 3] });
169 recursivelySetTemplateModel(div, m); 169 recursivelySetTemplateModel(div, m);
170 performMicrotaskCheckpoint(); 170 performMicrotaskCheckpoint();
171 expect(div.nodes.length, 1); 171 expect(div.nodes.length, 1);
172 172
173 m[#bar] = 1; 173 m['bar'] = 1;
174 performMicrotaskCheckpoint(); 174 performMicrotaskCheckpoint();
175 expect(div.nodes.length, 4); 175 expect(div.nodes.length, 4);
176 expect(div.nodes[1].text, '1'); 176 expect(div.nodes[1].text, '1');
177 expect(div.nodes[2].text, '2'); 177 expect(div.nodes[2].text, '2');
178 expect(div.nodes[3].text, '3'); 178 expect(div.nodes[3].text, '3');
179 }); 179 });
180 180
181 observeTest('TextTemplateWithNullStringBinding', () { 181 observeTest('TextTemplateWithNullStringBinding', () {
182 var div = createTestHtml('<template bind={{}}>a{{b}}c</template>'); 182 var div = createTestHtml('<template bind={{}}>a{{b}}c</template>');
183 var model = toSymbolMap({'b': 'B'}); 183 var model = toObservable({'b': 'B'});
184 recursivelySetTemplateModel(div, model); 184 recursivelySetTemplateModel(div, model);
185 185
186 deliverChanges(model); 186 deliverChanges(model);
187 expect(div.nodes.length, 2); 187 expect(div.nodes.length, 2);
188 expect(div.nodes.last.text, 'aBc'); 188 expect(div.nodes.last.text, 'aBc');
189 189
190 model[#b] = 'b'; 190 model['b'] = 'b';
191 deliverChanges(model); 191 deliverChanges(model);
192 expect(div.nodes.last.text, 'abc'); 192 expect(div.nodes.last.text, 'abc');
193 193
194 model[#b] = null; 194 model['b'] = null;
195 deliverChanges(model); 195 deliverChanges(model);
196 expect(div.nodes.last.text, 'ac'); 196 expect(div.nodes.last.text, 'ac');
197 197
198 model = null; 198 model = null;
199 deliverChanges(model); 199 deliverChanges(model);
200 // setting model isn't observable. 200 // setting model isn't observable.
201 expect(div.nodes.last.text, 'ac'); 201 expect(div.nodes.last.text, 'ac');
202 }); 202 });
203 203
204 observeTest('TextTemplateWithBindingPath', () { 204 observeTest('TextTemplateWithBindingPath', () {
205 var div = createTestHtml( 205 var div = createTestHtml(
206 '<template bind="{{ data }}">a{{b}}c</template>'); 206 '<template bind="{{ data }}">a{{b}}c</template>');
207 var model = toSymbolMap({ 'data': {'b': 'B'} }); 207 var model = toObservable({ 'data': {'b': 'B'} });
208 recursivelySetTemplateModel(div, model); 208 recursivelySetTemplateModel(div, model);
209 209
210 deliverChanges(model); 210 deliverChanges(model);
211 expect(div.nodes.length, 2); 211 expect(div.nodes.length, 2);
212 expect(div.nodes.last.text, 'aBc'); 212 expect(div.nodes.last.text, 'aBc');
213 213
214 model[#data][#b] = 'b'; 214 model['data']['b'] = 'b';
215 deliverChanges(model); 215 deliverChanges(model);
216 expect(div.nodes.last.text, 'abc'); 216 expect(div.nodes.last.text, 'abc');
217 217
218 model[#data] = toSymbols({'b': 'X'}); 218 model['data'] = toObservable({'b': 'X'});
219 deliverChanges(model); 219 deliverChanges(model);
220 expect(div.nodes.last.text, 'aXc'); 220 expect(div.nodes.last.text, 'aXc');
221 221
222 model[#data] = null; 222 model['data'] = null;
223 deliverChanges(model); 223 deliverChanges(model);
224 expect(div.nodes.last.text, 'ac'); 224 expect(div.nodes.last.text, 'ac');
225 }); 225 });
226 226
227 observeTest('TextTemplateWithBindingAndConditional', () { 227 observeTest('TextTemplateWithBindingAndConditional', () {
228 var div = createTestHtml( 228 var div = createTestHtml(
229 '<template bind="{{}}" if="{{ d }}">a{{b}}c</template>'); 229 '<template bind="{{}}" if="{{ d }}">a{{b}}c</template>');
230 var model = toSymbolMap({'b': 'B', 'd': 1}); 230 var model = toObservable({'b': 'B', 'd': 1});
231 recursivelySetTemplateModel(div, model); 231 recursivelySetTemplateModel(div, model);
232 232
233 deliverChanges(model); 233 deliverChanges(model);
234 expect(div.nodes.length, 2); 234 expect(div.nodes.length, 2);
235 expect(div.nodes.last.text, 'aBc'); 235 expect(div.nodes.last.text, 'aBc');
236 236
237 model[#b] = 'b'; 237 model['b'] = 'b';
238 deliverChanges(model); 238 deliverChanges(model);
239 expect(div.nodes.last.text, 'abc'); 239 expect(div.nodes.last.text, 'abc');
240 240
241 // TODO(jmesserly): MDV set this to empty string and relies on JS conversion 241 // TODO(jmesserly): MDV set this to empty string and relies on JS conversion
242 // rules. Is that intended? 242 // rules. Is that intended?
243 // See https://github.com/toolkitchen/mdv/issues/59 243 // See https://github.com/toolkitchen/mdv/issues/59
244 model[#d] = null; 244 model['d'] = null;
245 deliverChanges(model); 245 deliverChanges(model);
246 expect(div.nodes.length, 1); 246 expect(div.nodes.length, 1);
247 247
248 model[#d] = 'here'; 248 model['d'] = 'here';
249 model[#b] = 'd'; 249 model['b'] = 'd';
250 250
251 deliverChanges(model); 251 deliverChanges(model);
252 expect(div.nodes.length, 2); 252 expect(div.nodes.length, 2);
253 expect(div.nodes.last.text, 'adc'); 253 expect(div.nodes.last.text, 'adc');
254 }); 254 });
255 255
256 observeTest('TemplateWithTextBinding2', () { 256 observeTest('TemplateWithTextBinding2', () {
257 var div = createTestHtml( 257 var div = createTestHtml(
258 '<template bind="{{ b }}">a{{value}}c</template>'); 258 '<template bind="{{ b }}">a{{value}}c</template>');
259 expect(div.nodes.length, 1); 259 expect(div.nodes.length, 1);
260 var model = toSymbolMap({'b': {'value': 'B'}}); 260 var model = toObservable({'b': {'value': 'B'}});
261 recursivelySetTemplateModel(div, model); 261 recursivelySetTemplateModel(div, model);
262 262
263 deliverChanges(model); 263 deliverChanges(model);
264 expect(div.nodes.length, 2); 264 expect(div.nodes.length, 2);
265 expect(div.nodes.last.text, 'aBc'); 265 expect(div.nodes.last.text, 'aBc');
266 266
267 model[#b] = toSymbols({'value': 'b'}); 267 model['b'] = toObservable({'value': 'b'});
268 deliverChanges(model); 268 deliverChanges(model);
269 expect(div.nodes.last.text, 'abc'); 269 expect(div.nodes.last.text, 'abc');
270 }); 270 });
271 271
272 observeTest('TemplateWithAttributeBinding', () { 272 observeTest('TemplateWithAttributeBinding', () {
273 var div = createTestHtml( 273 var div = createTestHtml(
274 '<template bind="{{}}">' 274 '<template bind="{{}}">'
275 '<div foo="a{{b}}c"></div>' 275 '<div foo="a{{b}}c"></div>'
276 '</template>'); 276 '</template>');
277 var model = toSymbolMap({'b': 'B'}); 277 var model = toObservable({'b': 'B'});
278 recursivelySetTemplateModel(div, model); 278 recursivelySetTemplateModel(div, model);
279 279
280 deliverChanges(model); 280 deliverChanges(model);
281 expect(div.nodes.length, 2); 281 expect(div.nodes.length, 2);
282 expect(div.nodes.last.attributes['foo'], 'aBc'); 282 expect(div.nodes.last.attributes['foo'], 'aBc');
283 283
284 model[#b] = 'b'; 284 model['b'] = 'b';
285 deliverChanges(model); 285 deliverChanges(model);
286 expect(div.nodes.last.attributes['foo'], 'abc'); 286 expect(div.nodes.last.attributes['foo'], 'abc');
287 287
288 model[#b] = 'X'; 288 model['b'] = 'X';
289 deliverChanges(model); 289 deliverChanges(model);
290 expect(div.nodes.last.attributes['foo'], 'aXc'); 290 expect(div.nodes.last.attributes['foo'], 'aXc');
291 }); 291 });
292 292
293 observeTest('TemplateWithConditionalBinding', () { 293 observeTest('TemplateWithConditionalBinding', () {
294 var div = createTestHtml( 294 var div = createTestHtml(
295 '<template bind="{{}}">' 295 '<template bind="{{}}">'
296 '<div foo?="{{b}}"></div>' 296 '<div foo?="{{b}}"></div>'
297 '</template>'); 297 '</template>');
298 var model = toSymbolMap({'b': 'b'}); 298 var model = toObservable({'b': 'b'});
299 recursivelySetTemplateModel(div, model); 299 recursivelySetTemplateModel(div, model);
300 300
301 deliverChanges(model); 301 deliverChanges(model);
302 expect(div.nodes.length, 2); 302 expect(div.nodes.length, 2);
303 expect(div.nodes.last.attributes['foo'], ''); 303 expect(div.nodes.last.attributes['foo'], '');
304 expect(div.nodes.last.attributes, isNot(contains('foo?'))); 304 expect(div.nodes.last.attributes, isNot(contains('foo?')));
305 305
306 model[#b] = null; 306 model['b'] = null;
307 deliverChanges(model); 307 deliverChanges(model);
308 expect(div.nodes.last.attributes, isNot(contains('foo'))); 308 expect(div.nodes.last.attributes, isNot(contains('foo')));
309 }); 309 });
310 310
311 observeTest('Repeat', () { 311 observeTest('Repeat', () {
312 var div = createTestHtml( 312 var div = createTestHtml(
313 '<template repeat="{{}}"">text</template>'); 313 '<template repeat="{{}}"">text</template>');
314 314
315 var model = toSymbols([0, 1, 2]); 315 var model = toObservable([0, 1, 2]);
316 recursivelySetTemplateModel(div, model); 316 recursivelySetTemplateModel(div, model);
317 317
318 deliverChanges(model); 318 deliverChanges(model);
319 expect(div.nodes.length, 4); 319 expect(div.nodes.length, 4);
320 320
321 model.length = 1; 321 model.length = 1;
322 deliverChanges(model); 322 deliverChanges(model);
323 expect(div.nodes.length, 2); 323 expect(div.nodes.length, 2);
324 324
325 model.addAll(toSymbols([3, 4])); 325 model.addAll(toObservable([3, 4]));
326 deliverChanges(model); 326 deliverChanges(model);
327 expect(div.nodes.length, 4); 327 expect(div.nodes.length, 4);
328 328
329 model.removeRange(1, 2); 329 model.removeRange(1, 2);
330 deliverChanges(model); 330 deliverChanges(model);
331 expect(div.nodes.length, 3); 331 expect(div.nodes.length, 3);
332 }); 332 });
333 333
334 observeTest('Repeat - Reuse Instances', () { 334 observeTest('Repeat - Reuse Instances', () {
335 var div = createTestHtml('<template repeat>{{ val }}</template>'); 335 var div = createTestHtml('<template repeat>{{ val }}</template>');
336 336
337 var model = toSymbols([ 337 var model = toObservable([
338 {'val': 10}, 338 {'val': 10},
339 {'val': 5}, 339 {'val': 5},
340 {'val': 2}, 340 {'val': 2},
341 {'val': 8}, 341 {'val': 8},
342 {'val': 1} 342 {'val': 1}
343 ]); 343 ]);
344 recursivelySetTemplateModel(div, model); 344 recursivelySetTemplateModel(div, model);
345 345
346 deliverChanges(model); 346 deliverChanges(model);
347 expect(div.nodes.length, 6); 347 expect(div.nodes.length, 6);
348 var template = div.firstChild; 348 var template = div.firstChild;
349 349
350 addExpandos(template.nextNode); 350 addExpandos(template.nextNode);
351 checkExpandos(template.nextNode); 351 checkExpandos(template.nextNode);
352 352
353 model.sort((a, b) => a[#val] - b[#val]); 353 model.sort((a, b) => a['val'] - b['val']);
354 deliverChanges(model); 354 deliverChanges(model);
355 checkExpandos(template.nextNode); 355 checkExpandos(template.nextNode);
356 356
357 model = toObservable(model.reversed); 357 model = toObservable(model.reversed);
358 recursivelySetTemplateModel(div, model); 358 recursivelySetTemplateModel(div, model);
359 deliverChanges(model); 359 deliverChanges(model);
360 checkExpandos(template.nextNode); 360 checkExpandos(template.nextNode);
361 361
362 for (var item in model) { 362 for (var item in model) {
363 item[#val] += 1; 363 item['val'] += 1;
364 } 364 }
365 365
366 deliverChanges(model); 366 deliverChanges(model);
367 expect(div.nodes[1].text, "11"); 367 expect(div.nodes[1].text, "11");
368 expect(div.nodes[2].text, "9"); 368 expect(div.nodes[2].text, "9");
369 expect(div.nodes[3].text, "6"); 369 expect(div.nodes[3].text, "6");
370 expect(div.nodes[4].text, "3"); 370 expect(div.nodes[4].text, "3");
371 expect(div.nodes[5].text, "2"); 371 expect(div.nodes[5].text, "2");
372 }); 372 });
373 373
(...skipping 14 matching lines...) Expand all
388 model = toObservable({'foo': model['foo']}); 388 model = toObservable({'foo': model['foo']});
389 recursivelySetTemplateModel(div, model); 389 recursivelySetTemplateModel(div, model);
390 deliverChanges(model); 390 deliverChanges(model);
391 checkExpandos(template.nextNode); 391 checkExpandos(template.nextNode);
392 }); 392 });
393 393
394 observeTest('Repeat-Empty', () { 394 observeTest('Repeat-Empty', () {
395 var div = createTestHtml( 395 var div = createTestHtml(
396 '<template repeat>text</template>'); 396 '<template repeat>text</template>');
397 397
398 var model = toSymbols([0, 1, 2]); 398 var model = toObservable([0, 1, 2]);
399 recursivelySetTemplateModel(div, model); 399 recursivelySetTemplateModel(div, model);
400 400
401 deliverChanges(model); 401 deliverChanges(model);
402 expect(div.nodes.length, 4); 402 expect(div.nodes.length, 4);
403 403
404 model.length = 1; 404 model.length = 1;
405 deliverChanges(model); 405 deliverChanges(model);
406 expect(div.nodes.length, 2); 406 expect(div.nodes.length, 2);
407 407
408 model.addAll(toSymbols([3, 4])); 408 model.addAll(toObservable([3, 4]));
409 deliverChanges(model); 409 deliverChanges(model);
410 expect(div.nodes.length, 4); 410 expect(div.nodes.length, 4);
411 411
412 model.removeRange(1, 2); 412 model.removeRange(1, 2);
413 deliverChanges(model); 413 deliverChanges(model);
414 expect(div.nodes.length, 3); 414 expect(div.nodes.length, 3);
415 }); 415 });
416 416
417 observeTest('Removal from iteration needs to unbind', () { 417 observeTest('Removal from iteration needs to unbind', () {
418 var div = createTestHtml( 418 var div = createTestHtml(
419 '<template repeat="{{}}"><a>{{v}}</a></template>'); 419 '<template repeat="{{}}"><a>{{v}}</a></template>');
420 var model = toSymbols([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3}, {'v': 4}]); 420 var model = toObservable([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3}, {'v': 4}]) ;
421 recursivelySetTemplateModel(div, model); 421 recursivelySetTemplateModel(div, model);
422 deliverChanges(model); 422 deliverChanges(model);
423 423
424 var nodes = div.nodes.skip(1).toList(); 424 var nodes = div.nodes.skip(1).toList();
425 var vs = model.toList(); 425 var vs = model.toList();
426 426
427 for (var i = 0; i < 5; i++) { 427 for (var i = 0; i < 5; i++) {
428 expect(nodes[i].text, '$i'); 428 expect(nodes[i].text, '$i');
429 } 429 }
430 430
431 model.length = 3; 431 model.length = 3;
432 deliverChanges(model); 432 deliverChanges(model);
433 for (var i = 0; i < 5; i++) { 433 for (var i = 0; i < 5; i++) {
434 expect(nodes[i].text, '$i'); 434 expect(nodes[i].text, '$i');
435 } 435 }
436 436
437 vs[3][#v] = 33; 437 vs[3]['v'] = 33;
438 vs[4][#v] = 44; 438 vs[4]['v'] = 44;
439 deliverChanges(model); 439 deliverChanges(model);
440 for (var i = 0; i < 5; i++) { 440 for (var i = 0; i < 5; i++) {
441 expect(nodes[i].text, '$i'); 441 expect(nodes[i].text, '$i');
442 } 442 }
443 }); 443 });
444 444
445 observeTest('DOM Stability on Iteration', () { 445 observeTest('DOM Stability on Iteration', () {
446 var div = createTestHtml( 446 var div = createTestHtml(
447 '<template repeat="{{}}">{{}}</template>'); 447 '<template repeat="{{}}">{{}}</template>');
448 var model = toSymbols([1, 2, 3, 4, 5]); 448 var model = toObservable([1, 2, 3, 4, 5]);
449 recursivelySetTemplateModel(div, model); 449 recursivelySetTemplateModel(div, model);
450 450
451 deliverChanges(model); 451 deliverChanges(model);
452 452
453 // Note: the node at index 0 is the <template>. 453 // Note: the node at index 0 is the <template>.
454 var nodes = div.nodes.toList(); 454 var nodes = div.nodes.toList();
455 expect(nodes.length, 6, reason: 'list has 5 items'); 455 expect(nodes.length, 6, reason: 'list has 5 items');
456 456
457 model.removeAt(0); 457 model.removeAt(0);
458 model.removeLast(); 458 model.removeLast();
(...skipping 30 matching lines...) Expand all
489 expect(identical(div.nodes[4], nodes[3]), true); 489 expect(identical(div.nodes[4], nodes[3]), true);
490 expect(identical(div.nodes[5], nodes[4]), true); 490 expect(identical(div.nodes[5], nodes[4]), true);
491 expect(identical(div.nodes[6], nodes[5]), true); 491 expect(identical(div.nodes[6], nodes[5]), true);
492 }); 492 });
493 493
494 observeTest('Repeat2', () { 494 observeTest('Repeat2', () {
495 var div = createTestHtml( 495 var div = createTestHtml(
496 '<template repeat="{{}}">{{value}}</template>'); 496 '<template repeat="{{}}">{{value}}</template>');
497 expect(div.nodes.length, 1); 497 expect(div.nodes.length, 1);
498 498
499 var model = toSymbols([ 499 var model = toObservable([
500 {'value': 0}, 500 {'value': 0},
501 {'value': 1}, 501 {'value': 1},
502 {'value': 2} 502 {'value': 2}
503 ]); 503 ]);
504 recursivelySetTemplateModel(div, model); 504 recursivelySetTemplateModel(div, model);
505 505
506 deliverChanges(model); 506 deliverChanges(model);
507 expect(div.nodes.length, 4); 507 expect(div.nodes.length, 4);
508 expect(div.nodes[1].text, '0'); 508 expect(div.nodes[1].text, '0');
509 expect(div.nodes[2].text, '1'); 509 expect(div.nodes[2].text, '1');
510 expect(div.nodes[3].text, '2'); 510 expect(div.nodes[3].text, '2');
511 511
512 model[1][#value] = 'One'; 512 model[1]['value'] = 'One';
513 deliverChanges(model); 513 deliverChanges(model);
514 expect(div.nodes.length, 4); 514 expect(div.nodes.length, 4);
515 expect(div.nodes[1].text, '0'); 515 expect(div.nodes[1].text, '0');
516 expect(div.nodes[2].text, 'One'); 516 expect(div.nodes[2].text, 'One');
517 expect(div.nodes[3].text, '2'); 517 expect(div.nodes[3].text, '2');
518 518
519 model.replaceRange(0, 1, toSymbols([{'value': 'Zero'}])); 519 model.replaceRange(0, 1, toObservable([{'value': 'Zero'}]));
520 deliverChanges(model); 520 deliverChanges(model);
521 expect(div.nodes.length, 4); 521 expect(div.nodes.length, 4);
522 expect(div.nodes[1].text, 'Zero'); 522 expect(div.nodes[1].text, 'Zero');
523 expect(div.nodes[2].text, 'One'); 523 expect(div.nodes[2].text, 'One');
524 expect(div.nodes[3].text, '2'); 524 expect(div.nodes[3].text, '2');
525 }); 525 });
526 526
527 observeTest('TemplateWithInputValue', () { 527 observeTest('TemplateWithInputValue', () {
528 var div = createTestHtml( 528 var div = createTestHtml(
529 '<template bind="{{}}">' 529 '<template bind="{{}}">'
530 '<input value="{{x}}">' 530 '<input value="{{x}}">'
531 '</template>'); 531 '</template>');
532 var model = toSymbolMap({'x': 'hi'}); 532 var model = toObservable({'x': 'hi'});
533 recursivelySetTemplateModel(div, model); 533 recursivelySetTemplateModel(div, model);
534 534
535 deliverChanges(model); 535 deliverChanges(model);
536 expect(div.nodes.length, 2); 536 expect(div.nodes.length, 2);
537 expect(div.nodes.last.value, 'hi'); 537 expect(div.nodes.last.value, 'hi');
538 538
539 model[#x] = 'bye'; 539 model['x'] = 'bye';
540 expect(div.nodes.last.value, 'hi'); 540 expect(div.nodes.last.value, 'hi');
541 deliverChanges(model); 541 deliverChanges(model);
542 expect(div.nodes.last.value, 'bye'); 542 expect(div.nodes.last.value, 'bye');
543 543
544 div.nodes.last.value = 'hello'; 544 div.nodes.last.value = 'hello';
545 dispatchEvent('input', div.nodes.last); 545 dispatchEvent('input', div.nodes.last);
546 expect(model[#x], 'hello'); 546 expect(model['x'], 'hello');
547 deliverChanges(model); 547 deliverChanges(model);
548 expect(div.nodes.last.value, 'hello'); 548 expect(div.nodes.last.value, 'hello');
549 }); 549 });
550 550
551 ////////////////////////////////////////////////////////////////////////////// 551 //////////////////////////////////////////////////////////////////////////////
552 552
553 observeTest('Decorated', () { 553 observeTest('Decorated', () {
554 var div = createTestHtml( 554 var div = createTestHtml(
555 '<template bind="{{ XX }}" id="t1">' 555 '<template bind="{{ XX }}" id="t1">'
556 '<p>Crew member: {{name}}, Job title: {{title}}</p>' 556 '<p>Crew member: {{name}}, Job title: {{title}}</p>'
557 '</template>' 557 '</template>'
558 '<template bind="{{ XY }}" id="t2" ref="t1"></template>'); 558 '<template bind="{{ XY }}" id="t2" ref="t1"></template>');
559 559
560 var model = toSymbolMap({ 560 var model = toObservable({
561 'XX': {'name': 'Leela', 'title': 'Captain'}, 561 'XX': {'name': 'Leela', 'title': 'Captain'},
562 'XY': {'name': 'Fry', 'title': 'Delivery boy'}, 562 'XY': {'name': 'Fry', 'title': 'Delivery boy'},
563 'XZ': {'name': 'Zoidberg', 'title': 'Doctor'} 563 'XZ': {'name': 'Zoidberg', 'title': 'Doctor'}
564 }); 564 });
565 recursivelySetTemplateModel(div, model); 565 recursivelySetTemplateModel(div, model);
566 566
567 deliverChanges(model); 567 deliverChanges(model);
568 568
569 var t1 = document.getElementById('t1'); 569 var t1 = document.getElementById('t1');
570 var instance = t1.nextElementSibling; 570 var instance = t1.nextElementSibling;
(...skipping 16 matching lines...) Expand all
587 587
588 document.body.append(t); 588 document.body.append(t);
589 expect(t.getComputedStyle().display, 'none'); 589 expect(t.getComputedStyle().display, 'none');
590 590
591 t.remove(); 591 t.remove();
592 }); 592 });
593 593
594 594
595 observeTest('Bind', () { 595 observeTest('Bind', () {
596 var div = createTestHtml('<template bind="{{}}">Hi {{ name }}</template>'); 596 var div = createTestHtml('<template bind="{{}}">Hi {{ name }}</template>');
597 var model = toSymbolMap({'name': 'Leela'}); 597 var model = toObservable({'name': 'Leela'});
598 recursivelySetTemplateModel(div, model); 598 recursivelySetTemplateModel(div, model);
599 599
600 deliverChanges(model); 600 deliverChanges(model);
601 expect(div.nodes[1].text, 'Hi Leela'); 601 expect(div.nodes[1].text, 'Hi Leela');
602 }); 602 });
603 603
604 observeTest('BindImperative', () { 604 observeTest('BindImperative', () {
605 var div = createTestHtml( 605 var div = createTestHtml(
606 '<template>' 606 '<template>'
607 'Hi {{ name }}' 607 'Hi {{ name }}'
608 '</template>'); 608 '</template>');
609 var t = div.nodes.first; 609 var t = div.nodes.first;
610 610
611 var model = toSymbolMap({'name': 'Leela'}); 611 var model = toObservable({'name': 'Leela'});
612 t.bind('bind', model, ''); 612 t.bind('bind', model, '');
613 613
614 deliverChanges(model); 614 deliverChanges(model);
615 expect(div.nodes[1].text, 'Hi Leela'); 615 expect(div.nodes[1].text, 'Hi Leela');
616 }); 616 });
617 617
618 observeTest('BindPlaceHolderHasNewLine', () { 618 observeTest('BindPlaceHolderHasNewLine', () {
619 var div = createTestHtml('<template bind="{{}}">Hi {{\nname\n}}</template>') ; 619 var div = createTestHtml('<template bind="{{}}">Hi {{\nname\n}}</template>') ;
620 var model = toSymbolMap({'name': 'Leela'}); 620 var model = toObservable({'name': 'Leela'});
621 recursivelySetTemplateModel(div, model); 621 recursivelySetTemplateModel(div, model);
622 622
623 deliverChanges(model); 623 deliverChanges(model);
624 expect(div.nodes[1].text, 'Hi Leela'); 624 expect(div.nodes[1].text, 'Hi Leela');
625 }); 625 });
626 626
627 observeTest('BindWithRef', () { 627 observeTest('BindWithRef', () {
628 var id = 't${new math.Random().nextDouble()}'; 628 var id = 't${new math.Random().nextDouble()}';
629 var div = createTestHtml( 629 var div = createTestHtml(
630 '<template id="$id">' 630 '<template id="$id">'
631 'Hi {{ name }}' 631 'Hi {{ name }}'
632 '</template>' 632 '</template>'
633 '<template ref="$id" bind="{{}}"></template>'); 633 '<template ref="$id" bind="{{}}"></template>');
634 634
635 var t1 = div.nodes.first; 635 var t1 = div.nodes.first;
636 var t2 = div.nodes[1]; 636 var t2 = div.nodes[1];
637 637
638 expect(t2.ref, t1); 638 expect(t2.ref, t1);
639 639
640 var model = toSymbolMap({'name': 'Fry'}); 640 var model = toObservable({'name': 'Fry'});
641 recursivelySetTemplateModel(div, model); 641 recursivelySetTemplateModel(div, model);
642 642
643 deliverChanges(model); 643 deliverChanges(model);
644 expect(t2.nextNode.text, 'Hi Fry'); 644 expect(t2.nextNode.text, 'Hi Fry');
645 }); 645 });
646 646
647 observeTest('BindChanged', () { 647 observeTest('BindChanged', () {
648 var model = toSymbolMap({ 648 var model = toObservable({
649 'XX': {'name': 'Leela', 'title': 'Captain'}, 649 'XX': {'name': 'Leela', 'title': 'Captain'},
650 'XY': {'name': 'Fry', 'title': 'Delivery boy'}, 650 'XY': {'name': 'Fry', 'title': 'Delivery boy'},
651 'XZ': {'name': 'Zoidberg', 'title': 'Doctor'} 651 'XZ': {'name': 'Zoidberg', 'title': 'Doctor'}
652 }); 652 });
653 653
654 var div = createTestHtml( 654 var div = createTestHtml(
655 '<template bind="{{ XX }}">Hi {{ name }}</template>'); 655 '<template bind="{{ XX }}">Hi {{ name }}</template>');
656 656
657 recursivelySetTemplateModel(div, model); 657 recursivelySetTemplateModel(div, model);
658 658
(...skipping 18 matching lines...) Expand all
677 var targetNode = div.nodes[i + 1]; 677 var targetNode = div.nodes[i + 1];
678 expect(targetNode.text, arguments[i]); 678 expect(targetNode.text, arguments[i]);
679 } 679 }
680 } 680 }
681 681
682 observeTest('Repeat3', () { 682 observeTest('Repeat3', () {
683 var div = createTestHtml( 683 var div = createTestHtml(
684 '<template repeat="{{ contacts }}">Hi {{ name }}</template>'); 684 '<template repeat="{{ contacts }}">Hi {{ name }}</template>');
685 var t = div.nodes.first; 685 var t = div.nodes.first;
686 686
687 var m = toSymbols({ 687 var m = toObservable({
688 'contacts': [ 688 'contacts': [
689 {'name': 'Raf'}, 689 {'name': 'Raf'},
690 {'name': 'Arv'}, 690 {'name': 'Arv'},
691 {'name': 'Neal'} 691 {'name': 'Neal'}
692 ] 692 ]
693 }); 693 });
694 694
695 recursivelySetTemplateModel(div, m); 695 recursivelySetTemplateModel(div, m);
696 deliverChanges(m); 696 deliverChanges(m);
697 697
698 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); 698 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']);
699 699
700 m[#contacts].add(toSymbols({'name': 'Alex'})); 700 m['contacts'].add(toObservable({'name': 'Alex'}));
701 deliverChanges(m); 701 deliverChanges(m);
702 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']); 702 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']);
703 703
704 m[#contacts].replaceRange(0, 2, 704 m['contacts'].replaceRange(0, 2,
705 toSymbols([{'name': 'Rafael'}, {'name': 'Erik'}])); 705 toObservable([{'name': 'Rafael'}, {'name': 'Erik'}]));
706 deliverChanges(m); 706 deliverChanges(m);
707 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Neal', 'Hi Alex']); 707 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Neal', 'Hi Alex']);
708 708
709 m[#contacts].removeRange(1, 3); 709 m['contacts'].removeRange(1, 3);
710 deliverChanges(m); 710 deliverChanges(m);
711 assertNodesAre(div, ['Hi Rafael', 'Hi Alex']); 711 assertNodesAre(div, ['Hi Rafael', 'Hi Alex']);
712 712
713 m[#contacts].insertAll(1, 713 m['contacts'].insertAll(1,
714 toSymbols([{'name': 'Erik'}, {'name': 'Dimitri'}])); 714 toObservable([{'name': 'Erik'}, {'name': 'Dimitri'}]));
715 deliverChanges(m); 715 deliverChanges(m);
716 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']); 716 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']);
717 717
718 m[#contacts].replaceRange(0, 1, 718 m['contacts'].replaceRange(0, 1,
719 toSymbols([{'name': 'Tab'}, {'name': 'Neal'}])); 719 toObservable([{'name': 'Tab'}, {'name': 'Neal'}]));
720 deliverChanges(m); 720 deliverChanges(m);
721 assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri', 'Hi Alex' ]); 721 assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri', 'Hi Alex' ]);
722 722
723 m[#contacts] = toSymbols([{'name': 'Alex'}]); 723 m['contacts'] = toObservable([{'name': 'Alex'}]);
724 deliverChanges(m); 724 deliverChanges(m);
725 assertNodesAre(div, ['Hi Alex']); 725 assertNodesAre(div, ['Hi Alex']);
726 726
727 m[#contacts].length = 0; 727 m['contacts'].length = 0;
728 deliverChanges(m); 728 deliverChanges(m);
729 assertNodesAre(div, []); 729 assertNodesAre(div, []);
730 }); 730 });
731 731
732 observeTest('RepeatModelSet', () { 732 observeTest('RepeatModelSet', () {
733 var div = createTestHtml( 733 var div = createTestHtml(
734 '<template repeat="{{ contacts }}">' 734 '<template repeat="{{ contacts }}">'
735 'Hi {{ name }}' 735 'Hi {{ name }}'
736 '</template>'); 736 '</template>');
737 var m = toSymbols({ 737 var m = toObservable({
738 'contacts': [ 738 'contacts': [
739 {'name': 'Raf'}, 739 {'name': 'Raf'},
740 {'name': 'Arv'}, 740 {'name': 'Arv'},
741 {'name': 'Neal'} 741 {'name': 'Neal'}
742 ] 742 ]
743 }); 743 });
744 recursivelySetTemplateModel(div, m); 744 recursivelySetTemplateModel(div, m);
745 745
746 deliverChanges(m); 746 deliverChanges(m);
747 var t = div.nodes.first; 747 var t = div.nodes.first;
748 748
749 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); 749 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']);
750 }); 750 });
751 751
752 observeTest('RepeatEmptyPath', () { 752 observeTest('RepeatEmptyPath', () {
753 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ; 753 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ;
754 var t = div.nodes.first; 754 var t = div.nodes.first;
755 755
756 var m = toSymbols([ 756 var m = toObservable([
757 {'name': 'Raf'}, 757 {'name': 'Raf'},
758 {'name': 'Arv'}, 758 {'name': 'Arv'},
759 {'name': 'Neal'} 759 {'name': 'Neal'}
760 ]); 760 ]);
761 recursivelySetTemplateModel(div, m); 761 recursivelySetTemplateModel(div, m);
762 762
763 deliverChanges(m); 763 deliverChanges(m);
764 764
765 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); 765 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']);
766 766
767 m.add(toSymbols({'name': 'Alex'})); 767 m.add(toObservable({'name': 'Alex'}));
768 deliverChanges(m); 768 deliverChanges(m);
769 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']); 769 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']);
770 770
771 m.replaceRange(0, 2, toSymbols([{'name': 'Rafael'}, {'name': 'Erik'}])); 771 m.replaceRange(0, 2, toObservable([{'name': 'Rafael'}, {'name': 'Erik'}]));
772 deliverChanges(m); 772 deliverChanges(m);
773 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Neal', 'Hi Alex']); 773 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Neal', 'Hi Alex']);
774 774
775 m.removeRange(1, 3); 775 m.removeRange(1, 3);
776 deliverChanges(m); 776 deliverChanges(m);
777 assertNodesAre(div, ['Hi Rafael', 'Hi Alex']); 777 assertNodesAre(div, ['Hi Rafael', 'Hi Alex']);
778 778
779 m.insertAll(1, toSymbols([{'name': 'Erik'}, {'name': 'Dimitri'}])); 779 m.insertAll(1, toObservable([{'name': 'Erik'}, {'name': 'Dimitri'}]));
780 deliverChanges(m); 780 deliverChanges(m);
781 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']); 781 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']);
782 782
783 m.replaceRange(0, 1, toSymbols([{'name': 'Tab'}, {'name': 'Neal'}])); 783 m.replaceRange(0, 1, toObservable([{'name': 'Tab'}, {'name': 'Neal'}]));
784 deliverChanges(m); 784 deliverChanges(m);
785 assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri', 'Hi Alex' ]); 785 assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri', 'Hi Alex' ]);
786 786
787 m.length = 0; 787 m.length = 0;
788 m.add(toSymbols({'name': 'Alex'})); 788 m.add(toObservable({'name': 'Alex'}));
789 deliverChanges(m); 789 deliverChanges(m);
790 assertNodesAre(div, ['Hi Alex']); 790 assertNodesAre(div, ['Hi Alex']);
791 }); 791 });
792 792
793 observeTest('RepeatNullModel', () { 793 observeTest('RepeatNullModel', () {
794 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ; 794 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ;
795 var t = div.nodes.first; 795 var t = div.nodes.first;
796 796
797 var m = null; 797 var m = null;
798 recursivelySetTemplateModel(div, m); 798 recursivelySetTemplateModel(div, m);
799 799
800 expect(div.nodes.length, 1); 800 expect(div.nodes.length, 1);
801 801
802 t.attributes['iterate'] = ''; 802 t.attributes['iterate'] = '';
803 m = toSymbols({}); 803 m = toObservable({});
804 recursivelySetTemplateModel(div, m); 804 recursivelySetTemplateModel(div, m);
805 805
806 deliverChanges(m); 806 deliverChanges(m);
807 expect(div.nodes.length, 1); 807 expect(div.nodes.length, 1);
808 }); 808 });
809 809
810 observeTest('RepeatReuse', () { 810 observeTest('RepeatReuse', () {
811 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ; 811 var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>') ;
812 var t = div.nodes.first; 812 var t = div.nodes.first;
813 813
814 var m = toSymbols([ 814 var m = toObservable([
815 {'name': 'Raf'}, 815 {'name': 'Raf'},
816 {'name': 'Arv'}, 816 {'name': 'Arv'},
817 {'name': 'Neal'} 817 {'name': 'Neal'}
818 ]); 818 ]);
819 recursivelySetTemplateModel(div, m); 819 recursivelySetTemplateModel(div, m);
820 deliverChanges(m); 820 deliverChanges(m);
821 821
822 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); 822 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']);
823 var node1 = div.nodes[1]; 823 var node1 = div.nodes[1];
824 var node2 = div.nodes[2]; 824 var node2 = div.nodes[2];
825 var node3 = div.nodes[3]; 825 var node3 = div.nodes[3];
826 826
827 m.replaceRange(1, 2, toSymbols([{'name': 'Erik'}])); 827 m.replaceRange(1, 2, toObservable([{'name': 'Erik'}]));
828 deliverChanges(m); 828 deliverChanges(m);
829 assertNodesAre(div, ['Hi Raf', 'Hi Erik', 'Hi Neal']); 829 assertNodesAre(div, ['Hi Raf', 'Hi Erik', 'Hi Neal']);
830 expect(div.nodes[1], node1, 830 expect(div.nodes[1], node1,
831 reason: 'model[0] did not change so the node should not have changed'); 831 reason: 'model[0] did not change so the node should not have changed');
832 expect(div.nodes[2], isNot(equals(node2)), 832 expect(div.nodes[2], isNot(equals(node2)),
833 reason: 'Should not reuse when replacing'); 833 reason: 'Should not reuse when replacing');
834 expect(div.nodes[3], node3, 834 expect(div.nodes[3], node3,
835 reason: 'model[2] did not change so the node should not have changed'); 835 reason: 'model[2] did not change so the node should not have changed');
836 836
837 node2 = div.nodes[2]; 837 node2 = div.nodes[2];
838 m.insert(0, toSymbols({'name': 'Alex'})); 838 m.insert(0, toObservable({'name': 'Alex'}));
839 deliverChanges(m); 839 deliverChanges(m);
840 assertNodesAre(div, ['Hi Alex', 'Hi Raf', 'Hi Erik', 'Hi Neal']); 840 assertNodesAre(div, ['Hi Alex', 'Hi Raf', 'Hi Erik', 'Hi Neal']);
841 }); 841 });
842 842
843 observeTest('TwoLevelsDeepBug', () { 843 observeTest('TwoLevelsDeepBug', () {
844 var div = createTestHtml( 844 var div = createTestHtml(
845 '<template bind="{{}}"><span><span>{{ foo }}</span></span></template>'); 845 '<template bind="{{}}"><span><span>{{ foo }}</span></span></template>');
846 846
847 var model = toSymbolMap({'foo': 'bar'}); 847 var model = toObservable({'foo': 'bar'});
848 recursivelySetTemplateModel(div, model); 848 recursivelySetTemplateModel(div, model);
849 deliverChanges(model); 849 deliverChanges(model);
850 850
851 expect(div.nodes[1].nodes[0].nodes[0].text, 'bar'); 851 expect(div.nodes[1].nodes[0].nodes[0].text, 'bar');
852 }); 852 });
853 853
854 observeTest('Checked', () { 854 observeTest('Checked', () {
855 var div = createTestHtml( 855 var div = createTestHtml(
856 '<template>' 856 '<template>'
857 '<input type="checkbox" checked="{{a}}">' 857 '<input type="checkbox" checked="{{a}}">'
858 '</template>'); 858 '</template>');
859 var t = div.nodes.first; 859 var t = div.nodes.first;
860 var m = toSymbols({ 860 var m = toObservable({
861 'a': true 861 'a': true
862 }); 862 });
863 t.bind('bind', m, ''); 863 t.bind('bind', m, '');
864 deliverChanges(m); 864 deliverChanges(m);
865 865
866 var instanceInput = t.nextNode; 866 var instanceInput = t.nextNode;
867 expect(instanceInput.checked, true); 867 expect(instanceInput.checked, true);
868 868
869 instanceInput.click(); 869 instanceInput.click();
870 expect(instanceInput.checked, false); 870 expect(instanceInput.checked, false);
871 871
872 instanceInput.click(); 872 instanceInput.click();
873 expect(instanceInput.checked, true); 873 expect(instanceInput.checked, true);
874 }); 874 });
875 875
876 nestedHelper(s, start) { 876 nestedHelper(s, start) {
877 var div = createTestHtml(s); 877 var div = createTestHtml(s);
878 878
879 var m = toSymbols({ 879 var m = toObservable({
880 'a': { 880 'a': {
881 'b': 1, 881 'b': 1,
882 'c': {'d': 2} 882 'c': {'d': 2}
883 }, 883 },
884 }); 884 });
885 885
886 recursivelySetTemplateModel(div, m); 886 recursivelySetTemplateModel(div, m);
887 deliverChanges(m); 887 deliverChanges(m);
888 888
889 var i = start; 889 var i = start;
890 expect(div.nodes[i++].text, '1'); 890 expect(div.nodes[i++].text, '1');
891 expect(div.nodes[i++].tagName, 'TEMPLATE'); 891 expect(div.nodes[i++].tagName, 'TEMPLATE');
892 expect(div.nodes[i++].text, '2'); 892 expect(div.nodes[i++].text, '2');
893 893
894 m[#a][#b] = 11; 894 m['a']['b'] = 11;
895 deliverChanges(m); 895 deliverChanges(m);
896 expect(div.nodes[start].text, '11'); 896 expect(div.nodes[start].text, '11');
897 897
898 m[#a][#c] = toSymbols({'d': 22}); 898 m['a']['c'] = toObservable({'d': 22});
899 deliverChanges(m); 899 deliverChanges(m);
900 expect(div.nodes[start + 2].text, '22'); 900 expect(div.nodes[start + 2].text, '22');
901 } 901 }
902 902
903 observeTest('Nested', () { 903 observeTest('Nested', () {
904 nestedHelper( 904 nestedHelper(
905 '<template bind="{{a}}">' 905 '<template bind="{{a}}">'
906 '{{b}}' 906 '{{b}}'
907 '<template bind="{{c}}">' 907 '<template bind="{{c}}">'
908 '{{d}}' 908 '{{d}}'
909 '</template>' 909 '</template>'
910 '</template>', 1); 910 '</template>', 1);
911 }); 911 });
912 912
913 observeTest('NestedWithRef', () { 913 observeTest('NestedWithRef', () {
914 nestedHelper( 914 nestedHelper(
915 '<template id="inner">{{d}}</template>' 915 '<template id="inner">{{d}}</template>'
916 '<template id="outer" bind="{{a}}">' 916 '<template id="outer" bind="{{a}}">'
917 '{{b}}' 917 '{{b}}'
918 '<template ref="inner" bind="{{c}}"></template>' 918 '<template ref="inner" bind="{{c}}"></template>'
919 '</template>', 2); 919 '</template>', 2);
920 }); 920 });
921 921
922 nestedIterateInstantiateHelper(s, start) { 922 nestedIterateInstantiateHelper(s, start) {
923 var div = createTestHtml(s); 923 var div = createTestHtml(s);
924 924
925 var m = toSymbols({ 925 var m = toObservable({
926 'a': [ 926 'a': [
927 { 927 {
928 'b': 1, 928 'b': 1,
929 'c': {'d': 11} 929 'c': {'d': 11}
930 }, 930 },
931 { 931 {
932 'b': 2, 932 'b': 2,
933 'c': {'d': 22} 933 'c': {'d': 22}
934 } 934 }
935 ] 935 ]
936 }); 936 });
937 937
938 recursivelySetTemplateModel(div, m); 938 recursivelySetTemplateModel(div, m);
939 deliverChanges(m); 939 deliverChanges(m);
940 940
941 var i = start; 941 var i = start;
942 expect(div.nodes[i++].text, '1'); 942 expect(div.nodes[i++].text, '1');
943 expect(div.nodes[i++].tagName, 'TEMPLATE'); 943 expect(div.nodes[i++].tagName, 'TEMPLATE');
944 expect(div.nodes[i++].text, '11'); 944 expect(div.nodes[i++].text, '11');
945 expect(div.nodes[i++].text, '2'); 945 expect(div.nodes[i++].text, '2');
946 expect(div.nodes[i++].tagName, 'TEMPLATE'); 946 expect(div.nodes[i++].tagName, 'TEMPLATE');
947 expect(div.nodes[i++].text, '22'); 947 expect(div.nodes[i++].text, '22');
948 948
949 m[#a][1] = toSymbols({ 949 m['a'][1] = toObservable({
950 'b': 3, 950 'b': 3,
951 'c': {'d': 33} 951 'c': {'d': 33}
952 }); 952 });
953 953
954 deliverChanges(m); 954 deliverChanges(m);
955 expect(div.nodes[start + 3].text, '3'); 955 expect(div.nodes[start + 3].text, '3');
956 expect(div.nodes[start + 5].text, '33'); 956 expect(div.nodes[start + 5].text, '33');
957 } 957 }
958 958
959 observeTest('NestedRepeatBind', () { 959 observeTest('NestedRepeatBind', () {
(...skipping 13 matching lines...) Expand all
973 '</template>' 973 '</template>'
974 '<template repeat="{{a}}">' 974 '<template repeat="{{a}}">'
975 '{{b}}' 975 '{{b}}'
976 '<template ref="inner" bind="{{c}}"></template>' 976 '<template ref="inner" bind="{{c}}"></template>'
977 '</template>', 2); 977 '</template>', 2);
978 }); 978 });
979 979
980 nestedIterateIterateHelper(s, start) { 980 nestedIterateIterateHelper(s, start) {
981 var div = createTestHtml(s); 981 var div = createTestHtml(s);
982 982
983 var m = toSymbols({ 983 var m = toObservable({
984 'a': [ 984 'a': [
985 { 985 {
986 'b': 1, 986 'b': 1,
987 'c': [{'d': 11}, {'d': 12}] 987 'c': [{'d': 11}, {'d': 12}]
988 }, 988 },
989 { 989 {
990 'b': 2, 990 'b': 2,
991 'c': [{'d': 21}, {'d': 22}] 991 'c': [{'d': 21}, {'d': 22}]
992 } 992 }
993 ] 993 ]
994 }); 994 });
995 995
996 recursivelySetTemplateModel(div, m); 996 recursivelySetTemplateModel(div, m);
997 deliverChanges(m); 997 deliverChanges(m);
998 998
999 var i = start; 999 var i = start;
1000 expect(div.nodes[i++].text, '1'); 1000 expect(div.nodes[i++].text, '1');
1001 expect(div.nodes[i++].tagName, 'TEMPLATE'); 1001 expect(div.nodes[i++].tagName, 'TEMPLATE');
1002 expect(div.nodes[i++].text, '11'); 1002 expect(div.nodes[i++].text, '11');
1003 expect(div.nodes[i++].text, '12'); 1003 expect(div.nodes[i++].text, '12');
1004 expect(div.nodes[i++].text, '2'); 1004 expect(div.nodes[i++].text, '2');
1005 expect(div.nodes[i++].tagName, 'TEMPLATE'); 1005 expect(div.nodes[i++].tagName, 'TEMPLATE');
1006 expect(div.nodes[i++].text, '21'); 1006 expect(div.nodes[i++].text, '21');
1007 expect(div.nodes[i++].text, '22'); 1007 expect(div.nodes[i++].text, '22');
1008 1008
1009 m[#a][1] = toSymbols({ 1009 m['a'][1] = toObservable({
1010 'b': 3, 1010 'b': 3,
1011 'c': [{'d': 31}, {'d': 32}, {'d': 33}] 1011 'c': [{'d': 31}, {'d': 32}, {'d': 33}]
1012 }); 1012 });
1013 1013
1014 i = start + 4; 1014 i = start + 4;
1015 deliverChanges(m); 1015 deliverChanges(m);
1016 expect(div.nodes[start + 4].text, '3'); 1016 expect(div.nodes[start + 4].text, '3');
1017 expect(div.nodes[start + 6].text, '31'); 1017 expect(div.nodes[start + 6].text, '31');
1018 expect(div.nodes[start + 7].text, '32'); 1018 expect(div.nodes[start + 7].text, '32');
1019 expect(div.nodes[start + 8].text, '33'); 1019 expect(div.nodes[start + 8].text, '33');
(...skipping 20 matching lines...) Expand all
1040 '</template>', 2); 1040 '</template>', 2);
1041 }); 1041 });
1042 1042
1043 observeTest('NestedRepeatSelfRef', () { 1043 observeTest('NestedRepeatSelfRef', () {
1044 var div = createTestHtml( 1044 var div = createTestHtml(
1045 '<template id="t" repeat="{{}}">' 1045 '<template id="t" repeat="{{}}">'
1046 '{{name}}' 1046 '{{name}}'
1047 '<template ref="t" repeat="{{items}}"></template>' 1047 '<template ref="t" repeat="{{items}}"></template>'
1048 '</template>'); 1048 '</template>');
1049 1049
1050 var m = toSymbols([ 1050 var m = toObservable([
1051 { 1051 {
1052 'name': 'Item 1', 1052 'name': 'Item 1',
1053 'items': [ 1053 'items': [
1054 { 1054 {
1055 'name': 'Item 1.1', 1055 'name': 'Item 1.1',
1056 'items': [ 1056 'items': [
1057 { 1057 {
1058 'name': 'Item 1.1.1', 1058 'name': 'Item 1.1.1',
1059 'items': [] 1059 'items': []
1060 } 1060 }
(...skipping 17 matching lines...) Expand all
1078 expect(div.nodes[i++].text, 'Item 1'); 1078 expect(div.nodes[i++].text, 'Item 1');
1079 expect(div.nodes[i++].tagName, 'TEMPLATE'); 1079 expect(div.nodes[i++].tagName, 'TEMPLATE');
1080 expect(div.nodes[i++].text, 'Item 1.1'); 1080 expect(div.nodes[i++].text, 'Item 1.1');
1081 expect(div.nodes[i++].tagName, 'TEMPLATE'); 1081 expect(div.nodes[i++].tagName, 'TEMPLATE');
1082 expect(div.nodes[i++].text, 'Item 1.1.1'); 1082 expect(div.nodes[i++].text, 'Item 1.1.1');
1083 expect(div.nodes[i++].tagName, 'TEMPLATE'); 1083 expect(div.nodes[i++].tagName, 'TEMPLATE');
1084 expect(div.nodes[i++].text, 'Item 1.2'); 1084 expect(div.nodes[i++].text, 'Item 1.2');
1085 expect(div.nodes[i++].tagName, 'TEMPLATE'); 1085 expect(div.nodes[i++].tagName, 'TEMPLATE');
1086 expect(div.nodes[i++].text, 'Item 2'); 1086 expect(div.nodes[i++].text, 'Item 2');
1087 1087
1088 m[0] = toSymbols({'name': 'Item 1 changed'}); 1088 m[0] = toObservable({'name': 'Item 1 changed'});
1089 1089
1090 i = 1; 1090 i = 1;
1091 deliverChanges(m); 1091 deliverChanges(m);
1092 expect(div.nodes[i++].text, 'Item 1 changed'); 1092 expect(div.nodes[i++].text, 'Item 1 changed');
1093 expect(div.nodes[i++].tagName, 'TEMPLATE'); 1093 expect(div.nodes[i++].tagName, 'TEMPLATE');
1094 expect(div.nodes[i++].text, 'Item 2'); 1094 expect(div.nodes[i++].text, 'Item 2');
1095 }); 1095 });
1096 1096
1097 observeTest('Attribute Template Option/Optgroup', () { 1097 observeTest('Attribute Template Option/Optgroup', () {
1098 var div = createTestHtml( 1098 var div = createTestHtml(
1099 '<template bind>' 1099 '<template bind>'
1100 '<select selectedIndex="{{ selected }}">' 1100 '<select selectedIndex="{{ selected }}">'
1101 '<optgroup template repeat="{{ groups }}" label="{{ name }}">' 1101 '<optgroup template repeat="{{ groups }}" label="{{ name }}">'
1102 '<option template repeat="{{ items }}">{{ val }}</option>' 1102 '<option template repeat="{{ items }}">{{ val }}</option>'
1103 '</optgroup>' 1103 '</optgroup>'
1104 '</select>' 1104 '</select>'
1105 '</template>'); 1105 '</template>');
1106 1106
1107 var m = toSymbols({ 1107 var m = toObservable({
1108 'selected': 1, 1108 'selected': 1,
1109 'groups': [{ 1109 'groups': [{
1110 'name': 'one', 'items': [{ 'val': 0 }, { 'val': 1 }] 1110 'name': 'one', 'items': [{ 'val': 0 }, { 'val': 1 }]
1111 }], 1111 }],
1112 }); 1112 });
1113 1113
1114 recursivelySetTemplateModel(div, m); 1114 recursivelySetTemplateModel(div, m);
1115 deliverChanges(m); 1115 deliverChanges(m);
1116 1116
1117 var select = div.nodes[0].nextNode; 1117 var select = div.nodes[0].nextNode;
(...skipping 21 matching lines...) Expand all
1139 1139
1140 var div = createTestHtml( 1140 var div = createTestHtml(
1141 '<table><tbody>' 1141 '<table><tbody>'
1142 '<template repeat="{{}}">' 1142 '<template repeat="{{}}">'
1143 '<tr>' 1143 '<tr>'
1144 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>' 1144 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>'
1145 '</tr>' 1145 '</tr>'
1146 '</template>' 1146 '</template>'
1147 '</tbody></table>'); 1147 '</tbody></table>');
1148 1148
1149 var m = toSymbols([ 1149 var m = toObservable([
1150 [{ 'val': 0 }, { 'val': 1 }], 1150 [{ 'val': 0 }, { 'val': 1 }],
1151 [{ 'val': 2 }, { 'val': 3 }] 1151 [{ 'val': 2 }, { 'val': 3 }]
1152 ]); 1152 ]);
1153 1153
1154 recursivelySetTemplateModel(div, m); 1154 recursivelySetTemplateModel(div, m);
1155 deliverChanges(m); 1155 deliverChanges(m);
1156 1156
1157 var tbody = div.nodes[0].nodes[0]; 1157 var tbody = div.nodes[0].nodes[0];
1158 1158
1159 // 1 for the <tr template>, 2 * (1 tr) 1159 // 1 for the <tr template>, 2 * (1 tr)
(...skipping 16 matching lines...) Expand all
1176 }); 1176 });
1177 1177
1178 observeTest('NestedIterateTable', () { 1178 observeTest('NestedIterateTable', () {
1179 var div = createTestHtml( 1179 var div = createTestHtml(
1180 '<table><tbody>' 1180 '<table><tbody>'
1181 '<tr template repeat="{{}}">' 1181 '<tr template repeat="{{}}">'
1182 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>' 1182 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>'
1183 '</tr>' 1183 '</tr>'
1184 '</tbody></table>'); 1184 '</tbody></table>');
1185 1185
1186 var m = toSymbols([ 1186 var m = toObservable([
1187 [{ 'val': 0 }, { 'val': 1 }], 1187 [{ 'val': 0 }, { 'val': 1 }],
1188 [{ 'val': 2 }, { 'val': 3 }] 1188 [{ 'val': 2 }, { 'val': 3 }]
1189 ]); 1189 ]);
1190 1190
1191 recursivelySetTemplateModel(div, m); 1191 recursivelySetTemplateModel(div, m);
1192 deliverChanges(m); 1192 deliverChanges(m);
1193 1193
1194 var i = 1; 1194 var i = 1;
1195 var tbody = div.nodes[0].nodes[0]; 1195 var tbody = div.nodes[0].nodes[0];
1196 1196
(...skipping 20 matching lines...) Expand all
1217 '<ul>' 1217 '<ul>'
1218 '<template repeat="{{}}" id=t1>' 1218 '<template repeat="{{}}" id=t1>'
1219 '<li>{{name}}' 1219 '<li>{{name}}'
1220 '<ul>' 1220 '<ul>'
1221 '<template ref=t1 repaet="{{items}}"></template>' 1221 '<template ref=t1 repaet="{{items}}"></template>'
1222 '</ul>' 1222 '</ul>'
1223 '</li>' 1223 '</li>'
1224 '</template>' 1224 '</template>'
1225 '</ul>'); 1225 '</ul>');
1226 1226
1227 var m = toSymbols([ 1227 var m = toObservable([
1228 { 1228 {
1229 'name': 'Item 1', 1229 'name': 'Item 1',
1230 'items': [ 1230 'items': [
1231 { 1231 {
1232 'name': 'Item 1.1' 1232 'name': 'Item 1.1'
1233 } 1233 }
1234 ] 1234 ]
1235 } 1235 }
1236 ]); 1236 ]);
1237 1237
1238 recursivelySetTemplateModel(div, m); 1238 recursivelySetTemplateModel(div, m);
1239 1239
1240 deliverChanges(m); 1240 deliverChanges(m);
1241 m.removeAt(0); 1241 m.removeAt(0);
1242 deliverChanges(m); 1242 deliverChanges(m);
1243 }); 1243 });
1244 1244
1245 observeTest('DeepNested', () { 1245 observeTest('DeepNested', () {
1246 var div = createTestHtml( 1246 var div = createTestHtml(
1247 '<template bind="{{a}}">' 1247 '<template bind="{{a}}">'
1248 '<p>' 1248 '<p>'
1249 '<template bind="{{b}}">' 1249 '<template bind="{{b}}">'
1250 '{{ c }}' 1250 '{{ c }}'
1251 '</template>' 1251 '</template>'
1252 '</p>' 1252 '</p>'
1253 '</template>'); 1253 '</template>');
1254 1254
1255 var m = toSymbols({ 1255 var m = toObservable({
1256 'a': { 1256 'a': {
1257 'b': { 1257 'b': {
1258 'c': 42 1258 'c': 42
1259 } 1259 }
1260 } 1260 }
1261 }); 1261 });
1262 recursivelySetTemplateModel(div, m); 1262 recursivelySetTemplateModel(div, m);
1263 deliverChanges(m); 1263 deliverChanges(m);
1264 1264
1265 expect(div.nodes[1].tagName, 'P'); 1265 expect(div.nodes[1].tagName, 'P');
1266 expect(div.nodes[1].nodes.first.tagName, 'TEMPLATE'); 1266 expect(div.nodes[1].nodes.first.tagName, 'TEMPLATE');
1267 expect(div.nodes[1].nodes[1].text, '42'); 1267 expect(div.nodes[1].nodes[1].text, '42');
1268 }); 1268 });
1269 1269
1270 observeTest('TemplateContentRemoved', () { 1270 observeTest('TemplateContentRemoved', () {
1271 var div = createTestHtml('<template bind="{{}}">{{ }}</template>'); 1271 var div = createTestHtml('<template bind="{{}}">{{ }}</template>');
1272 var model = 42; 1272 var model = 42;
1273 1273
1274 recursivelySetTemplateModel(div, model); 1274 recursivelySetTemplateModel(div, model);
1275 deliverChanges(model); 1275 deliverChanges(model);
1276 expect(div.nodes[1].text, '42'); 1276 expect(div.nodes[1].text, '42');
1277 expect(div.nodes[0].text, ''); 1277 expect(div.nodes[0].text, '');
1278 }); 1278 });
1279 1279
1280 observeTest('TemplateContentRemovedEmptyArray', () { 1280 observeTest('TemplateContentRemovedEmptyArray', () {
1281 var div = createTestHtml('<template iterate>Remove me</template>'); 1281 var div = createTestHtml('<template iterate>Remove me</template>');
1282 var model = toSymbols([]); 1282 var model = toObservable([]);
1283 1283
1284 recursivelySetTemplateModel(div, model); 1284 recursivelySetTemplateModel(div, model);
1285 deliverChanges(model); 1285 deliverChanges(model);
1286 expect(div.nodes.length, 1); 1286 expect(div.nodes.length, 1);
1287 expect(div.nodes[0].text, ''); 1287 expect(div.nodes[0].text, '');
1288 }); 1288 });
1289 1289
1290 observeTest('TemplateContentRemovedNested', () { 1290 observeTest('TemplateContentRemovedNested', () {
1291 var div = createTestHtml( 1291 var div = createTestHtml(
1292 '<template bind="{{}}">' 1292 '<template bind="{{}}">'
1293 '{{ a }}' 1293 '{{ a }}'
1294 '<template bind="{{}}">' 1294 '<template bind="{{}}">'
1295 '{{ b }}' 1295 '{{ b }}'
1296 '</template>' 1296 '</template>'
1297 '</template>'); 1297 '</template>');
1298 1298
1299 var model = toSymbolMap({ 1299 var model = toObservable({
1300 'a': 1, 1300 'a': 1,
1301 'b': 2 1301 'b': 2
1302 }); 1302 });
1303 recursivelySetTemplateModel(div, model); 1303 recursivelySetTemplateModel(div, model);
1304 deliverChanges(model); 1304 deliverChanges(model);
1305 1305
1306 expect(div.nodes[0].text, ''); 1306 expect(div.nodes[0].text, '');
1307 expect(div.nodes[1].text, '1'); 1307 expect(div.nodes[1].text, '1');
1308 expect(div.nodes[2].text, ''); 1308 expect(div.nodes[2].text, '');
1309 expect(div.nodes[3].text, '2'); 1309 expect(div.nodes[3].text, '2');
1310 }); 1310 });
1311 1311
1312 observeTest('BindWithUndefinedModel', () { 1312 observeTest('BindWithUndefinedModel', () {
1313 var div = createTestHtml( 1313 var div = createTestHtml(
1314 '<template bind="{{}}" if="{{}}">{{ a }}</template>'); 1314 '<template bind="{{}}" if="{{}}">{{ a }}</template>');
1315 1315
1316 var model = toSymbolMap({'a': 42}); 1316 var model = toObservable({'a': 42});
1317 recursivelySetTemplateModel(div, model); 1317 recursivelySetTemplateModel(div, model);
1318 deliverChanges(model); 1318 deliverChanges(model);
1319 expect(div.nodes[1].text, '42'); 1319 expect(div.nodes[1].text, '42');
1320 1320
1321 model = null; 1321 model = null;
1322 recursivelySetTemplateModel(div, model); 1322 recursivelySetTemplateModel(div, model);
1323 deliverChanges(model); 1323 deliverChanges(model);
1324 expect(div.nodes.length, 1); 1324 expect(div.nodes.length, 1);
1325 1325
1326 model = toSymbols({'a': 42}); 1326 model = toObservable({'a': 42});
1327 recursivelySetTemplateModel(div, model); 1327 recursivelySetTemplateModel(div, model);
1328 deliverChanges(model); 1328 deliverChanges(model);
1329 expect(div.nodes[1].text, '42'); 1329 expect(div.nodes[1].text, '42');
1330 }); 1330 });
1331 1331
1332 observeTest('BindNested', () { 1332 observeTest('BindNested', () {
1333 var div = createTestHtml( 1333 var div = createTestHtml(
1334 '<template bind="{{}}">' 1334 '<template bind="{{}}">'
1335 'Name: {{ name }}' 1335 'Name: {{ name }}'
1336 '<template bind="{{wife}}" if="{{wife}}">' 1336 '<template bind="{{wife}}" if="{{wife}}">'
1337 'Wife: {{ name }}' 1337 'Wife: {{ name }}'
1338 '</template>' 1338 '</template>'
1339 '<template bind="{{child}}" if="{{child}}">' 1339 '<template bind="{{child}}" if="{{child}}">'
1340 'Child: {{ name }}' 1340 'Child: {{ name }}'
1341 '</template>' 1341 '</template>'
1342 '</template>'); 1342 '</template>');
1343 1343
1344 var m = toSymbols({ 1344 var m = toObservable({
1345 'name': 'Hermes', 1345 'name': 'Hermes',
1346 'wife': { 1346 'wife': {
1347 'name': 'LaBarbara' 1347 'name': 'LaBarbara'
1348 } 1348 }
1349 }); 1349 });
1350 recursivelySetTemplateModel(div, m); 1350 recursivelySetTemplateModel(div, m);
1351 deliverChanges(m); 1351 deliverChanges(m);
1352 1352
1353 expect(div.nodes.length, 5); 1353 expect(div.nodes.length, 5);
1354 expect(div.nodes[1].text, 'Name: Hermes'); 1354 expect(div.nodes[1].text, 'Name: Hermes');
1355 expect(div.nodes[3].text, 'Wife: LaBarbara'); 1355 expect(div.nodes[3].text, 'Wife: LaBarbara');
1356 1356
1357 m[#child] = toSymbols({'name': 'Dwight'}); 1357 m['child'] = toObservable({'name': 'Dwight'});
1358 deliverChanges(m); 1358 deliverChanges(m);
1359 expect(div.nodes.length, 6); 1359 expect(div.nodes.length, 6);
1360 expect(div.nodes[5].text, 'Child: Dwight'); 1360 expect(div.nodes[5].text, 'Child: Dwight');
1361 1361
1362 m.remove(#wife); 1362 m.remove('wife');
1363 deliverChanges(m); 1363 deliverChanges(m);
1364 expect(div.nodes.length, 5); 1364 expect(div.nodes.length, 5);
1365 expect(div.nodes[4].text, 'Child: Dwight'); 1365 expect(div.nodes[4].text, 'Child: Dwight');
1366 }); 1366 });
1367 1367
1368 observeTest('BindRecursive', () { 1368 observeTest('BindRecursive', () {
1369 var div = createTestHtml( 1369 var div = createTestHtml(
1370 '<template bind="{{}}" if="{{}}" id="t">' 1370 '<template bind="{{}}" if="{{}}" id="t">'
1371 'Name: {{ name }}' 1371 'Name: {{ name }}'
1372 '<template bind="{{friend}}" if="{{friend}}" ref="t"></template>' 1372 '<template bind="{{friend}}" if="{{friend}}" ref="t"></template>'
1373 '</template>'); 1373 '</template>');
1374 1374
1375 var m = toSymbols({ 1375 var m = toObservable({
1376 'name': 'Fry', 1376 'name': 'Fry',
1377 'friend': { 1377 'friend': {
1378 'name': 'Bender' 1378 'name': 'Bender'
1379 } 1379 }
1380 }); 1380 });
1381 recursivelySetTemplateModel(div, m); 1381 recursivelySetTemplateModel(div, m);
1382 deliverChanges(m); 1382 deliverChanges(m);
1383 1383
1384 expect(div.nodes.length, 5); 1384 expect(div.nodes.length, 5);
1385 expect(div.nodes[1].text, 'Name: Fry'); 1385 expect(div.nodes[1].text, 'Name: Fry');
1386 expect(div.nodes[3].text, 'Name: Bender'); 1386 expect(div.nodes[3].text, 'Name: Bender');
1387 1387
1388 m[#friend][#friend] = toSymbols({'name': 'Leela'}); 1388 m['friend']['friend'] = toObservable({'name': 'Leela'});
1389 deliverChanges(m); 1389 deliverChanges(m);
1390 expect(div.nodes.length, 7); 1390 expect(div.nodes.length, 7);
1391 expect(div.nodes[5].text, 'Name: Leela'); 1391 expect(div.nodes[5].text, 'Name: Leela');
1392 1392
1393 m[#friend] = toSymbols({'name': 'Leela'}); 1393 m['friend'] = toObservable({'name': 'Leela'});
1394 deliverChanges(m); 1394 deliverChanges(m);
1395 expect(div.nodes.length, 5); 1395 expect(div.nodes.length, 5);
1396 expect(div.nodes[3].text, 'Name: Leela'); 1396 expect(div.nodes[3].text, 'Name: Leela');
1397 }); 1397 });
1398 1398
1399 observeTest('Template - Self is terminator', () { 1399 observeTest('Template - Self is terminator', () {
1400 var div = createTestHtml( 1400 var div = createTestHtml(
1401 '<template repeat>{{ foo }}' 1401 '<template repeat>{{ foo }}'
1402 '<template bind></template>' 1402 '<template bind></template>'
1403 '</template>'); 1403 '</template>');
1404 1404
1405 var m = toSymbols([{ 'foo': 'bar' }]); 1405 var m = toObservable([{ 'foo': 'bar' }]);
1406 recursivelySetTemplateModel(div, m); 1406 recursivelySetTemplateModel(div, m);
1407 performMicrotaskCheckpoint(); 1407 performMicrotaskCheckpoint();
1408 1408
1409 m.add(toSymbols({ 'foo': 'baz' })); 1409 m.add(toObservable({ 'foo': 'baz' }));
1410 recursivelySetTemplateModel(div, m); 1410 recursivelySetTemplateModel(div, m);
1411 performMicrotaskCheckpoint(); 1411 performMicrotaskCheckpoint();
1412 1412
1413 expect(div.nodes.length, 5); 1413 expect(div.nodes.length, 5);
1414 expect(div.nodes[1].text, 'bar'); 1414 expect(div.nodes[1].text, 'bar');
1415 expect(div.nodes[3].text, 'baz'); 1415 expect(div.nodes[3].text, 'baz');
1416 }); 1416 });
1417 1417
1418 observeTest('Template - Same Contents, Different Array has no effect', () { 1418 observeTest('Template - Same Contents, Different Array has no effect', () {
1419 if (!MutationObserver.supported) return; 1419 if (!MutationObserver.supported) return;
1420 1420
1421 var div = createTestHtml('<template repeat>{{ foo }}</template>'); 1421 var div = createTestHtml('<template repeat>{{ foo }}</template>');
1422 1422
1423 var m = toSymbols([{ 'foo': 'bar' }, { 'foo': 'bat'}]); 1423 var m = toObservable([{ 'foo': 'bar' }, { 'foo': 'bat'}]);
1424 recursivelySetTemplateModel(div, m); 1424 recursivelySetTemplateModel(div, m);
1425 performMicrotaskCheckpoint(); 1425 performMicrotaskCheckpoint();
1426 1426
1427 var observer = new MutationObserver((records, _) {}); 1427 var observer = new MutationObserver((records, _) {});
1428 observer.observe(div, childList: true); 1428 observer.observe(div, childList: true);
1429 1429
1430 var template = div.firstChild; 1430 var template = div.firstChild;
1431 template.bind('repeat', toObservable(m.toList()), ''); 1431 template.bind('repeat', toObservable(m.toList()), '');
1432 performMicrotaskCheckpoint(); 1432 performMicrotaskCheckpoint();
1433 var records = observer.takeRecords(); 1433 var records = observer.takeRecords();
1434 expect(records.length, 0); 1434 expect(records.length, 0);
1435 }); 1435 });
1436 1436
1437 observeTest('RecursiveRef', () { 1437 observeTest('RecursiveRef', () {
1438 var div = createTestHtml( 1438 var div = createTestHtml(
1439 '<template bind>' 1439 '<template bind>'
1440 '<template id=src>{{ foo }}</template>' 1440 '<template id=src>{{ foo }}</template>'
1441 '<template bind ref=src></template>' 1441 '<template bind ref=src></template>'
1442 '</template>'); 1442 '</template>');
1443 1443
1444 var m = toSymbols({'foo': 'bar'}); 1444 var m = toObservable({'foo': 'bar'});
1445 recursivelySetTemplateModel(div, m); 1445 recursivelySetTemplateModel(div, m);
1446 performMicrotaskCheckpoint(); 1446 performMicrotaskCheckpoint();
1447 1447
1448 expect(div.nodes.length, 4); 1448 expect(div.nodes.length, 4);
1449 expect(div.nodes[3].text, 'bar'); 1449 expect(div.nodes[3].text, 'bar');
1450 }); 1450 });
1451 1451
1452 observeTest('ChangeFromBindToRepeat', () { 1452 observeTest('ChangeFromBindToRepeat', () {
1453 var div = createTestHtml( 1453 var div = createTestHtml(
1454 '<template bind="{{a}}">' 1454 '<template bind="{{a}}">'
1455 '{{ length }}' 1455 '{{ length }}'
1456 '</template>'); 1456 '</template>');
1457 var template = div.nodes.first; 1457 var template = div.nodes.first;
1458 1458
1459 // Note: this test data is a little different from the JS version, because 1459 // Note: this test data is a little different from the JS version, because
1460 // we allow binding to the "length" field of the Map in preference to 1460 // we allow binding to the "length" field of the Map in preference to
1461 // binding keys. 1461 // binding keys.
1462 var m = toSymbols({ 1462 var m = toObservable({
1463 'a': [ 1463 'a': [
1464 [], 1464 [],
1465 { 'b': [1,2,3,4] }, 1465 { 'b': [1,2,3,4] },
1466 // Note: this will use the Map "length" property, not the "length" key. 1466 // Note: this will use the Map "length" property, not the "length" key.
1467 {'length': 42, 'c': 123} 1467 {'length': 42, 'c': 123}
1468 ] 1468 ]
1469 }); 1469 });
1470 recursivelySetTemplateModel(div, m); 1470 recursivelySetTemplateModel(div, m);
1471 deliverChanges(m); 1471 deliverChanges(m);
1472 1472
(...skipping 16 matching lines...) Expand all
1489 expect(div.nodes[1].text, '4'); 1489 expect(div.nodes[1].text, '4');
1490 }); 1490 });
1491 1491
1492 observeTest('ChangeRefId', () { 1492 observeTest('ChangeRefId', () {
1493 var div = createTestHtml( 1493 var div = createTestHtml(
1494 '<template id="a">a:{{ }}</template>' 1494 '<template id="a">a:{{ }}</template>'
1495 '<template id="b">b:{{ }}</template>' 1495 '<template id="b">b:{{ }}</template>'
1496 '<template repeat="{{}}">' 1496 '<template repeat="{{}}">'
1497 '<template ref="a" bind="{{}}"></template>' 1497 '<template ref="a" bind="{{}}"></template>'
1498 '</template>'); 1498 '</template>');
1499 var model = toSymbols([]); 1499 var model = toObservable([]);
1500 recursivelySetTemplateModel(div, model); 1500 recursivelySetTemplateModel(div, model);
1501 deliverChanges(model); 1501 deliverChanges(model);
1502 1502
1503 expect(div.nodes.length, 3); 1503 expect(div.nodes.length, 3);
1504 1504
1505 document.getElementById('a').id = 'old-a'; 1505 document.getElementById('a').id = 'old-a';
1506 document.getElementById('b').id = 'a'; 1506 document.getElementById('b').id = 'a';
1507 1507
1508 model..add(1)..add(2); 1508 model..add(1)..add(2);
1509 deliverChanges(model); 1509 deliverChanges(model);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1551 var templateB = templateA.content.nodes.first; 1551 var templateB = templateA.content.nodes.first;
1552 1552
1553 expect(templateB.document, templateA.content.document); 1553 expect(templateB.document, templateA.content.document);
1554 expect(templateB.content.document, templateA.content.document); 1554 expect(templateB.content.document, templateA.content.document);
1555 }); 1555 });
1556 1556
1557 observeTest('BindShadowDOM', () { 1557 observeTest('BindShadowDOM', () {
1558 if (ShadowRoot.supported) { 1558 if (ShadowRoot.supported) {
1559 var root = createShadowTestHtml( 1559 var root = createShadowTestHtml(
1560 '<template bind="{{}}">Hi {{ name }}</template>'); 1560 '<template bind="{{}}">Hi {{ name }}</template>');
1561 var model = toSymbolMap({'name': 'Leela'}); 1561 var model = toObservable({'name': 'Leela'});
1562 recursivelySetTemplateModel(root, model); 1562 recursivelySetTemplateModel(root, model);
1563 deliverChanges(model); 1563 deliverChanges(model);
1564 expect(root.nodes[1].text, 'Hi Leela'); 1564 expect(root.nodes[1].text, 'Hi Leela');
1565 } 1565 }
1566 }); 1566 });
1567 1567
1568 observeTest('BindShadowDOM createInstance', () { 1568 observeTest('BindShadowDOM createInstance', () {
1569 if (ShadowRoot.supported) { 1569 if (ShadowRoot.supported) {
1570 var model = toSymbolMap({'name': 'Leela'}); 1570 var model = toObservable({'name': 'Leela'});
1571 var template = new Element.html('<template>Hi {{ name }}</template>'); 1571 var template = new Element.html('<template>Hi {{ name }}</template>');
1572 var root = createShadowTestHtml(''); 1572 var root = createShadowTestHtml('');
1573 root.nodes.add(template.createInstance(model)); 1573 root.nodes.add(template.createInstance(model));
1574 1574
1575 performMicrotaskCheckpoint(); 1575 performMicrotaskCheckpoint();
1576 expect(root.text, 'Hi Leela'); 1576 expect(root.text, 'Hi Leela');
1577 1577
1578 model[#name] = 'Fry'; 1578 model['name'] = 'Fry';
1579 performMicrotaskCheckpoint(); 1579 performMicrotaskCheckpoint();
1580 expect(root.text, 'Hi Fry'); 1580 expect(root.text, 'Hi Fry');
1581 } 1581 }
1582 }); 1582 });
1583 1583
1584 observeTest('BindShadowDOM Template Ref', () { 1584 observeTest('BindShadowDOM Template Ref', () {
1585 if (ShadowRoot.supported) { 1585 if (ShadowRoot.supported) {
1586 var root = createShadowTestHtml( 1586 var root = createShadowTestHtml(
1587 '<template id=foo>Hi</template><template bind ref=foo></template>'); 1587 '<template id=foo>Hi</template><template bind ref=foo></template>');
1588 recursivelySetTemplateModel(root, toSymbolMap({})); 1588 recursivelySetTemplateModel(root, toObservable({}));
1589 performMicrotaskCheckpoint(); 1589 performMicrotaskCheckpoint();
1590 expect(root.nodes.length, 3); 1590 expect(root.nodes.length, 3);
1591 } 1591 }
1592 }); 1592 });
1593 1593
1594 // https://github.com/toolkitchen/mdv/issues/8 1594 // https://github.com/toolkitchen/mdv/issues/8
1595 observeTest('UnbindingInNestedBind', () { 1595 observeTest('UnbindingInNestedBind', () {
1596 var div = createTestHtml( 1596 var div = createTestHtml(
1597 '<template bind="{{outer}}" if="{{outer}}" syntax="testHelper">' 1597 '<template bind="{{outer}}" if="{{outer}}" syntax="testHelper">'
1598 '<template bind="{{inner}}" if="{{inner}}">' 1598 '<template bind="{{inner}}" if="{{inner}}">'
1599 '{{ age }}' 1599 '{{ age }}'
1600 '</template>' 1600 '</template>'
1601 '</template>'); 1601 '</template>');
1602 1602
1603 var syntax = new UnbindingInNestedBindSyntax(); 1603 var syntax = new UnbindingInNestedBindSyntax();
1604 var model = toSymbolMap({ 1604 var model = toObservable({
1605 'outer': { 1605 'outer': {
1606 'inner': { 1606 'inner': {
1607 'age': 42 1607 'age': 42
1608 } 1608 }
1609 } 1609 }
1610 }); 1610 });
1611 1611
1612 recursivelySetTemplateModel(div, model, syntax); 1612 recursivelySetTemplateModel(div, model, syntax);
1613 1613
1614 deliverChanges(model); 1614 deliverChanges(model);
1615 expect(syntax.count, 1); 1615 expect(syntax.count, 1);
1616 1616
1617 var inner = model[#outer][#inner]; 1617 var inner = model['outer']['inner'];
1618 model[#outer] = null; 1618 model['outer'] = null;
1619 1619
1620 deliverChanges(model); 1620 deliverChanges(model);
1621 expect(syntax.count, 1); 1621 expect(syntax.count, 1);
1622 1622
1623 model[#outer] = toSymbols({'inner': {'age': 2}}); 1623 model['outer'] = toObservable({'inner': {'age': 2}});
1624 syntax.expectedAge = 2; 1624 syntax.expectedAge = 2;
1625 1625
1626 deliverChanges(model); 1626 deliverChanges(model);
1627 expect(syntax.count, 2); 1627 expect(syntax.count, 2);
1628 }); 1628 });
1629 1629
1630 // https://github.com/toolkitchen/mdv/issues/8 1630 // https://github.com/toolkitchen/mdv/issues/8
1631 observeTest('DontCreateInstancesForAbandonedIterators', () { 1631 observeTest('DontCreateInstancesForAbandonedIterators', () {
1632 var div = createTestHtml( 1632 var div = createTestHtml(
1633 '<template bind="{{}} {{}}">' 1633 '<template bind="{{}} {{}}">'
1634 '<template bind="{{}}">Foo' 1634 '<template bind="{{}}">Foo'
1635 '</template>' 1635 '</template>'
1636 '</template>'); 1636 '</template>');
1637 recursivelySetTemplateModel(div, null); 1637 recursivelySetTemplateModel(div, null);
1638 performMicrotaskCheckpoint(); 1638 performMicrotaskCheckpoint();
1639 }); 1639 });
1640 1640
1641 observeTest('CreateInstance', () { 1641 observeTest('CreateInstance', () {
1642 var div = createTestHtml( 1642 var div = createTestHtml(
1643 '<template bind="{{a}}">' 1643 '<template bind="{{a}}">'
1644 '<template bind="{{b}}">' 1644 '<template bind="{{b}}">'
1645 '{{ foo }}:{{ replaceme }}' 1645 '{{ foo }}:{{ replaceme }}'
1646 '</template>' 1646 '</template>'
1647 '</template>'); 1647 '</template>');
1648 var outer = div.nodes.first; 1648 var outer = div.nodes.first;
1649 var model = toSymbolMap({'b': {'foo': 'bar'}}); 1649 var model = toObservable({'b': {'foo': 'bar'}});
1650 1650
1651 var host = new DivElement(); 1651 var host = new DivElement();
1652 var instance = outer.createInstance(model, new TestBindingSyntax()); 1652 var instance = outer.createInstance(model, new TestBindingSyntax());
1653 expect(outer.content.nodes.first, instance.nodes.first.ref); 1653 expect(outer.content.nodes.first, instance.nodes.first.ref);
1654 1654
1655 host.append(instance); 1655 host.append(instance);
1656 performMicrotaskCheckpoint(); 1656 performMicrotaskCheckpoint();
1657 expect(host.firstChild.nextNode.text, 'bar:replaced'); 1657 expect(host.firstChild.nextNode.text, 'bar:replaced');
1658 }); 1658 });
1659 1659
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1719 } 1719 }
1720 1720
1721 class UnbindingInNestedBindSyntax extends BindingDelegate { 1721 class UnbindingInNestedBindSyntax extends BindingDelegate {
1722 int expectedAge = 42; 1722 int expectedAge = 42;
1723 int count = 0; 1723 int count = 0;
1724 1724
1725 getBinding(model, path, name, node) { 1725 getBinding(model, path, name, node) {
1726 if (name != 'text' || path != 'age') 1726 if (name != 'text' || path != 'age')
1727 return; 1727 return;
1728 1728
1729 expect(model[#age], expectedAge); 1729 expect(model['age'], expectedAge);
1730 count++; 1730 count++;
1731 } 1731 }
1732 } 1732 }
1733 1733
1734 /** 1734 /**
1735 * Verifies that the model is Observable, then calls 1735 * Verifies that the model is Observable, then calls
1736 * [performMicrotaskCheckpoint]. 1736 * [performMicrotaskCheckpoint].
1737 */ 1737 */
1738 void deliverChanges(model) { 1738 void deliverChanges(model) {
1739 expectObservable(model); 1739 expectObservable(model);
1740 performMicrotaskCheckpoint(); 1740 performMicrotaskCheckpoint();
1741 } 1741 }
1742 1742
1743 void expectObservable(model) { 1743 void expectObservable(model) {
1744 if (model is! Observable) { 1744 if (model is! Observable) {
1745 // This is here to eagerly catch a bug in the test; it means the test 1745 // This is here to eagerly catch a bug in the test; it means the test
1746 // forgot a toSymbols somewhere. 1746 // forgot a toObservable somewhere.
1747 expect(identical(toSymbols(model), model), true, 1747 expect(identical(toObservable(model), model), true,
1748 reason: 'model type "${model.runtimeType}" should be observable'); 1748 reason: 'model type "${model.runtimeType}" should be observable');
1749 return; 1749 return;
1750 } 1750 }
1751 if (model is ObservableList) { 1751 if (model is ObservableList) {
1752 for (var item in model) { 1752 for (var item in model) {
1753 expectObservable(item); 1753 expectObservable(item);
1754 } 1754 }
1755 } else if (model is ObservableMap) { 1755 } else if (model is ObservableMap) {
1756 model.forEach((k, v) { 1756 model.forEach((k, v) {
1757 expectObservable(k); 1757 expectObservable(k);
1758 expectObservable(v); 1758 expectObservable(v);
1759 }); 1759 });
1760 } 1760 }
1761 } 1761 }
1762 1762
1763 toSymbols(obj) => toObservable(_deepToSymbol(obj));
1764
1765 _deepToSymbol(value) { 1763 _deepToSymbol(value) {
1766 if (value is Map) { 1764 if (value is Map) {
1767 var result = new LinkedHashMap(); 1765 var result = new LinkedHashMap();
1768 value.forEach((k, v) { 1766 value.forEach((k, v) {
1769 k = k is String ? new Symbol(k) : _deepToSymbol(k); 1767 k = k is String ? new Symbol(k) : _deepToSymbol(k);
1770 result[k] = _deepToSymbol(v); 1768 result[k] = _deepToSymbol(v);
1771 }); 1769 });
1772 return result; 1770 return result;
1773 } 1771 }
1774 if (value is Iterable) { 1772 if (value is Iterable) {
1775 return value.map(_deepToSymbol).toList(); 1773 return value.map(_deepToSymbol).toList();
1776 } 1774 }
1777 return value; 1775 return value;
1778 } 1776 }
1779 1777
1780 /** 1778 /**
1781 * Sanitizer which does nothing. 1779 * Sanitizer which does nothing.
1782 */ 1780 */
1783 class NullTreeSanitizer implements NodeTreeSanitizer { 1781 class NullTreeSanitizer implements NodeTreeSanitizer {
1784 void sanitizeTree(Node node) {} 1782 void sanitizeTree(Node node) {}
1785 } 1783 }
OLDNEW
« no previous file with comments | « pkg/mdv/test/node_bindings_test.dart ('k') | pkg/observe/lib/html.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698