OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 = toSymbolMap({ '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[sym('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 = toSymbolMap({ '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[sym('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 = toSymbolMap({ '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[sym('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 = toSymbolMap({ '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[sym('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 = toSymbolMap({'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[sym('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[sym('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 = toSymbolMap({ '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[sym('data')][sym('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[sym('data')] = toSymbols({'b': 'X'}); | 218 model[#data] = toSymbols({'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[sym('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 = toSymbolMap({'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[sym('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[sym('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[sym('d')] = 'here'; | 248 model[#d] = 'here'; |
249 model[sym('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 = toSymbolMap({'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[sym('b')] = toSymbols({'value': 'b'}); | 267 model[#b] = toSymbols({'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 = toSymbolMap({'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[sym('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[sym('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 = toSymbolMap({'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[sym('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 = toSymbols([0, 1, 2]); |
316 recursivelySetTemplateModel(div, model); | 316 recursivelySetTemplateModel(div, model); |
(...skipping 26 matching lines...) Expand all Loading... |
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 final VAL = const Symbol('val'); | 353 model.sort((a, b) => a[#val] - b[#val]); |
354 model.sort((a, b) => a[VAL] - b[VAL]); | |
355 deliverChanges(model); | 354 deliverChanges(model); |
356 checkExpandos(template.nextNode); | 355 checkExpandos(template.nextNode); |
357 | 356 |
358 model = toObservable(model.reversed); | 357 model = toObservable(model.reversed); |
359 recursivelySetTemplateModel(div, model); | 358 recursivelySetTemplateModel(div, model); |
360 deliverChanges(model); | 359 deliverChanges(model); |
361 checkExpandos(template.nextNode); | 360 checkExpandos(template.nextNode); |
362 | 361 |
363 for (var item in model) { | 362 for (var item in model) { |
364 item[VAL] += 1; | 363 item[#val] += 1; |
365 } | 364 } |
366 | 365 |
367 deliverChanges(model); | 366 deliverChanges(model); |
368 expect(div.nodes[1].text, "11"); | 367 expect(div.nodes[1].text, "11"); |
369 expect(div.nodes[2].text, "9"); | 368 expect(div.nodes[2].text, "9"); |
370 expect(div.nodes[3].text, "6"); | 369 expect(div.nodes[3].text, "6"); |
371 expect(div.nodes[4].text, "3"); | 370 expect(div.nodes[4].text, "3"); |
372 expect(div.nodes[5].text, "2"); | 371 expect(div.nodes[5].text, "2"); |
373 }); | 372 }); |
374 | 373 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 for (var i = 0; i < 5; i++) { | 427 for (var i = 0; i < 5; i++) { |
429 expect(nodes[i].text, '$i'); | 428 expect(nodes[i].text, '$i'); |
430 } | 429 } |
431 | 430 |
432 model.length = 3; | 431 model.length = 3; |
433 deliverChanges(model); | 432 deliverChanges(model); |
434 for (var i = 0; i < 5; i++) { | 433 for (var i = 0; i < 5; i++) { |
435 expect(nodes[i].text, '$i'); | 434 expect(nodes[i].text, '$i'); |
436 } | 435 } |
437 | 436 |
438 vs[3][sym('v')] = 33; | 437 vs[3][#v] = 33; |
439 vs[4][sym('v')] = 44; | 438 vs[4][#v] = 44; |
440 deliverChanges(model); | 439 deliverChanges(model); |
441 for (var i = 0; i < 5; i++) { | 440 for (var i = 0; i < 5; i++) { |
442 expect(nodes[i].text, '$i'); | 441 expect(nodes[i].text, '$i'); |
443 } | 442 } |
444 }); | 443 }); |
445 | 444 |
446 observeTest('DOM Stability on Iteration', () { | 445 observeTest('DOM Stability on Iteration', () { |
447 var div = createTestHtml( | 446 var div = createTestHtml( |
448 '<template repeat="{{}}">{{}}</template>'); | 447 '<template repeat="{{}}">{{}}</template>'); |
449 var model = toSymbols([1, 2, 3, 4, 5]); | 448 var model = toSymbols([1, 2, 3, 4, 5]); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 {'value': 2} | 502 {'value': 2} |
504 ]); | 503 ]); |
505 recursivelySetTemplateModel(div, model); | 504 recursivelySetTemplateModel(div, model); |
506 | 505 |
507 deliverChanges(model); | 506 deliverChanges(model); |
508 expect(div.nodes.length, 4); | 507 expect(div.nodes.length, 4); |
509 expect(div.nodes[1].text, '0'); | 508 expect(div.nodes[1].text, '0'); |
510 expect(div.nodes[2].text, '1'); | 509 expect(div.nodes[2].text, '1'); |
511 expect(div.nodes[3].text, '2'); | 510 expect(div.nodes[3].text, '2'); |
512 | 511 |
513 model[1][sym('value')] = 'One'; | 512 model[1][#value] = 'One'; |
514 deliverChanges(model); | 513 deliverChanges(model); |
515 expect(div.nodes.length, 4); | 514 expect(div.nodes.length, 4); |
516 expect(div.nodes[1].text, '0'); | 515 expect(div.nodes[1].text, '0'); |
517 expect(div.nodes[2].text, 'One'); | 516 expect(div.nodes[2].text, 'One'); |
518 expect(div.nodes[3].text, '2'); | 517 expect(div.nodes[3].text, '2'); |
519 | 518 |
520 model.replaceRange(0, 1, toSymbols([{'value': 'Zero'}])); | 519 model.replaceRange(0, 1, toSymbols([{'value': 'Zero'}])); |
521 deliverChanges(model); | 520 deliverChanges(model); |
522 expect(div.nodes.length, 4); | 521 expect(div.nodes.length, 4); |
523 expect(div.nodes[1].text, 'Zero'); | 522 expect(div.nodes[1].text, 'Zero'); |
524 expect(div.nodes[2].text, 'One'); | 523 expect(div.nodes[2].text, 'One'); |
525 expect(div.nodes[3].text, '2'); | 524 expect(div.nodes[3].text, '2'); |
526 }); | 525 }); |
527 | 526 |
528 observeTest('TemplateWithInputValue', () { | 527 observeTest('TemplateWithInputValue', () { |
529 var div = createTestHtml( | 528 var div = createTestHtml( |
530 '<template bind="{{}}">' | 529 '<template bind="{{}}">' |
531 '<input value="{{x}}">' | 530 '<input value="{{x}}">' |
532 '</template>'); | 531 '</template>'); |
533 var model = toSymbolMap({'x': 'hi'}); | 532 var model = toSymbolMap({'x': 'hi'}); |
534 recursivelySetTemplateModel(div, model); | 533 recursivelySetTemplateModel(div, model); |
535 | 534 |
536 deliverChanges(model); | 535 deliverChanges(model); |
537 expect(div.nodes.length, 2); | 536 expect(div.nodes.length, 2); |
538 expect(div.nodes.last.value, 'hi'); | 537 expect(div.nodes.last.value, 'hi'); |
539 | 538 |
540 model[sym('x')] = 'bye'; | 539 model[#x] = 'bye'; |
541 expect(div.nodes.last.value, 'hi'); | 540 expect(div.nodes.last.value, 'hi'); |
542 deliverChanges(model); | 541 deliverChanges(model); |
543 expect(div.nodes.last.value, 'bye'); | 542 expect(div.nodes.last.value, 'bye'); |
544 | 543 |
545 div.nodes.last.value = 'hello'; | 544 div.nodes.last.value = 'hello'; |
546 dispatchEvent('input', div.nodes.last); | 545 dispatchEvent('input', div.nodes.last); |
547 expect(model[sym('x')], 'hello'); | 546 expect(model[#x], 'hello'); |
548 deliverChanges(model); | 547 deliverChanges(model); |
549 expect(div.nodes.last.value, 'hello'); | 548 expect(div.nodes.last.value, 'hello'); |
550 }); | 549 }); |
551 | 550 |
552 ////////////////////////////////////////////////////////////////////////////// | 551 ////////////////////////////////////////////////////////////////////////////// |
553 | 552 |
554 observeTest('Decorated', () { | 553 observeTest('Decorated', () { |
555 var div = createTestHtml( | 554 var div = createTestHtml( |
556 '<template bind="{{ XX }}" id="t1">' | 555 '<template bind="{{ XX }}" id="t1">' |
557 '<p>Crew member: {{name}}, Job title: {{title}}</p>' | 556 '<p>Crew member: {{name}}, Job title: {{title}}</p>' |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 {'name': 'Arv'}, | 690 {'name': 'Arv'}, |
692 {'name': 'Neal'} | 691 {'name': 'Neal'} |
693 ] | 692 ] |
694 }); | 693 }); |
695 | 694 |
696 recursivelySetTemplateModel(div, m); | 695 recursivelySetTemplateModel(div, m); |
697 deliverChanges(m); | 696 deliverChanges(m); |
698 | 697 |
699 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); | 698 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); |
700 | 699 |
701 m[sym('contacts')].add(toSymbols({'name': 'Alex'})); | 700 m[#contacts].add(toSymbols({'name': 'Alex'})); |
702 deliverChanges(m); | 701 deliverChanges(m); |
703 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']); | 702 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']); |
704 | 703 |
705 m[sym('contacts')].replaceRange(0, 2, | 704 m[#contacts].replaceRange(0, 2, |
706 toSymbols([{'name': 'Rafael'}, {'name': 'Erik'}])); | 705 toSymbols([{'name': 'Rafael'}, {'name': 'Erik'}])); |
707 deliverChanges(m); | 706 deliverChanges(m); |
708 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Neal', 'Hi Alex']); | 707 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Neal', 'Hi Alex']); |
709 | 708 |
710 m[sym('contacts')].removeRange(1, 3); | 709 m[#contacts].removeRange(1, 3); |
711 deliverChanges(m); | 710 deliverChanges(m); |
712 assertNodesAre(div, ['Hi Rafael', 'Hi Alex']); | 711 assertNodesAre(div, ['Hi Rafael', 'Hi Alex']); |
713 | 712 |
714 m[sym('contacts')].insertAll(1, | 713 m[#contacts].insertAll(1, |
715 toSymbols([{'name': 'Erik'}, {'name': 'Dimitri'}])); | 714 toSymbols([{'name': 'Erik'}, {'name': 'Dimitri'}])); |
716 deliverChanges(m); | 715 deliverChanges(m); |
717 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']); | 716 assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']); |
718 | 717 |
719 m[sym('contacts')].replaceRange(0, 1, | 718 m[#contacts].replaceRange(0, 1, |
720 toSymbols([{'name': 'Tab'}, {'name': 'Neal'}])); | 719 toSymbols([{'name': 'Tab'}, {'name': 'Neal'}])); |
721 deliverChanges(m); | 720 deliverChanges(m); |
722 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'
]); |
723 | 722 |
724 m[sym('contacts')] = toSymbols([{'name': 'Alex'}]); | 723 m[#contacts] = toSymbols([{'name': 'Alex'}]); |
725 deliverChanges(m); | 724 deliverChanges(m); |
726 assertNodesAre(div, ['Hi Alex']); | 725 assertNodesAre(div, ['Hi Alex']); |
727 | 726 |
728 m[sym('contacts')].length = 0; | 727 m[#contacts].length = 0; |
729 deliverChanges(m); | 728 deliverChanges(m); |
730 assertNodesAre(div, []); | 729 assertNodesAre(div, []); |
731 }); | 730 }); |
732 | 731 |
733 observeTest('RepeatModelSet', () { | 732 observeTest('RepeatModelSet', () { |
734 var div = createTestHtml( | 733 var div = createTestHtml( |
735 '<template repeat="{{ contacts }}">' | 734 '<template repeat="{{ contacts }}">' |
736 'Hi {{ name }}' | 735 'Hi {{ name }}' |
737 '</template>'); | 736 '</template>'); |
738 var m = toSymbols({ | 737 var m = toSymbols({ |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 }); | 884 }); |
886 | 885 |
887 recursivelySetTemplateModel(div, m); | 886 recursivelySetTemplateModel(div, m); |
888 deliverChanges(m); | 887 deliverChanges(m); |
889 | 888 |
890 var i = start; | 889 var i = start; |
891 expect(div.nodes[i++].text, '1'); | 890 expect(div.nodes[i++].text, '1'); |
892 expect(div.nodes[i++].tagName, 'TEMPLATE'); | 891 expect(div.nodes[i++].tagName, 'TEMPLATE'); |
893 expect(div.nodes[i++].text, '2'); | 892 expect(div.nodes[i++].text, '2'); |
894 | 893 |
895 m[sym('a')][sym('b')] = 11; | 894 m[#a][#b] = 11; |
896 deliverChanges(m); | 895 deliverChanges(m); |
897 expect(div.nodes[start].text, '11'); | 896 expect(div.nodes[start].text, '11'); |
898 | 897 |
899 m[sym('a')][sym('c')] = toSymbols({'d': 22}); | 898 m[#a][#c] = toSymbols({'d': 22}); |
900 deliverChanges(m); | 899 deliverChanges(m); |
901 expect(div.nodes[start + 2].text, '22'); | 900 expect(div.nodes[start + 2].text, '22'); |
902 } | 901 } |
903 | 902 |
904 observeTest('Nested', () { | 903 observeTest('Nested', () { |
905 nestedHelper( | 904 nestedHelper( |
906 '<template bind="{{a}}">' | 905 '<template bind="{{a}}">' |
907 '{{b}}' | 906 '{{b}}' |
908 '<template bind="{{c}}">' | 907 '<template bind="{{c}}">' |
909 '{{d}}' | 908 '{{d}}' |
(...skipping 30 matching lines...) Expand all Loading... |
940 deliverChanges(m); | 939 deliverChanges(m); |
941 | 940 |
942 var i = start; | 941 var i = start; |
943 expect(div.nodes[i++].text, '1'); | 942 expect(div.nodes[i++].text, '1'); |
944 expect(div.nodes[i++].tagName, 'TEMPLATE'); | 943 expect(div.nodes[i++].tagName, 'TEMPLATE'); |
945 expect(div.nodes[i++].text, '11'); | 944 expect(div.nodes[i++].text, '11'); |
946 expect(div.nodes[i++].text, '2'); | 945 expect(div.nodes[i++].text, '2'); |
947 expect(div.nodes[i++].tagName, 'TEMPLATE'); | 946 expect(div.nodes[i++].tagName, 'TEMPLATE'); |
948 expect(div.nodes[i++].text, '22'); | 947 expect(div.nodes[i++].text, '22'); |
949 | 948 |
950 m[sym('a')][1] = toSymbols({ | 949 m[#a][1] = toSymbols({ |
951 'b': 3, | 950 'b': 3, |
952 'c': {'d': 33} | 951 'c': {'d': 33} |
953 }); | 952 }); |
954 | 953 |
955 deliverChanges(m); | 954 deliverChanges(m); |
956 expect(div.nodes[start + 3].text, '3'); | 955 expect(div.nodes[start + 3].text, '3'); |
957 expect(div.nodes[start + 5].text, '33'); | 956 expect(div.nodes[start + 5].text, '33'); |
958 } | 957 } |
959 | 958 |
960 observeTest('NestedRepeatBind', () { | 959 observeTest('NestedRepeatBind', () { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1000 var i = start; | 999 var i = start; |
1001 expect(div.nodes[i++].text, '1'); | 1000 expect(div.nodes[i++].text, '1'); |
1002 expect(div.nodes[i++].tagName, 'TEMPLATE'); | 1001 expect(div.nodes[i++].tagName, 'TEMPLATE'); |
1003 expect(div.nodes[i++].text, '11'); | 1002 expect(div.nodes[i++].text, '11'); |
1004 expect(div.nodes[i++].text, '12'); | 1003 expect(div.nodes[i++].text, '12'); |
1005 expect(div.nodes[i++].text, '2'); | 1004 expect(div.nodes[i++].text, '2'); |
1006 expect(div.nodes[i++].tagName, 'TEMPLATE'); | 1005 expect(div.nodes[i++].tagName, 'TEMPLATE'); |
1007 expect(div.nodes[i++].text, '21'); | 1006 expect(div.nodes[i++].text, '21'); |
1008 expect(div.nodes[i++].text, '22'); | 1007 expect(div.nodes[i++].text, '22'); |
1009 | 1008 |
1010 m[sym('a')][1] = toSymbols({ | 1009 m[#a][1] = toSymbols({ |
1011 'b': 3, | 1010 'b': 3, |
1012 'c': [{'d': 31}, {'d': 32}, {'d': 33}] | 1011 'c': [{'d': 31}, {'d': 32}, {'d': 33}] |
1013 }); | 1012 }); |
1014 | 1013 |
1015 i = start + 4; | 1014 i = start + 4; |
1016 deliverChanges(m); | 1015 deliverChanges(m); |
1017 expect(div.nodes[start + 4].text, '3'); | 1016 expect(div.nodes[start + 4].text, '3'); |
1018 expect(div.nodes[start + 6].text, '31'); | 1017 expect(div.nodes[start + 6].text, '31'); |
1019 expect(div.nodes[start + 7].text, '32'); | 1018 expect(div.nodes[start + 7].text, '32'); |
1020 expect(div.nodes[start + 8].text, '33'); | 1019 expect(div.nodes[start + 8].text, '33'); |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 'name': 'LaBarbara' | 1347 'name': 'LaBarbara' |
1349 } | 1348 } |
1350 }); | 1349 }); |
1351 recursivelySetTemplateModel(div, m); | 1350 recursivelySetTemplateModel(div, m); |
1352 deliverChanges(m); | 1351 deliverChanges(m); |
1353 | 1352 |
1354 expect(div.nodes.length, 5); | 1353 expect(div.nodes.length, 5); |
1355 expect(div.nodes[1].text, 'Name: Hermes'); | 1354 expect(div.nodes[1].text, 'Name: Hermes'); |
1356 expect(div.nodes[3].text, 'Wife: LaBarbara'); | 1355 expect(div.nodes[3].text, 'Wife: LaBarbara'); |
1357 | 1356 |
1358 m[sym('child')] = toSymbols({'name': 'Dwight'}); | 1357 m[#child] = toSymbols({'name': 'Dwight'}); |
1359 deliverChanges(m); | 1358 deliverChanges(m); |
1360 expect(div.nodes.length, 6); | 1359 expect(div.nodes.length, 6); |
1361 expect(div.nodes[5].text, 'Child: Dwight'); | 1360 expect(div.nodes[5].text, 'Child: Dwight'); |
1362 | 1361 |
1363 m.remove(sym('wife')); | 1362 m.remove(#wife); |
1364 deliverChanges(m); | 1363 deliverChanges(m); |
1365 expect(div.nodes.length, 5); | 1364 expect(div.nodes.length, 5); |
1366 expect(div.nodes[4].text, 'Child: Dwight'); | 1365 expect(div.nodes[4].text, 'Child: Dwight'); |
1367 }); | 1366 }); |
1368 | 1367 |
1369 observeTest('BindRecursive', () { | 1368 observeTest('BindRecursive', () { |
1370 var div = createTestHtml( | 1369 var div = createTestHtml( |
1371 '<template bind="{{}}" if="{{}}" id="t">' | 1370 '<template bind="{{}}" if="{{}}" id="t">' |
1372 'Name: {{ name }}' | 1371 'Name: {{ name }}' |
1373 '<template bind="{{friend}}" if="{{friend}}" ref="t"></template>' | 1372 '<template bind="{{friend}}" if="{{friend}}" ref="t"></template>' |
1374 '</template>'); | 1373 '</template>'); |
1375 | 1374 |
1376 var m = toSymbols({ | 1375 var m = toSymbols({ |
1377 'name': 'Fry', | 1376 'name': 'Fry', |
1378 'friend': { | 1377 'friend': { |
1379 'name': 'Bender' | 1378 'name': 'Bender' |
1380 } | 1379 } |
1381 }); | 1380 }); |
1382 recursivelySetTemplateModel(div, m); | 1381 recursivelySetTemplateModel(div, m); |
1383 deliverChanges(m); | 1382 deliverChanges(m); |
1384 | 1383 |
1385 expect(div.nodes.length, 5); | 1384 expect(div.nodes.length, 5); |
1386 expect(div.nodes[1].text, 'Name: Fry'); | 1385 expect(div.nodes[1].text, 'Name: Fry'); |
1387 expect(div.nodes[3].text, 'Name: Bender'); | 1386 expect(div.nodes[3].text, 'Name: Bender'); |
1388 | 1387 |
1389 m[sym('friend')][sym('friend')] = toSymbols({'name': 'Leela'}); | 1388 m[#friend][#friend] = toSymbols({'name': 'Leela'}); |
1390 deliverChanges(m); | 1389 deliverChanges(m); |
1391 expect(div.nodes.length, 7); | 1390 expect(div.nodes.length, 7); |
1392 expect(div.nodes[5].text, 'Name: Leela'); | 1391 expect(div.nodes[5].text, 'Name: Leela'); |
1393 | 1392 |
1394 m[sym('friend')] = toSymbols({'name': 'Leela'}); | 1393 m[#friend] = toSymbols({'name': 'Leela'}); |
1395 deliverChanges(m); | 1394 deliverChanges(m); |
1396 expect(div.nodes.length, 5); | 1395 expect(div.nodes.length, 5); |
1397 expect(div.nodes[3].text, 'Name: Leela'); | 1396 expect(div.nodes[3].text, 'Name: Leela'); |
1398 }); | 1397 }); |
1399 | 1398 |
1400 observeTest('Template - Self is terminator', () { | 1399 observeTest('Template - Self is terminator', () { |
1401 var div = createTestHtml( | 1400 var div = createTestHtml( |
1402 '<template repeat>{{ foo }}' | 1401 '<template repeat>{{ foo }}' |
1403 '<template bind></template>' | 1402 '<template bind></template>' |
1404 '</template>'); | 1403 '</template>'); |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1569 observeTest('BindShadowDOM createInstance', () { | 1568 observeTest('BindShadowDOM createInstance', () { |
1570 if (ShadowRoot.supported) { | 1569 if (ShadowRoot.supported) { |
1571 var model = toSymbolMap({'name': 'Leela'}); | 1570 var model = toSymbolMap({'name': 'Leela'}); |
1572 var template = new Element.html('<template>Hi {{ name }}</template>'); | 1571 var template = new Element.html('<template>Hi {{ name }}</template>'); |
1573 var root = createShadowTestHtml(''); | 1572 var root = createShadowTestHtml(''); |
1574 root.nodes.add(template.createInstance(model)); | 1573 root.nodes.add(template.createInstance(model)); |
1575 | 1574 |
1576 performMicrotaskCheckpoint(); | 1575 performMicrotaskCheckpoint(); |
1577 expect(root.text, 'Hi Leela'); | 1576 expect(root.text, 'Hi Leela'); |
1578 | 1577 |
1579 model[sym('name')] = 'Fry'; | 1578 model[#name] = 'Fry'; |
1580 performMicrotaskCheckpoint(); | 1579 performMicrotaskCheckpoint(); |
1581 expect(root.text, 'Hi Fry'); | 1580 expect(root.text, 'Hi Fry'); |
1582 } | 1581 } |
1583 }); | 1582 }); |
1584 | 1583 |
1585 observeTest('BindShadowDOM Template Ref', () { | 1584 observeTest('BindShadowDOM Template Ref', () { |
1586 if (ShadowRoot.supported) { | 1585 if (ShadowRoot.supported) { |
1587 var root = createShadowTestHtml( | 1586 var root = createShadowTestHtml( |
1588 '<template id=foo>Hi</template><template bind ref=foo></template>'); | 1587 '<template id=foo>Hi</template><template bind ref=foo></template>'); |
1589 recursivelySetTemplateModel(root, toSymbolMap({})); | 1588 recursivelySetTemplateModel(root, toSymbolMap({})); |
(...skipping 18 matching lines...) Expand all Loading... |
1608 'age': 42 | 1607 'age': 42 |
1609 } | 1608 } |
1610 } | 1609 } |
1611 }); | 1610 }); |
1612 | 1611 |
1613 recursivelySetTemplateModel(div, model, syntax); | 1612 recursivelySetTemplateModel(div, model, syntax); |
1614 | 1613 |
1615 deliverChanges(model); | 1614 deliverChanges(model); |
1616 expect(syntax.count, 1); | 1615 expect(syntax.count, 1); |
1617 | 1616 |
1618 var inner = model[sym('outer')][sym('inner')]; | 1617 var inner = model[#outer][#inner]; |
1619 model[sym('outer')] = null; | 1618 model[#outer] = null; |
1620 | 1619 |
1621 deliverChanges(model); | 1620 deliverChanges(model); |
1622 expect(syntax.count, 1); | 1621 expect(syntax.count, 1); |
1623 | 1622 |
1624 model[sym('outer')] = toSymbols({'inner': {'age': 2}}); | 1623 model[#outer] = toSymbols({'inner': {'age': 2}}); |
1625 syntax.expectedAge = 2; | 1624 syntax.expectedAge = 2; |
1626 | 1625 |
1627 deliverChanges(model); | 1626 deliverChanges(model); |
1628 expect(syntax.count, 2); | 1627 expect(syntax.count, 2); |
1629 }); | 1628 }); |
1630 | 1629 |
1631 // https://github.com/toolkitchen/mdv/issues/8 | 1630 // https://github.com/toolkitchen/mdv/issues/8 |
1632 observeTest('DontCreateInstancesForAbandonedIterators', () { | 1631 observeTest('DontCreateInstancesForAbandonedIterators', () { |
1633 var div = createTestHtml( | 1632 var div = createTestHtml( |
1634 '<template bind="{{}} {{}}">' | 1633 '<template bind="{{}} {{}}">' |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1720 } | 1719 } |
1721 | 1720 |
1722 class UnbindingInNestedBindSyntax extends BindingDelegate { | 1721 class UnbindingInNestedBindSyntax extends BindingDelegate { |
1723 int expectedAge = 42; | 1722 int expectedAge = 42; |
1724 int count = 0; | 1723 int count = 0; |
1725 | 1724 |
1726 getBinding(model, path, name, node) { | 1725 getBinding(model, path, name, node) { |
1727 if (name != 'text' || path != 'age') | 1726 if (name != 'text' || path != 'age') |
1728 return; | 1727 return; |
1729 | 1728 |
1730 expect(model[sym('age')], expectedAge); | 1729 expect(model[#age], expectedAge); |
1731 count++; | 1730 count++; |
1732 } | 1731 } |
1733 } | 1732 } |
1734 | 1733 |
1735 /** | 1734 /** |
1736 * Verifies that the model is Observable, then calls | 1735 * Verifies that the model is Observable, then calls |
1737 * [performMicrotaskCheckpoint]. | 1736 * [performMicrotaskCheckpoint]. |
1738 */ | 1737 */ |
1739 void deliverChanges(model) { | 1738 void deliverChanges(model) { |
1740 expectObservable(model); | 1739 expectObservable(model); |
(...skipping 15 matching lines...) Expand all Loading... |
1756 } else if (model is ObservableMap) { | 1755 } else if (model is ObservableMap) { |
1757 model.forEach((k, v) { | 1756 model.forEach((k, v) { |
1758 expectObservable(k); | 1757 expectObservable(k); |
1759 expectObservable(v); | 1758 expectObservable(v); |
1760 }); | 1759 }); |
1761 } | 1760 } |
1762 } | 1761 } |
1763 | 1762 |
1764 toSymbols(obj) => toObservable(_deepToSymbol(obj)); | 1763 toSymbols(obj) => toObservable(_deepToSymbol(obj)); |
1765 | 1764 |
1766 sym(x) => new Symbol(x); | |
1767 | |
1768 _deepToSymbol(value) { | 1765 _deepToSymbol(value) { |
1769 if (value is Map) { | 1766 if (value is Map) { |
1770 var result = new LinkedHashMap(); | 1767 var result = new LinkedHashMap(); |
1771 value.forEach((k, v) { | 1768 value.forEach((k, v) { |
1772 k = k is String ? sym(k) : _deepToSymbol(k); | 1769 k = k is String ? new Symbol(k) : _deepToSymbol(k); |
1773 result[k] = _deepToSymbol(v); | 1770 result[k] = _deepToSymbol(v); |
1774 }); | 1771 }); |
1775 return result; | 1772 return result; |
1776 } | 1773 } |
1777 if (value is Iterable) { | 1774 if (value is Iterable) { |
1778 return value.map(_deepToSymbol).toList(); | 1775 return value.map(_deepToSymbol).toList(); |
1779 } | 1776 } |
1780 return value; | 1777 return value; |
1781 } | 1778 } |
1782 | 1779 |
1783 /** | 1780 /** |
1784 * Sanitizer which does nothing. | 1781 * Sanitizer which does nothing. |
1785 */ | 1782 */ |
1786 class NullTreeSanitizer implements NodeTreeSanitizer { | 1783 class NullTreeSanitizer implements NodeTreeSanitizer { |
1787 void sanitizeTree(Node node) {} | 1784 void sanitizeTree(Node node) {} |
1788 } | 1785 } |
OLD | NEW |