| 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_binding.test.template_binding_test; | 5 library template_binding.test.template_binding_test; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:html'; | 8 import 'dart:html'; |
| 9 import 'dart:js' show JsObject; |
| 9 import 'dart:math' as math; | 10 import 'dart:math' as math; |
| 10 import 'package:observe/observe.dart'; | 11 import 'package:observe/observe.dart'; |
| 11 import 'package:template_binding/template_binding.dart'; | 12 import 'package:template_binding/template_binding.dart'; |
| 12 import 'package:unittest/html_config.dart'; | 13 import 'package:unittest/html_config.dart'; |
| 13 import 'package:unittest/unittest.dart'; | 14 import 'package:unittest/unittest.dart'; |
| 14 | 15 |
| 15 // TODO(jmesserly): merge this file? | 16 // TODO(jmesserly): merge this file? |
| 16 import 'binding_syntax.dart' show syntaxTests; | 17 import 'binding_syntax.dart' show syntaxTests; |
| 17 import 'utils.dart'; | 18 import 'utils.dart'; |
| 18 | 19 |
| 19 // Note: this file ported from | 20 // Note: this file ported from TemplateBinding's tests/tests.js |
| 20 // https://github.com/Polymer/TemplateBinding/blob/fcb7a502794f19544f2d4b77c96ee
bb70830591d/tests/tests.js | |
| 21 | 21 |
| 22 // TODO(jmesserly): submit a small cleanup patch to original. I fixed some | 22 // TODO(jmesserly): submit a small cleanup patch to original. I fixed some |
| 23 // cases where "div" and "t" were unintentionally using the JS global scope; | 23 // cases where "div" and "t" were unintentionally using the JS global scope; |
| 24 // look for "assertNodesAre". | 24 // look for "assertNodesAre". |
| 25 | 25 |
| 26 main() => dirtyCheckZone().run(() { | 26 main() => dirtyCheckZone().run(() { |
| 27 useHtmlConfiguration(); | 27 useHtmlConfiguration(); |
| 28 | 28 |
| 29 // Load MutationObserver polyfill in case IE needs it. | 29 // Load MutationObserver polyfill in case IE needs it. |
| 30 var script = new ScriptElement() | 30 var script = new ScriptElement() |
| 31 ..src = '/root_dart/pkg/mutation_observer/lib/mutation_observer.min.js'; | 31 ..src = '/root_dart/pkg/mutation_observer/lib/mutation_observer.min.js'; |
| 32 var polyfillLoaded = script.onLoad.first; | 32 var polyfillLoaded = script.onLoad.first; |
| 33 document.head.append(script); | 33 document.head.append(script); |
| 34 | 34 |
| 35 setUp(() => polyfillLoaded.then((_) { | 35 setUp(() => polyfillLoaded.then((_) { |
| 36 document.body.append(testDiv = new DivElement()); | 36 document.body.append(testDiv = new DivElement()); |
| 37 })); | 37 })); |
| 38 | 38 |
| 39 tearDown(() { | 39 tearDown(() { |
| 40 testDiv.remove(); | 40 testDiv.remove(); |
| 41 clearAllTemplates(testDiv); |
| 41 testDiv = null; | 42 testDiv = null; |
| 42 }); | 43 }); |
| 43 | 44 |
| 44 test('MutationObserver is supported', () { | 45 test('MutationObserver is supported', () { |
| 45 expect(MutationObserver.supported, true, reason: 'polyfill was loaded.'); | 46 expect(MutationObserver.supported, true, reason: 'polyfill was loaded.'); |
| 46 }); | 47 }); |
| 47 | 48 |
| 48 group('Template', templateInstantiationTests); | 49 group('Template', templateInstantiationTests); |
| 49 | 50 |
| 50 group('Binding Delegate API', () { | 51 group('Binding Delegate API', () { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 72 expect(node, isNotNull); | 73 expect(node, isNotNull); |
| 73 while (node != null) { | 74 while (node != null) { |
| 74 expect(expando[node], node.text); | 75 expect(expando[node], node.text); |
| 75 node = node.nextNode; | 76 node = node.nextNode; |
| 76 } | 77 } |
| 77 } | 78 } |
| 78 | 79 |
| 79 templateInstantiationTests() { | 80 templateInstantiationTests() { |
| 80 // Dart note: renamed some of these tests to have unique names | 81 // Dart note: renamed some of these tests to have unique names |
| 81 | 82 |
| 82 test('Bind (simple)', () { | 83 test('accessing bindingDelegate getter without Bind', () { |
| 84 var div = createTestHtml('<template>'); |
| 85 var template = div.firstChild; |
| 86 expect(templateBind(template).bindingDelegate, null); |
| 87 }); |
| 88 |
| 89 test('Bind - simple', () { |
| 83 var div = createTestHtml('<template bind={{}}>text</template>'); | 90 var div = createTestHtml('<template bind={{}}>text</template>'); |
| 84 templateBind(div.firstChild).model = {}; | 91 templateBind(div.firstChild).model = {}; |
| 85 return new Future(() { | 92 return new Future(() { |
| 86 expect(div.nodes.length, 2); | 93 expect(div.nodes.length, 2); |
| 87 expect(div.nodes.last.text, 'text'); | 94 expect(div.nodes.last.text, 'text'); |
| 88 | 95 |
| 89 // Dart note: null is used instead of undefined to clear the template. | 96 // Dart note: null is used instead of undefined to clear the template. |
| 90 templateBind(div.firstChild).model = null; | 97 templateBind(div.firstChild).model = null; |
| 91 | 98 |
| 92 }).then(endOfMicrotask).then((_) { | 99 }).then(endOfMicrotask).then((_) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 expect(template.nodes.length, 0); | 132 expect(template.nodes.length, 0); |
| 126 expect(template.nextNode, null); | 133 expect(template.nextNode, null); |
| 127 }); | 134 }); |
| 128 }); | 135 }); |
| 129 | 136 |
| 130 test('Bind - no defaultView', () { | 137 test('Bind - no defaultView', () { |
| 131 var div = createTestHtml('<template bind>text</template>'); | 138 var div = createTestHtml('<template bind>text</template>'); |
| 132 var template = div.firstChild; | 139 var template = div.firstChild; |
| 133 var doc = document.implementation.createHtmlDocument(''); | 140 var doc = document.implementation.createHtmlDocument(''); |
| 134 doc.adoptNode(div); | 141 doc.adoptNode(div); |
| 135 recursivelySetTemplateModel(template, {}); | 142 templateBind(template).model = {}; |
| 136 return new Future(() => expect(div.nodes.length, 1)); | 143 return new Future(() => expect(div.nodes.length, 2)); |
| 137 }); | 144 }); |
| 138 | 145 |
| 139 test('Empty Bind', () { | 146 test('Empty Bind', () { |
| 140 var div = createTestHtml('<template bind>text</template>'); | 147 var div = createTestHtml('<template bind>text</template>'); |
| 141 var template = div.firstChild; | 148 var template = div.firstChild; |
| 142 templateBind(template).model = {}; | 149 templateBind(template).model = {}; |
| 143 return new Future(() { | 150 return new Future(() { |
| 144 expect(div.nodes.length, 2); | 151 expect(div.nodes.length, 2); |
| 145 expect(div.nodes.last.text, 'text'); | 152 expect(div.nodes.last.text, 'text'); |
| 146 }); | 153 }); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 templateBind(template).model = null; | 356 templateBind(template).model = null; |
| 350 | 357 |
| 351 }).then(endOfMicrotask).then((_) { | 358 }).then(endOfMicrotask).then((_) { |
| 352 expect(div.nodes.length, 1); | 359 expect(div.nodes.length, 1); |
| 353 }); | 360 }); |
| 354 }); | 361 }); |
| 355 | 362 |
| 356 test('Bind If, 2', () { | 363 test('Bind If, 2', () { |
| 357 var div = createTestHtml( | 364 var div = createTestHtml( |
| 358 '<template bind="{{ foo }}" if="{{ bar }}">{{ bat }}</template>'); | 365 '<template bind="{{ foo }}" if="{{ bar }}">{{ bat }}</template>'); |
| 366 var template = div.firstChild; |
| 359 var m = toObservable({ 'bar': null, 'foo': { 'bat': 'baz' } }); | 367 var m = toObservable({ 'bar': null, 'foo': { 'bat': 'baz' } }); |
| 360 recursivelySetTemplateModel(div, m); | 368 templateBind(template).model = m; |
| 361 return new Future(() { | 369 return new Future(() { |
| 362 expect(div.nodes.length, 1); | 370 expect(div.nodes.length, 1); |
| 363 | 371 |
| 364 m['bar'] = 1; | 372 m['bar'] = 1; |
| 365 }).then(endOfMicrotask).then((_) { | 373 }).then(endOfMicrotask).then((_) { |
| 366 expect(div.nodes.length, 2); | 374 expect(div.nodes.length, 2); |
| 367 expect(div.lastChild.text, 'baz'); | 375 expect(div.lastChild.text, 'baz'); |
| 368 }); | 376 }); |
| 369 }); | 377 }); |
| 370 | 378 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 384 expect(div.lastChild.text, 'foo'); | 392 expect(div.lastChild.text, 'foo'); |
| 385 | 393 |
| 386 templateBind(template).model = null; | 394 templateBind(template).model = null; |
| 387 }).then(endOfMicrotask).then((_) { | 395 }).then(endOfMicrotask).then((_) { |
| 388 expect(div.nodes.length, 1); | 396 expect(div.nodes.length, 1); |
| 389 }); | 397 }); |
| 390 }); | 398 }); |
| 391 | 399 |
| 392 test('Empty-If', () { | 400 test('Empty-If', () { |
| 393 var div = createTestHtml('<template if>{{ value }}</template>'); | 401 var div = createTestHtml('<template if>{{ value }}</template>'); |
| 402 var template = div.firstChild; |
| 394 var m = toObservable({ 'value': 'foo' }); | 403 var m = toObservable({ 'value': 'foo' }); |
| 395 recursivelySetTemplateModel(div, null); | 404 templateBind(template).model = null; |
| 396 return new Future(() { | 405 return new Future(() { |
| 397 expect(div.nodes.length, 1); | 406 expect(div.nodes.length, 1); |
| 398 | 407 |
| 399 recursivelySetTemplateModel(div, m); | 408 templateBind(template).model = m; |
| 400 }).then(endOfMicrotask).then((_) { | 409 }).then(endOfMicrotask).then((_) { |
| 401 expect(div.nodes.length, 2); | 410 expect(div.nodes.length, 2); |
| 402 expect(div.lastChild.text, 'foo'); | 411 expect(div.lastChild.text, 'foo'); |
| 403 }); | 412 }); |
| 404 }); | 413 }); |
| 405 | 414 |
| 406 test('OneTime - simple text', () { | 415 test('OneTime - simple text', () { |
| 407 var div = createTestHtml('<template bind>[[ value ]]</template>'); | 416 var div = createTestHtml('<template bind>[[ value ]]</template>'); |
| 417 var template = div.firstChild; |
| 408 var m = toObservable({ 'value': 'foo' }); | 418 var m = toObservable({ 'value': 'foo' }); |
| 409 recursivelySetTemplateModel(div, m); | 419 templateBind(template).model = m; |
| 410 return new Future(() { | 420 return new Future(() { |
| 411 expect(div.nodes.length, 2); | 421 expect(div.nodes.length, 2); |
| 412 expect(div.lastChild.text, 'foo'); | 422 expect(div.lastChild.text, 'foo'); |
| 413 | 423 |
| 414 m['value'] = 'bar'; | 424 m['value'] = 'bar'; |
| 415 | 425 |
| 416 }).then(endOfMicrotask).then((_) { | 426 }).then(endOfMicrotask).then((_) { |
| 417 // unchanged. | 427 // unchanged. |
| 418 expect(div.lastChild.text, 'foo'); | 428 expect(div.lastChild.text, 'foo'); |
| 419 }); | 429 }); |
| 420 }); | 430 }); |
| 421 | 431 |
| 422 test('OneTime - compound text', () { | 432 test('OneTime - compound text', () { |
| 423 var div = createTestHtml( | 433 var div = createTestHtml( |
| 424 '<template bind>[[ foo ]] bar [[ baz ]]</template>'); | 434 '<template bind>[[ foo ]] bar [[ baz ]]</template>'); |
| 435 var template = div.firstChild; |
| 425 var m = toObservable({ 'foo': 'FOO', 'baz': 'BAZ' }); | 436 var m = toObservable({ 'foo': 'FOO', 'baz': 'BAZ' }); |
| 426 recursivelySetTemplateModel(div, m); | 437 templateBind(template).model = m; |
| 427 return new Future(() { | 438 return new Future(() { |
| 428 expect(div.nodes.length, 2); | 439 expect(div.nodes.length, 2); |
| 429 expect(div.lastChild.text, 'FOO bar BAZ'); | 440 expect(div.lastChild.text, 'FOO bar BAZ'); |
| 430 | 441 |
| 431 m['foo'] = 'FI'; | 442 m['foo'] = 'FI'; |
| 432 m['baz'] = 'BA'; | 443 m['baz'] = 'BA'; |
| 433 | 444 |
| 434 }).then(endOfMicrotask).then((_) { | 445 }).then(endOfMicrotask).then((_) { |
| 435 // unchanged. | 446 // unchanged. |
| 436 expect(div.nodes.length, 2); | 447 expect(div.nodes.length, 2); |
| 437 expect(div.lastChild.text, 'FOO bar BAZ'); | 448 expect(div.lastChild.text, 'FOO bar BAZ'); |
| 438 }); | 449 }); |
| 439 }); | 450 }); |
| 440 | 451 |
| 441 test('OneTime/Dynamic Mixed - compound text', () { | 452 test('OneTime/Dynamic Mixed - compound text', () { |
| 442 var div = createTestHtml( | 453 var div = createTestHtml( |
| 443 '<template bind>[[ foo ]] bar {{ baz }}</template>'); | 454 '<template bind>[[ foo ]] bar {{ baz }}</template>'); |
| 455 var template = div.firstChild; |
| 444 var m = toObservable({ 'foo': 'FOO', 'baz': 'BAZ' }); | 456 var m = toObservable({ 'foo': 'FOO', 'baz': 'BAZ' }); |
| 445 recursivelySetTemplateModel(div, m); | 457 templateBind(template).model = m; |
| 446 return new Future(() { | 458 return new Future(() { |
| 447 expect(div.nodes.length, 2); | 459 expect(div.nodes.length, 2); |
| 448 expect(div.lastChild.text, 'FOO bar BAZ'); | 460 expect(div.lastChild.text, 'FOO bar BAZ'); |
| 449 | 461 |
| 450 m['foo'] = 'FI'; | 462 m['foo'] = 'FI'; |
| 451 m['baz'] = 'BA'; | 463 m['baz'] = 'BA'; |
| 452 | 464 |
| 453 }).then(endOfMicrotask).then((_) { | 465 }).then(endOfMicrotask).then((_) { |
| 454 // unchanged [[ foo ]]. | 466 // unchanged [[ foo ]]. |
| 455 expect(div.nodes.length, 2); | 467 expect(div.nodes.length, 2); |
| 456 expect(div.lastChild.text, 'FOO bar BA'); | 468 expect(div.lastChild.text, 'FOO bar BA'); |
| 457 }); | 469 }); |
| 458 }); | 470 }); |
| 459 | 471 |
| 460 test('OneTime - simple attribute', () { | 472 test('OneTime - simple attribute', () { |
| 461 var div = createTestHtml( | 473 var div = createTestHtml( |
| 462 '<template bind><div foo="[[ value ]]"></div></template>'); | 474 '<template bind><div foo="[[ value ]]"></div></template>'); |
| 475 var template = div.firstChild; |
| 463 var m = toObservable({ 'value': 'foo' }); | 476 var m = toObservable({ 'value': 'foo' }); |
| 464 recursivelySetTemplateModel(div, m); | 477 templateBind(template).model = m; |
| 465 return new Future(() { | 478 return new Future(() { |
| 466 expect(div.nodes.length, 2); | 479 expect(div.nodes.length, 2); |
| 467 expect(div.lastChild.attributes['foo'], 'foo'); | 480 expect(div.lastChild.attributes['foo'], 'foo'); |
| 468 | 481 |
| 469 m['value'] = 'bar'; | 482 m['value'] = 'bar'; |
| 470 | 483 |
| 471 }).then(endOfMicrotask).then((_) { | 484 }).then(endOfMicrotask).then((_) { |
| 472 // unchanged. | 485 // unchanged. |
| 473 expect(div.nodes.length, 2); | 486 expect(div.nodes.length, 2); |
| 474 expect(div.lastChild.attributes['foo'], 'foo'); | 487 expect(div.lastChild.attributes['foo'], 'foo'); |
| 475 }); | 488 }); |
| 476 }); | 489 }); |
| 477 | 490 |
| 478 test('OneTime - compound attribute', () { | 491 test('OneTime - compound attribute', () { |
| 479 var div = createTestHtml( | 492 var div = createTestHtml( |
| 480 '<template bind>' | 493 '<template bind>' |
| 481 '<div foo="[[ value ]]:[[ otherValue ]]"></div>' | 494 '<div foo="[[ value ]]:[[ otherValue ]]"></div>' |
| 482 '</template>'); | 495 '</template>'); |
| 496 var template = div.firstChild; |
| 483 var m = toObservable({ 'value': 'foo', 'otherValue': 'bar' }); | 497 var m = toObservable({ 'value': 'foo', 'otherValue': 'bar' }); |
| 484 recursivelySetTemplateModel(div, m); | 498 templateBind(template).model = m; |
| 485 return new Future(() { | 499 return new Future(() { |
| 486 expect(div.nodes.length, 2); | 500 expect(div.nodes.length, 2); |
| 487 expect(div.lastChild.attributes['foo'], 'foo:bar'); | 501 expect(div.lastChild.attributes['foo'], 'foo:bar'); |
| 488 | 502 |
| 489 m['value'] = 'baz'; | 503 m['value'] = 'baz'; |
| 490 m['otherValue'] = 'bot'; | 504 m['otherValue'] = 'bot'; |
| 491 | 505 |
| 492 }).then(endOfMicrotask).then((_) { | 506 }).then(endOfMicrotask).then((_) { |
| 493 // unchanged. | 507 // unchanged. |
| 494 expect(div.lastChild.attributes['foo'], 'foo:bar'); | 508 expect(div.lastChild.attributes['foo'], 'foo:bar'); |
| 495 }); | 509 }); |
| 496 }); | 510 }); |
| 497 | 511 |
| 498 test('OneTime/Dynamic mixed - compound attribute', () { | 512 test('OneTime/Dynamic mixed - compound attribute', () { |
| 499 var div = createTestHtml( | 513 var div = createTestHtml( |
| 500 '<template bind>' | 514 '<template bind>' |
| 501 '<div foo="{{ value }}:[[ otherValue ]]"></div>' | 515 '<div foo="{{ value }}:[[ otherValue ]]"></div>' |
| 502 '</template>'); | 516 '</template>'); |
| 517 var template = div.firstChild; |
| 503 var m = toObservable({ 'value': 'foo', 'otherValue': 'bar' }); | 518 var m = toObservable({ 'value': 'foo', 'otherValue': 'bar' }); |
| 504 recursivelySetTemplateModel(div, m); | 519 templateBind(template).model = m; |
| 505 return new Future(() { | 520 return new Future(() { |
| 506 expect(div.nodes.length, 2); | 521 expect(div.nodes.length, 2); |
| 507 expect(div.lastChild.attributes['foo'], 'foo:bar'); | 522 expect(div.lastChild.attributes['foo'], 'foo:bar'); |
| 508 | 523 |
| 509 m['value'] = 'baz'; | 524 m['value'] = 'baz'; |
| 510 m['otherValue'] = 'bot'; | 525 m['otherValue'] = 'bot'; |
| 511 | 526 |
| 512 }).then(endOfMicrotask).then((_) { | 527 }).then(endOfMicrotask).then((_) { |
| 513 // unchanged [[ otherValue ]]. | 528 // unchanged [[ otherValue ]]. |
| 514 expect(div.lastChild.attributes['foo'], 'baz:bar'); | 529 expect(div.lastChild.attributes['foo'], 'baz:bar'); |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 expect(div.nodes[1].text, '1'); | 700 expect(div.nodes[1].text, '1'); |
| 686 | 701 |
| 687 templateBind(template).model = null; | 702 templateBind(template).model = null; |
| 688 }).then(endOfMicrotask).then((_) { | 703 }).then(endOfMicrotask).then((_) { |
| 689 expect(div.nodes.length, 1); | 704 expect(div.nodes.length, 1); |
| 690 }); | 705 }); |
| 691 }); | 706 }); |
| 692 | 707 |
| 693 test('TextTemplateWithNullStringBinding', () { | 708 test('TextTemplateWithNullStringBinding', () { |
| 694 var div = createTestHtml('<template bind={{}}>a{{b}}c</template>'); | 709 var div = createTestHtml('<template bind={{}}>a{{b}}c</template>'); |
| 710 var template = div.firstChild; |
| 695 var model = toObservable({'b': 'B'}); | 711 var model = toObservable({'b': 'B'}); |
| 696 recursivelySetTemplateModel(div, model); | 712 templateBind(template).model = model; |
| 697 | 713 |
| 698 return new Future(() { | 714 return new Future(() { |
| 699 expect(div.nodes.length, 2); | 715 expect(div.nodes.length, 2); |
| 700 expect(div.nodes.last.text, 'aBc'); | 716 expect(div.nodes.last.text, 'aBc'); |
| 701 | 717 |
| 702 model['b'] = 'b'; | 718 model['b'] = 'b'; |
| 703 }).then(endOfMicrotask).then((_) { | 719 }).then(endOfMicrotask).then((_) { |
| 704 expect(div.nodes.last.text, 'abc'); | 720 expect(div.nodes.last.text, 'abc'); |
| 705 | 721 |
| 706 model['b'] = null; | 722 model['b'] = null; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 | 756 |
| 741 model['data'] = null; | 757 model['data'] = null; |
| 742 }).then(endOfMicrotask).then((_) { | 758 }).then(endOfMicrotask).then((_) { |
| 743 expect(div.nodes.length, 1); | 759 expect(div.nodes.length, 1); |
| 744 }); | 760 }); |
| 745 }); | 761 }); |
| 746 | 762 |
| 747 test('TextTemplateWithBindingAndConditional', () { | 763 test('TextTemplateWithBindingAndConditional', () { |
| 748 var div = createTestHtml( | 764 var div = createTestHtml( |
| 749 '<template bind="{{}}" if="{{ d }}">a{{b}}c</template>'); | 765 '<template bind="{{}}" if="{{ d }}">a{{b}}c</template>'); |
| 766 var template = div.firstChild; |
| 750 var model = toObservable({'b': 'B', 'd': 1}); | 767 var model = toObservable({'b': 'B', 'd': 1}); |
| 751 recursivelySetTemplateModel(div, model); | 768 templateBind(template).model = model; |
| 752 | 769 |
| 753 return new Future(() { | 770 return new Future(() { |
| 754 expect(div.nodes.length, 2); | 771 expect(div.nodes.length, 2); |
| 755 expect(div.nodes.last.text, 'aBc'); | 772 expect(div.nodes.last.text, 'aBc'); |
| 756 | 773 |
| 757 model['b'] = 'b'; | 774 model['b'] = 'b'; |
| 758 }).then(endOfMicrotask).then((_) { | 775 }).then(endOfMicrotask).then((_) { |
| 759 expect(div.nodes.last.text, 'abc'); | 776 expect(div.nodes.last.text, 'abc'); |
| 760 | 777 |
| 761 // TODO(jmesserly): MDV set this to empty string and relies on JS conversi
on | 778 // TODO(jmesserly): MDV set this to empty string and relies on JS conversi
on |
| 762 // rules. Is that intended? | 779 // rules. Is that intended? |
| 763 // See https://github.com/Polymer/TemplateBinding/issues/59 | 780 // See https://github.com/Polymer/TemplateBinding/issues/59 |
| 764 model['d'] = null; | 781 model['d'] = null; |
| 765 }).then(endOfMicrotask).then((_) { | 782 }).then(endOfMicrotask).then((_) { |
| 766 expect(div.nodes.length, 1); | 783 expect(div.nodes.length, 1); |
| 767 | 784 |
| 768 model['d'] = 'here'; | 785 model['d'] = 'here'; |
| 769 model['b'] = 'd'; | 786 model['b'] = 'd'; |
| 770 | 787 |
| 771 }).then(endOfMicrotask).then((_) { | 788 }).then(endOfMicrotask).then((_) { |
| 772 expect(div.nodes.length, 2); | 789 expect(div.nodes.length, 2); |
| 773 expect(div.nodes.last.text, 'adc'); | 790 expect(div.nodes.last.text, 'adc'); |
| 774 }); | 791 }); |
| 775 }); | 792 }); |
| 776 | 793 |
| 777 test('TemplateWithTextBinding2', () { | 794 test('TemplateWithTextBinding2', () { |
| 778 var div = createTestHtml( | 795 var div = createTestHtml( |
| 779 '<template bind="{{ b }}">a{{value}}c</template>'); | 796 '<template bind="{{ b }}">a{{value}}c</template>'); |
| 780 expect(div.nodes.length, 1); | 797 expect(div.nodes.length, 1); |
| 798 var template = div.firstChild; |
| 781 var model = toObservable({'b': {'value': 'B'}}); | 799 var model = toObservable({'b': {'value': 'B'}}); |
| 782 recursivelySetTemplateModel(div, model); | 800 templateBind(template).model = model; |
| 783 | 801 |
| 784 return new Future(() { | 802 return new Future(() { |
| 785 expect(div.nodes.length, 2); | 803 expect(div.nodes.length, 2); |
| 786 expect(div.nodes.last.text, 'aBc'); | 804 expect(div.nodes.last.text, 'aBc'); |
| 787 | 805 |
| 788 model['b'] = toObservable({'value': 'b'}); | 806 model['b'] = toObservable({'value': 'b'}); |
| 789 }).then(endOfMicrotask).then((_) { | 807 }).then(endOfMicrotask).then((_) { |
| 790 expect(div.nodes.last.text, 'abc'); | 808 expect(div.nodes.last.text, 'abc'); |
| 791 }); | 809 }); |
| 792 }); | 810 }); |
| 793 | 811 |
| 794 test('TemplateWithAttributeBinding', () { | 812 test('TemplateWithAttributeBinding', () { |
| 795 var div = createTestHtml( | 813 var div = createTestHtml( |
| 796 '<template bind="{{}}">' | 814 '<template bind="{{}}">' |
| 797 '<div foo="a{{b}}c"></div>' | 815 '<div foo="a{{b}}c"></div>' |
| 798 '</template>'); | 816 '</template>'); |
| 817 var template = div.firstChild; |
| 799 var model = toObservable({'b': 'B'}); | 818 var model = toObservable({'b': 'B'}); |
| 800 recursivelySetTemplateModel(div, model); | 819 templateBind(template).model = model; |
| 801 | 820 |
| 802 return new Future(() { | 821 return new Future(() { |
| 803 expect(div.nodes.length, 2); | 822 expect(div.nodes.length, 2); |
| 804 expect(div.nodes.last.attributes['foo'], 'aBc'); | 823 expect(div.nodes.last.attributes['foo'], 'aBc'); |
| 805 | 824 |
| 806 model['b'] = 'b'; | 825 model['b'] = 'b'; |
| 807 }).then(endOfMicrotask).then((_) { | 826 }).then(endOfMicrotask).then((_) { |
| 808 expect(div.nodes.last.attributes['foo'], 'abc'); | 827 expect(div.nodes.last.attributes['foo'], 'abc'); |
| 809 | 828 |
| 810 model['b'] = 'X'; | 829 model['b'] = 'X'; |
| 811 }).then(endOfMicrotask).then((_) { | 830 }).then(endOfMicrotask).then((_) { |
| 812 expect(div.nodes.last.attributes['foo'], 'aXc'); | 831 expect(div.nodes.last.attributes['foo'], 'aXc'); |
| 813 }); | 832 }); |
| 814 }); | 833 }); |
| 815 | 834 |
| 816 test('TemplateWithConditionalBinding', () { | 835 test('TemplateWithConditionalBinding', () { |
| 817 var div = createTestHtml( | 836 var div = createTestHtml( |
| 818 '<template bind="{{}}">' | 837 '<template bind="{{}}">' |
| 819 '<div foo?="{{b}}"></div>' | 838 '<div foo?="{{b}}"></div>' |
| 820 '</template>'); | 839 '</template>'); |
| 840 var template = div.firstChild; |
| 821 var model = toObservable({'b': 'b'}); | 841 var model = toObservable({'b': 'b'}); |
| 822 recursivelySetTemplateModel(div, model); | 842 templateBind(template).model = model; |
| 823 | 843 |
| 824 return new Future(() { | 844 return new Future(() { |
| 825 expect(div.nodes.length, 2); | 845 expect(div.nodes.length, 2); |
| 826 expect(div.nodes.last.attributes['foo'], ''); | 846 expect(div.nodes.last.attributes['foo'], ''); |
| 827 expect(div.nodes.last.attributes, isNot(contains('foo?'))); | 847 expect(div.nodes.last.attributes, isNot(contains('foo?'))); |
| 828 | 848 |
| 829 model['b'] = null; | 849 model['b'] = null; |
| 830 }).then(endOfMicrotask).then((_) { | 850 }).then(endOfMicrotask).then((_) { |
| 831 expect(div.nodes.last.attributes, isNot(contains('foo'))); | 851 expect(div.nodes.last.attributes, isNot(contains('foo'))); |
| 832 }); | 852 }); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 test('Repeat - Reuse Instances', () { | 928 test('Repeat - Reuse Instances', () { |
| 909 var div = createTestHtml('<template repeat>{{ val }}</template>'); | 929 var div = createTestHtml('<template repeat>{{ val }}</template>'); |
| 910 | 930 |
| 911 var model = toObservable([ | 931 var model = toObservable([ |
| 912 {'val': 10}, | 932 {'val': 10}, |
| 913 {'val': 5}, | 933 {'val': 5}, |
| 914 {'val': 2}, | 934 {'val': 2}, |
| 915 {'val': 8}, | 935 {'val': 8}, |
| 916 {'val': 1} | 936 {'val': 1} |
| 917 ]); | 937 ]); |
| 918 recursivelySetTemplateModel(div, model); | |
| 919 var template = div.firstChild; | 938 var template = div.firstChild; |
| 939 templateBind(template).model = model; |
| 920 | 940 |
| 921 return new Future(() { | 941 return new Future(() { |
| 922 expect(div.nodes.length, 6); | 942 expect(div.nodes.length, 6); |
| 923 | 943 |
| 924 addExpandos(template.nextNode); | 944 addExpandos(template.nextNode); |
| 925 checkExpandos(template.nextNode); | 945 checkExpandos(template.nextNode); |
| 926 | 946 |
| 927 model.sort((a, b) => a['val'] - b['val']); | 947 model.sort((a, b) => a['val'] - b['val']); |
| 928 }).then(endOfMicrotask).then((_) { | 948 }).then(endOfMicrotask).then((_) { |
| 929 checkExpandos(template.nextNode); | 949 checkExpandos(template.nextNode); |
| 930 | 950 |
| 931 model = toObservable(model.reversed); | 951 model = toObservable(model.reversed); |
| 932 recursivelySetTemplateModel(div, model); | 952 templateBind(template).model = model; |
| 933 }).then(endOfMicrotask).then((_) { | 953 }).then(endOfMicrotask).then((_) { |
| 934 checkExpandos(template.nextNode); | 954 checkExpandos(template.nextNode); |
| 935 | 955 |
| 936 for (var item in model) { | 956 for (var item in model) { |
| 937 item['val'] += 1; | 957 item['val'] += 1; |
| 938 } | 958 } |
| 939 | 959 |
| 940 }).then(endOfMicrotask).then((_) { | 960 }).then(endOfMicrotask).then((_) { |
| 941 expect(div.nodes[1].text, "11"); | 961 expect(div.nodes[1].text, "11"); |
| 942 expect(div.nodes[2].text, "9"); | 962 expect(div.nodes[2].text, "9"); |
| 943 expect(div.nodes[3].text, "6"); | 963 expect(div.nodes[3].text, "6"); |
| 944 expect(div.nodes[4].text, "3"); | 964 expect(div.nodes[4].text, "3"); |
| 945 expect(div.nodes[5].text, "2"); | 965 expect(div.nodes[5].text, "2"); |
| 946 }); | 966 }); |
| 947 }); | 967 }); |
| 948 | 968 |
| 949 test('Bind - Reuse Instance', () { | 969 test('Bind - Reuse Instance', () { |
| 950 var div = createTestHtml( | 970 var div = createTestHtml( |
| 951 '<template bind="{{ foo }}">{{ bar }}</template>'); | 971 '<template bind="{{ foo }}">{{ bar }}</template>'); |
| 952 | 972 |
| 973 var template = div.firstChild; |
| 953 var model = toObservable({ 'foo': { 'bar': 5 }}); | 974 var model = toObservable({ 'foo': { 'bar': 5 }}); |
| 954 recursivelySetTemplateModel(div, model); | 975 templateBind(template).model = model; |
| 955 var template = div.firstChild; | |
| 956 | 976 |
| 957 return new Future(() { | 977 return new Future(() { |
| 958 expect(div.nodes.length, 2); | 978 expect(div.nodes.length, 2); |
| 959 | 979 |
| 960 addExpandos(template.nextNode); | 980 addExpandos(template.nextNode); |
| 961 checkExpandos(template.nextNode); | 981 checkExpandos(template.nextNode); |
| 962 | 982 |
| 963 model = toObservable({'foo': model['foo']}); | 983 model = toObservable({'foo': model['foo']}); |
| 964 recursivelySetTemplateModel(div, model); | 984 templateBind(template).model = model; |
| 965 }).then(endOfMicrotask).then((_) { | 985 }).then(endOfMicrotask).then((_) { |
| 966 checkExpandos(template.nextNode); | 986 checkExpandos(template.nextNode); |
| 967 }); | 987 }); |
| 968 }); | 988 }); |
| 969 | 989 |
| 970 test('Repeat-Empty', () { | 990 test('Repeat-Empty', () { |
| 971 var div = createTestHtml( | 991 var div = createTestHtml( |
| 972 '<template repeat>text</template>'); | 992 '<template repeat>text</template>'); |
| 973 | 993 |
| 994 var template = div.firstChild; |
| 974 var model = toObservable([0, 1, 2]); | 995 var model = toObservable([0, 1, 2]); |
| 975 recursivelySetTemplateModel(div, model); | 996 templateBind(template).model = model; |
| 976 | 997 |
| 977 return new Future(() { | 998 return new Future(() { |
| 978 expect(div.nodes.length, 4); | 999 expect(div.nodes.length, 4); |
| 979 | 1000 |
| 980 model.length = 1; | 1001 model.length = 1; |
| 981 }).then(endOfMicrotask).then((_) { | 1002 }).then(endOfMicrotask).then((_) { |
| 982 expect(div.nodes.length, 2); | 1003 expect(div.nodes.length, 2); |
| 983 | 1004 |
| 984 model.addAll(toObservable([3, 4])); | 1005 model.addAll(toObservable([3, 4])); |
| 985 }).then(endOfMicrotask).then((_) { | 1006 }).then(endOfMicrotask).then((_) { |
| 986 expect(div.nodes.length, 4); | 1007 expect(div.nodes.length, 4); |
| 987 | 1008 |
| 988 model.removeRange(1, 2); | 1009 model.removeRange(1, 2); |
| 989 }).then(endOfMicrotask).then((_) { | 1010 }).then(endOfMicrotask).then((_) { |
| 990 expect(div.nodes.length, 3); | 1011 expect(div.nodes.length, 3); |
| 991 }); | 1012 }); |
| 992 }); | 1013 }); |
| 993 | 1014 |
| 994 test('Removal from iteration needs to unbind', () { | 1015 test('Removal from iteration needs to unbind', () { |
| 995 var div = createTestHtml( | 1016 var div = createTestHtml( |
| 996 '<template repeat="{{}}"><a>{{v}}</a></template>'); | 1017 '<template repeat="{{}}"><a>{{v}}</a></template>'); |
| 1018 var template = div.firstChild; |
| 997 var model = toObservable([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3}, | 1019 var model = toObservable([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3}, |
| 998 {'v': 4}]); | 1020 {'v': 4}]); |
| 999 recursivelySetTemplateModel(div, model); | 1021 templateBind(template).model = model; |
| 1000 | 1022 |
| 1001 var nodes, vs; | 1023 var nodes, vs; |
| 1002 return new Future(() { | 1024 return new Future(() { |
| 1003 | 1025 |
| 1004 nodes = div.nodes.skip(1).toList(); | 1026 nodes = div.nodes.skip(1).toList(); |
| 1005 vs = model.toList(); | 1027 vs = model.toList(); |
| 1006 | 1028 |
| 1007 for (var i = 0; i < 5; i++) { | 1029 for (var i = 0; i < 5; i++) { |
| 1008 expect(nodes[i].text, '$i'); | 1030 expect(nodes[i].text, '$i'); |
| 1009 } | 1031 } |
| 1010 | 1032 |
| 1011 model.length = 3; | 1033 model.length = 3; |
| 1012 }).then(endOfMicrotask).then((_) { | 1034 }).then(endOfMicrotask).then((_) { |
| 1013 for (var i = 0; i < 5; i++) { | 1035 for (var i = 0; i < 5; i++) { |
| 1014 expect(nodes[i].text, '$i'); | 1036 expect(nodes[i].text, '$i'); |
| 1015 } | 1037 } |
| 1016 | 1038 |
| 1017 vs[3]['v'] = 33; | 1039 vs[3]['v'] = 33; |
| 1018 vs[4]['v'] = 44; | 1040 vs[4]['v'] = 44; |
| 1019 }).then(endOfMicrotask).then((_) { | 1041 }).then(endOfMicrotask).then((_) { |
| 1020 for (var i = 0; i < 5; i++) { | 1042 for (var i = 0; i < 5; i++) { |
| 1021 expect(nodes[i].text, '$i'); | 1043 expect(nodes[i].text, '$i'); |
| 1022 } | 1044 } |
| 1023 }); | 1045 }); |
| 1024 }); | 1046 }); |
| 1025 | 1047 |
| 1048 test('Template.clear', () { |
| 1049 var div = createTestHtml( |
| 1050 '<template repeat>{{}}</template>'); |
| 1051 var template = div.firstChild; |
| 1052 templateBind(template).model = [0, 1, 2]; |
| 1053 |
| 1054 return new Future(() { |
| 1055 expect(div.nodes.length, 4); |
| 1056 expect(div.nodes[1].text, '0'); |
| 1057 expect(div.nodes[2].text, '1'); |
| 1058 expect(div.nodes[3].text, '2'); |
| 1059 |
| 1060 // clear() synchronously removes instances and clears the model. |
| 1061 templateBind(div.firstChild).clear(); |
| 1062 expect(div.nodes.length, 1); |
| 1063 expect(templateBind(template).model, null); |
| 1064 |
| 1065 // test that template still works if new model assigned |
| 1066 templateBind(template).model = [3, 4]; |
| 1067 |
| 1068 }).then(endOfMicrotask).then((_) { |
| 1069 expect(div.nodes.length, 3); |
| 1070 expect(div.nodes[1].text, '3'); |
| 1071 expect(div.nodes[2].text, '4'); |
| 1072 }); |
| 1073 }); |
| 1074 |
| 1026 test('DOM Stability on Iteration', () { | 1075 test('DOM Stability on Iteration', () { |
| 1027 var div = createTestHtml( | 1076 var div = createTestHtml( |
| 1028 '<template repeat="{{}}">{{}}</template>'); | 1077 '<template repeat="{{}}">{{}}</template>'); |
| 1078 var template = div.firstChild; |
| 1029 var model = toObservable([1, 2, 3, 4, 5]); | 1079 var model = toObservable([1, 2, 3, 4, 5]); |
| 1030 recursivelySetTemplateModel(div, model); | 1080 templateBind(template).model = model; |
| 1031 | 1081 |
| 1032 var nodes; | 1082 var nodes; |
| 1033 return new Future(() { | 1083 return new Future(() { |
| 1034 // Note: the node at index 0 is the <template>. | 1084 // Note: the node at index 0 is the <template>. |
| 1035 nodes = div.nodes.toList(); | 1085 nodes = div.nodes.toList(); |
| 1036 expect(nodes.length, 6, reason: 'list has 5 items'); | 1086 expect(nodes.length, 6, reason: 'list has 5 items'); |
| 1037 | 1087 |
| 1038 model.removeAt(0); | 1088 model.removeAt(0); |
| 1039 model.removeLast(); | 1089 model.removeLast(); |
| 1040 | 1090 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1071 expect(identical(div.nodes[5], nodes[4]), true); | 1121 expect(identical(div.nodes[5], nodes[4]), true); |
| 1072 expect(identical(div.nodes[6], nodes[5]), true); | 1122 expect(identical(div.nodes[6], nodes[5]), true); |
| 1073 }); | 1123 }); |
| 1074 }); | 1124 }); |
| 1075 | 1125 |
| 1076 test('Repeat2', () { | 1126 test('Repeat2', () { |
| 1077 var div = createTestHtml( | 1127 var div = createTestHtml( |
| 1078 '<template repeat="{{}}">{{value}}</template>'); | 1128 '<template repeat="{{}}">{{value}}</template>'); |
| 1079 expect(div.nodes.length, 1); | 1129 expect(div.nodes.length, 1); |
| 1080 | 1130 |
| 1131 var template = div.firstChild; |
| 1081 var model = toObservable([ | 1132 var model = toObservable([ |
| 1082 {'value': 0}, | 1133 {'value': 0}, |
| 1083 {'value': 1}, | 1134 {'value': 1}, |
| 1084 {'value': 2} | 1135 {'value': 2} |
| 1085 ]); | 1136 ]); |
| 1086 recursivelySetTemplateModel(div, model); | 1137 templateBind(template).model = model; |
| 1087 | 1138 |
| 1088 return new Future(() { | 1139 return new Future(() { |
| 1089 expect(div.nodes.length, 4); | 1140 expect(div.nodes.length, 4); |
| 1090 expect(div.nodes[1].text, '0'); | 1141 expect(div.nodes[1].text, '0'); |
| 1091 expect(div.nodes[2].text, '1'); | 1142 expect(div.nodes[2].text, '1'); |
| 1092 expect(div.nodes[3].text, '2'); | 1143 expect(div.nodes[3].text, '2'); |
| 1093 | 1144 |
| 1094 model[1]['value'] = 'One'; | 1145 model[1]['value'] = 'One'; |
| 1095 }).then(endOfMicrotask).then((_) { | 1146 }).then(endOfMicrotask).then((_) { |
| 1096 expect(div.nodes.length, 4); | 1147 expect(div.nodes.length, 4); |
| 1097 expect(div.nodes[1].text, '0'); | 1148 expect(div.nodes[1].text, '0'); |
| 1098 expect(div.nodes[2].text, 'One'); | 1149 expect(div.nodes[2].text, 'One'); |
| 1099 expect(div.nodes[3].text, '2'); | 1150 expect(div.nodes[3].text, '2'); |
| 1100 | 1151 |
| 1101 model.replaceRange(0, 1, toObservable([{'value': 'Zero'}])); | 1152 model.replaceRange(0, 1, toObservable([{'value': 'Zero'}])); |
| 1102 }).then(endOfMicrotask).then((_) { | 1153 }).then(endOfMicrotask).then((_) { |
| 1103 expect(div.nodes.length, 4); | 1154 expect(div.nodes.length, 4); |
| 1104 expect(div.nodes[1].text, 'Zero'); | 1155 expect(div.nodes[1].text, 'Zero'); |
| 1105 expect(div.nodes[2].text, 'One'); | 1156 expect(div.nodes[2].text, 'One'); |
| 1106 expect(div.nodes[3].text, '2'); | 1157 expect(div.nodes[3].text, '2'); |
| 1107 }); | 1158 }); |
| 1108 }); | 1159 }); |
| 1109 | 1160 |
| 1110 test('TemplateWithInputValue', () { | 1161 test('TemplateWithInputValue', () { |
| 1111 var div = createTestHtml( | 1162 var div = createTestHtml( |
| 1112 '<template bind="{{}}">' | 1163 '<template bind="{{}}">' |
| 1113 '<input value="{{x}}">' | 1164 '<input value="{{x}}">' |
| 1114 '</template>'); | 1165 '</template>'); |
| 1166 var template = div.firstChild; |
| 1115 var model = toObservable({'x': 'hi'}); | 1167 var model = toObservable({'x': 'hi'}); |
| 1116 recursivelySetTemplateModel(div, model); | 1168 templateBind(template).model = model; |
| 1117 | 1169 |
| 1118 return new Future(() { | 1170 return new Future(() { |
| 1119 expect(div.nodes.length, 2); | 1171 expect(div.nodes.length, 2); |
| 1120 expect(div.nodes.last.value, 'hi'); | 1172 expect(div.nodes.last.value, 'hi'); |
| 1121 | 1173 |
| 1122 model['x'] = 'bye'; | 1174 model['x'] = 'bye'; |
| 1123 expect(div.nodes.last.value, 'hi'); | 1175 expect(div.nodes.last.value, 'hi'); |
| 1124 }).then(endOfMicrotask).then((_) { | 1176 }).then(endOfMicrotask).then((_) { |
| 1125 expect(div.nodes.last.value, 'bye'); | 1177 expect(div.nodes.last.value, 'bye'); |
| 1126 | 1178 |
| 1127 div.nodes.last.value = 'hello'; | 1179 div.nodes.last.value = 'hello'; |
| 1128 dispatchEvent('input', div.nodes.last); | 1180 dispatchEvent('input', div.nodes.last); |
| 1129 expect(model['x'], 'hello'); | 1181 expect(model['x'], 'hello'); |
| 1130 }).then(endOfMicrotask).then((_) { | 1182 }).then(endOfMicrotask).then((_) { |
| 1131 expect(div.nodes.last.value, 'hello'); | 1183 expect(div.nodes.last.value, 'hello'); |
| 1132 }); | 1184 }); |
| 1133 }); | 1185 }); |
| 1134 | 1186 |
| 1135 ////////////////////////////////////////////////////////////////////////////// | 1187 ////////////////////////////////////////////////////////////////////////////// |
| 1136 | 1188 |
| 1137 test('Decorated', () { | 1189 test('Decorated', () { |
| 1138 var div = createTestHtml( | 1190 var div = createTestHtml( |
| 1139 '<template bind="{{ XX }}" id="t1">' | 1191 '<template bind="{{ XX }}" id="t1">' |
| 1140 '<p>Crew member: {{name}}, Job title: {{title}}</p>' | 1192 '<p>Crew member: {{name}}, Job title: {{title}}</p>' |
| 1141 '</template>' | 1193 '</template>' |
| 1142 '<template bind="{{ XY }}" id="t2" ref="t1"></template>'); | 1194 '<template bind="{{ XY }}" id="t2" ref="t1"></template>'); |
| 1143 | 1195 |
| 1196 var t1 = document.getElementById('t1'); |
| 1197 var t2 = document.getElementById('t2'); |
| 1144 var model = toObservable({ | 1198 var model = toObservable({ |
| 1145 'XX': {'name': 'Leela', 'title': 'Captain'}, | 1199 'XX': {'name': 'Leela', 'title': 'Captain'}, |
| 1146 'XY': {'name': 'Fry', 'title': 'Delivery boy'}, | 1200 'XY': {'name': 'Fry', 'title': 'Delivery boy'}, |
| 1147 'XZ': {'name': 'Zoidberg', 'title': 'Doctor'} | 1201 'XZ': {'name': 'Zoidberg', 'title': 'Doctor'} |
| 1148 }); | 1202 }); |
| 1149 recursivelySetTemplateModel(div, model); | 1203 templateBind(t1).model = model; |
| 1204 templateBind(t2).model = model; |
| 1150 | 1205 |
| 1151 return new Future(() { | 1206 return new Future(() { |
| 1152 var t1 = document.getElementById('t1'); | |
| 1153 var instance = t1.nextElementSibling; | 1207 var instance = t1.nextElementSibling; |
| 1154 expect(instance.text, 'Crew member: Leela, Job title: Captain'); | 1208 expect(instance.text, 'Crew member: Leela, Job title: Captain'); |
| 1155 | 1209 |
| 1156 var t2 = document.getElementById('t2'); | |
| 1157 instance = t2.nextElementSibling; | 1210 instance = t2.nextElementSibling; |
| 1158 expect(instance.text, 'Crew member: Fry, Job title: Delivery boy'); | 1211 expect(instance.text, 'Crew member: Fry, Job title: Delivery boy'); |
| 1159 | 1212 |
| 1160 expect(div.children.length, 4); | 1213 expect(div.children.length, 4); |
| 1161 expect(div.nodes.length, 4); | 1214 expect(div.nodes.length, 4); |
| 1162 | 1215 |
| 1163 expect(div.nodes[1].tagName, 'P'); | 1216 expect(div.nodes[1].tagName, 'P'); |
| 1164 expect(div.nodes[3].tagName, 'P'); | 1217 expect(div.nodes[3].tagName, 'P'); |
| 1165 }); | 1218 }); |
| 1166 }); | 1219 }); |
| 1167 | 1220 |
| 1168 test('DefaultStyles', () { | 1221 test('DefaultStyles', () { |
| 1169 var t = new Element.tag('template'); | 1222 var t = new Element.tag('template'); |
| 1170 TemplateBindExtension.decorate(t); | 1223 TemplateBindExtension.decorate(t); |
| 1171 | 1224 |
| 1172 document.body.append(t); | 1225 document.body.append(t); |
| 1173 expect(t.getComputedStyle().display, 'none'); | 1226 expect(t.getComputedStyle().display, 'none'); |
| 1174 | 1227 |
| 1175 t.remove(); | 1228 t.remove(); |
| 1176 }); | 1229 }); |
| 1177 | 1230 |
| 1178 | 1231 |
| 1179 test('Bind', () { | 1232 test('Bind', () { |
| 1180 var div = createTestHtml('<template bind="{{}}">Hi {{ name }}</template>'); | 1233 var div = createTestHtml('<template bind="{{}}">Hi {{ name }}</template>'); |
| 1234 var template = div.firstChild; |
| 1181 var model = toObservable({'name': 'Leela'}); | 1235 var model = toObservable({'name': 'Leela'}); |
| 1182 recursivelySetTemplateModel(div, model); | 1236 templateBind(template).model = model; |
| 1183 | 1237 |
| 1184 return new Future(() => expect(div.nodes[1].text, 'Hi Leela')); | 1238 return new Future(() => expect(div.nodes[1].text, 'Hi Leela')); |
| 1185 }); | 1239 }); |
| 1186 | 1240 |
| 1187 test('BindPlaceHolderHasNewLine', () { | 1241 test('BindPlaceHolderHasNewLine', () { |
| 1188 var div = createTestHtml( | 1242 var div = createTestHtml( |
| 1189 '<template bind="{{}}">Hi {{\nname\n}}</template>'); | 1243 '<template bind="{{}}">Hi {{\nname\n}}</template>'); |
| 1244 var template = div.firstChild; |
| 1190 var model = toObservable({'name': 'Leela'}); | 1245 var model = toObservable({'name': 'Leela'}); |
| 1191 recursivelySetTemplateModel(div, model); | 1246 templateBind(template).model = model; |
| 1192 | 1247 |
| 1193 return new Future(() => expect(div.nodes[1].text, 'Hi Leela')); | 1248 return new Future(() => expect(div.nodes[1].text, 'Hi Leela')); |
| 1194 }); | 1249 }); |
| 1195 | 1250 |
| 1196 test('BindWithRef', () { | 1251 test('BindWithRef', () { |
| 1197 var id = 't${new math.Random().nextInt(100)}'; | 1252 var id = 't${new math.Random().nextInt(100)}'; |
| 1198 var div = createTestHtml( | 1253 var div = createTestHtml( |
| 1199 '<template id="$id">' | 1254 '<template id="$id">' |
| 1200 'Hi {{ name }}' | 1255 'Hi {{ name }}' |
| 1201 '</template>' | 1256 '</template>' |
| 1202 '<template ref="$id" bind="{{}}"></template>'); | 1257 '<template ref="$id" bind="{{}}"></template>'); |
| 1203 | 1258 |
| 1204 var t1 = div.nodes.first; | 1259 var t1 = div.nodes.first; |
| 1205 var t2 = div.nodes[1]; | 1260 var t2 = div.nodes[1]; |
| 1206 | 1261 |
| 1207 expect(templateBind(t2).ref, t1); | |
| 1208 | |
| 1209 var model = toObservable({'name': 'Fry'}); | 1262 var model = toObservable({'name': 'Fry'}); |
| 1210 recursivelySetTemplateModel(div, model); | 1263 templateBind(t1).model = model; |
| 1264 templateBind(t2).model = model; |
| 1211 | 1265 |
| 1212 return new Future(() => expect(t2.nextNode.text, 'Hi Fry')); | 1266 return new Future(() => expect(t2.nextNode.text, 'Hi Fry')); |
| 1213 }); | 1267 }); |
| 1214 | 1268 |
| 1269 test('Ref at multiple', () { |
| 1270 // Note: this test is asserting that template "ref"erences can be located |
| 1271 // at various points. In particular: |
| 1272 // -in the document (at large) (e.g. ref=doc) |
| 1273 // -within template content referenced from sub-content |
| 1274 // -both before and after the reference |
| 1275 // The following asserts ensure that all referenced templates content is |
| 1276 // found. |
| 1277 var div = createTestHtml( |
| 1278 '<template bind>' |
| 1279 '<template bind ref=doc></template>' |
| 1280 '<template id=elRoot>EL_ROOT</template>' |
| 1281 '<template bind>' |
| 1282 '<template bind ref=elRoot></template>' |
| 1283 '<template bind>' |
| 1284 '<template bind ref=subA></template>' |
| 1285 '<template id=subB>SUB_B</template>' |
| 1286 '<template bind>' |
| 1287 '<template bind ref=subB></template>' |
| 1288 '</template>' |
| 1289 '</template>' |
| 1290 '<template id=subA>SUB_A</template>' |
| 1291 '</template>' |
| 1292 '</template>' |
| 1293 '<template id=doc>DOC</template>'); |
| 1294 var t = div.firstChild; |
| 1295 var fragment = templateBind(t).createInstance({}); |
| 1296 expect(fragment.nodes.length, 14); |
| 1297 expect(fragment.nodes[1].text, 'DOC'); |
| 1298 expect(fragment.nodes[5].text, 'EL_ROOT'); |
| 1299 expect(fragment.nodes[8].text, 'SUB_A'); |
| 1300 expect(fragment.nodes[12].text, 'SUB_B'); |
| 1301 div.append(fragment); |
| 1302 }); |
| 1215 | 1303 |
| 1216 test('Update Ref', () { | 1304 test('Update Ref', () { |
| 1305 // Updating ref by observing the attribute is dependent on MutationObserver |
| 1217 var div = createTestHtml( | 1306 var div = createTestHtml( |
| 1218 '<template id=A>Hi, {{}}</template>' | 1307 '<template id=A>Hi, {{}}</template>' |
| 1219 '<template id=B>Hola, {{}}</template>' | 1308 '<template id=B>Hola, {{}}</template>' |
| 1220 '<template ref=A repeat></template>'); | 1309 '<template ref=A repeat></template>'); |
| 1221 | 1310 |
| 1311 var template = div.nodes[2]; |
| 1222 var model = new ObservableList.from(['Fry']); | 1312 var model = new ObservableList.from(['Fry']); |
| 1223 recursivelySetTemplateModel(div, model); | 1313 templateBind(template).model = model; |
| 1224 | 1314 |
| 1225 return new Future(() { | 1315 return new Future(() { |
| 1226 expect(div.nodes.length, 4); | 1316 expect(div.nodes.length, 4); |
| 1227 expect('Hi, Fry', div.nodes[3].text); | 1317 expect('Hi, Fry', div.nodes[3].text); |
| 1228 | 1318 |
| 1229 div.nodes[2].attributes['ref'] = 'B'; | 1319 div.nodes[2].attributes['ref'] = 'B'; |
| 1230 model.add('Leela'); | 1320 model.add('Leela'); |
| 1231 | 1321 |
| 1322 }).then(nextMicrotask).then((x) { |
| 1323 expect(div.nodes.length, 5); |
| 1324 |
| 1325 expect('Hola, Fry', div.nodes[3].text); |
| 1326 expect('Hola, Leela', div.nodes[4].text); |
| 1327 }); |
| 1328 }); |
| 1329 |
| 1330 test('Bound Ref', () { |
| 1331 var div = createTestHtml( |
| 1332 '<template id=A>Hi, {{}}</template>' |
| 1333 '<template id=B>Hola, {{}}</template>' |
| 1334 '<template ref="{{ ref }}" repeat="{{ people }}"></template>'); |
| 1335 |
| 1336 var template = div.nodes[2]; |
| 1337 var model = toObservable({'ref': 'A', 'people': ['Fry']}); |
| 1338 templateBind(template).model = model; |
| 1339 |
| 1340 return new Future(() { |
| 1341 expect(div.nodes.length, 4); |
| 1342 expect('Hi, Fry', div.nodes[3].text); |
| 1343 |
| 1344 model['ref'] = 'B'; |
| 1345 model['people'].add('Leela'); |
| 1346 |
| 1232 }).then(endOfMicrotask).then((x) { | 1347 }).then(endOfMicrotask).then((x) { |
| 1233 expect(div.nodes.length, 5); | 1348 expect(div.nodes.length, 5); |
| 1234 | 1349 |
| 1235 expect('Hi, Fry', div.nodes[3].text); | 1350 expect('Hola, Fry', div.nodes[3].text); |
| 1236 expect('Hola, Leela', div.nodes[4].text); | 1351 expect('Hola, Leela', div.nodes[4].text); |
| 1237 }); | 1352 }); |
| 1238 }); | 1353 }); |
| 1239 | 1354 |
| 1240 test('BindWithDynamicRef', () { | 1355 test('BindWithDynamicRef', () { |
| 1241 var id = 't${new math.Random().nextInt(100)}'; | 1356 var id = 't${new math.Random().nextInt(100)}'; |
| 1242 var div = createTestHtml( | 1357 var div = createTestHtml( |
| 1243 '<template id="$id">' | 1358 '<template id="$id">' |
| 1244 'Hi {{ name }}' | 1359 'Hi {{ name }}' |
| 1245 '</template>' | 1360 '</template>' |
| 1246 '<template ref="{{ id }}" bind="{{}}"></template>'); | 1361 '<template ref="{{ id }}" bind="{{}}"></template>'); |
| 1247 | 1362 |
| 1248 var t1 = div.firstChild; | 1363 var t1 = div.firstChild; |
| 1249 var t2 = div.nodes[1]; | 1364 var t2 = div.nodes[1]; |
| 1250 var model = toObservable({'name': 'Fry', 'id': id }); | 1365 var model = toObservable({'name': 'Fry', 'id': id }); |
| 1251 recursivelySetTemplateModel(div, model); | 1366 templateBind(t1).model = model; |
| 1367 templateBind(t2).model = model; |
| 1252 | 1368 |
| 1253 return new Future(() => expect(t2.nextNode.text, 'Hi Fry')); | 1369 return new Future(() => expect(t2.nextNode.text, 'Hi Fry')); |
| 1254 }); | 1370 }); |
| 1255 | 1371 |
| 1256 assertNodesAre(div, [arguments]) { | 1372 assertNodesAre(div, [arguments]) { |
| 1257 var expectedLength = arguments.length; | 1373 var expectedLength = arguments.length; |
| 1258 expect(div.nodes.length, expectedLength + 1); | 1374 expect(div.nodes.length, expectedLength + 1); |
| 1259 | 1375 |
| 1260 for (var i = 0; i < arguments.length; i++) { | 1376 for (var i = 0; i < arguments.length; i++) { |
| 1261 var targetNode = div.nodes[i + 1]; | 1377 var targetNode = div.nodes[i + 1]; |
| 1262 expect(targetNode.text, arguments[i]); | 1378 expect(targetNode.text, arguments[i]); |
| 1263 } | 1379 } |
| 1264 } | 1380 } |
| 1265 | 1381 |
| 1266 test('Repeat3', () { | 1382 test('Repeat3', () { |
| 1267 var div = createTestHtml( | 1383 var div = createTestHtml( |
| 1268 '<template repeat="{{ contacts }}">Hi {{ name }}</template>'); | 1384 '<template repeat="{{ contacts }}">Hi {{ name }}</template>'); |
| 1269 var t = div.nodes.first; | 1385 var t = div.nodes.first; |
| 1270 | 1386 |
| 1271 var m = toObservable({ | 1387 var m = toObservable({ |
| 1272 'contacts': [ | 1388 'contacts': [ |
| 1273 {'name': 'Raf'}, | 1389 {'name': 'Raf'}, |
| 1274 {'name': 'Arv'}, | 1390 {'name': 'Arv'}, |
| 1275 {'name': 'Neal'} | 1391 {'name': 'Neal'} |
| 1276 ] | 1392 ] |
| 1277 }); | 1393 }); |
| 1278 | 1394 |
| 1279 recursivelySetTemplateModel(div, m); | 1395 templateBind(t).model = m; |
| 1280 return new Future(() { | 1396 return new Future(() { |
| 1281 | 1397 |
| 1282 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); | 1398 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); |
| 1283 | 1399 |
| 1284 m['contacts'].add(toObservable({'name': 'Alex'})); | 1400 m['contacts'].add(toObservable({'name': 'Alex'})); |
| 1285 }).then(endOfMicrotask).then((_) { | 1401 }).then(endOfMicrotask).then((_) { |
| 1286 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']); | 1402 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']); |
| 1287 | 1403 |
| 1288 m['contacts'].replaceRange(0, 2, | 1404 m['contacts'].replaceRange(0, 2, |
| 1289 toObservable([{'name': 'Rafael'}, {'name': 'Erik'}])); | 1405 toObservable([{'name': 'Rafael'}, {'name': 'Erik'}])); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1313 }).then(endOfMicrotask).then((_) { | 1429 }).then(endOfMicrotask).then((_) { |
| 1314 assertNodesAre(div, []); | 1430 assertNodesAre(div, []); |
| 1315 }); | 1431 }); |
| 1316 }); | 1432 }); |
| 1317 | 1433 |
| 1318 test('RepeatModelSet', () { | 1434 test('RepeatModelSet', () { |
| 1319 var div = createTestHtml( | 1435 var div = createTestHtml( |
| 1320 '<template repeat="{{ contacts }}">' | 1436 '<template repeat="{{ contacts }}">' |
| 1321 'Hi {{ name }}' | 1437 'Hi {{ name }}' |
| 1322 '</template>'); | 1438 '</template>'); |
| 1439 var template = div.firstChild; |
| 1323 var m = toObservable({ | 1440 var m = toObservable({ |
| 1324 'contacts': [ | 1441 'contacts': [ |
| 1325 {'name': 'Raf'}, | 1442 {'name': 'Raf'}, |
| 1326 {'name': 'Arv'}, | 1443 {'name': 'Arv'}, |
| 1327 {'name': 'Neal'} | 1444 {'name': 'Neal'} |
| 1328 ] | 1445 ] |
| 1329 }); | 1446 }); |
| 1330 recursivelySetTemplateModel(div, m); | 1447 templateBind(template).model = m; |
| 1331 return new Future(() { | 1448 return new Future(() { |
| 1332 var t = div.nodes.first; | |
| 1333 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); | 1449 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); |
| 1334 }); | 1450 }); |
| 1335 }); | 1451 }); |
| 1336 | 1452 |
| 1337 test('RepeatEmptyPath', () { | 1453 test('RepeatEmptyPath', () { |
| 1338 var div = createTestHtml( | 1454 var div = createTestHtml( |
| 1339 '<template repeat="{{}}">Hi {{ name }}</template>'); | 1455 '<template repeat="{{}}">Hi {{ name }}</template>'); |
| 1340 var t = div.nodes.first; | 1456 var t = div.nodes.first; |
| 1341 | 1457 |
| 1342 var m = toObservable([ | 1458 var m = toObservable([ |
| 1343 {'name': 'Raf'}, | 1459 {'name': 'Raf'}, |
| 1344 {'name': 'Arv'}, | 1460 {'name': 'Arv'}, |
| 1345 {'name': 'Neal'} | 1461 {'name': 'Neal'} |
| 1346 ]); | 1462 ]); |
| 1347 recursivelySetTemplateModel(div, m); | 1463 templateBind(t).model = m; |
| 1348 return new Future(() { | 1464 return new Future(() { |
| 1349 | 1465 |
| 1350 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); | 1466 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); |
| 1351 | 1467 |
| 1352 m.add(toObservable({'name': 'Alex'})); | 1468 m.add(toObservable({'name': 'Alex'})); |
| 1353 }).then(endOfMicrotask).then((_) { | 1469 }).then(endOfMicrotask).then((_) { |
| 1354 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']); | 1470 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']); |
| 1355 | 1471 |
| 1356 m.replaceRange(0, 2, toObservable([{'name': 'Rafael'}, {'name': 'Erik'}]))
; | 1472 m.replaceRange(0, 2, toObservable([{'name': 'Rafael'}, {'name': 'Erik'}]))
; |
| 1357 }).then(endOfMicrotask).then((_) { | 1473 }).then(endOfMicrotask).then((_) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1376 assertNodesAre(div, ['Hi Alex']); | 1492 assertNodesAre(div, ['Hi Alex']); |
| 1377 }); | 1493 }); |
| 1378 }); | 1494 }); |
| 1379 | 1495 |
| 1380 test('RepeatNullModel', () { | 1496 test('RepeatNullModel', () { |
| 1381 var div = createTestHtml( | 1497 var div = createTestHtml( |
| 1382 '<template repeat="{{}}">Hi {{ name }}</template>'); | 1498 '<template repeat="{{}}">Hi {{ name }}</template>'); |
| 1383 var t = div.nodes.first; | 1499 var t = div.nodes.first; |
| 1384 | 1500 |
| 1385 var m = null; | 1501 var m = null; |
| 1386 recursivelySetTemplateModel(div, m); | 1502 templateBind(t).model = m; |
| 1387 | 1503 |
| 1388 expect(div.nodes.length, 1); | 1504 expect(div.nodes.length, 1); |
| 1389 | 1505 |
| 1390 t.attributes['iterate'] = ''; | 1506 t.attributes['iterate'] = ''; |
| 1391 m = toObservable({}); | 1507 m = toObservable({}); |
| 1392 recursivelySetTemplateModel(div, m); | 1508 templateBind(t).model = m; |
| 1393 return new Future(() => expect(div.nodes.length, 1)); | 1509 return new Future(() => expect(div.nodes.length, 1)); |
| 1394 }); | 1510 }); |
| 1395 | 1511 |
| 1396 test('RepeatReuse', () { | 1512 test('RepeatReuse', () { |
| 1397 var div = createTestHtml( | 1513 var div = createTestHtml( |
| 1398 '<template repeat="{{}}">Hi {{ name }}</template>'); | 1514 '<template repeat="{{}}">Hi {{ name }}</template>'); |
| 1399 var t = div.nodes.first; | 1515 var t = div.nodes.first; |
| 1400 | 1516 |
| 1401 var m = toObservable([ | 1517 var m = toObservable([ |
| 1402 {'name': 'Raf'}, | 1518 {'name': 'Raf'}, |
| 1403 {'name': 'Arv'}, | 1519 {'name': 'Arv'}, |
| 1404 {'name': 'Neal'} | 1520 {'name': 'Neal'} |
| 1405 ]); | 1521 ]); |
| 1406 recursivelySetTemplateModel(div, m); | 1522 templateBind(t).model = m; |
| 1407 | 1523 |
| 1408 var node1, node2, node3; | 1524 var node1, node2, node3; |
| 1409 return new Future(() { | 1525 return new Future(() { |
| 1410 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); | 1526 assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); |
| 1411 node1 = div.nodes[1]; | 1527 node1 = div.nodes[1]; |
| 1412 node2 = div.nodes[2]; | 1528 node2 = div.nodes[2]; |
| 1413 node3 = div.nodes[3]; | 1529 node3 = div.nodes[3]; |
| 1414 | 1530 |
| 1415 m.replaceRange(1, 2, toObservable([{'name': 'Erik'}])); | 1531 m.replaceRange(1, 2, toObservable([{'name': 'Erik'}])); |
| 1416 }).then(endOfMicrotask).then((_) { | 1532 }).then(endOfMicrotask).then((_) { |
| 1417 assertNodesAre(div, ['Hi Raf', 'Hi Erik', 'Hi Neal']); | 1533 assertNodesAre(div, ['Hi Raf', 'Hi Erik', 'Hi Neal']); |
| 1418 expect(div.nodes[1], node1, | 1534 expect(div.nodes[1], node1, |
| 1419 reason: 'model[0] did not change so the node should not have changed')
; | 1535 reason: 'model[0] did not change so the node should not have changed')
; |
| 1420 expect(div.nodes[2], isNot(equals(node2)), | 1536 expect(div.nodes[2], isNot(equals(node2)), |
| 1421 reason: 'Should not reuse when replacing'); | 1537 reason: 'Should not reuse when replacing'); |
| 1422 expect(div.nodes[3], node3, | 1538 expect(div.nodes[3], node3, |
| 1423 reason: 'model[2] did not change so the node should not have changed')
; | 1539 reason: 'model[2] did not change so the node should not have changed')
; |
| 1424 | 1540 |
| 1425 node2 = div.nodes[2]; | 1541 node2 = div.nodes[2]; |
| 1426 m.insert(0, toObservable({'name': 'Alex'})); | 1542 m.insert(0, toObservable({'name': 'Alex'})); |
| 1427 }).then(endOfMicrotask).then((_) { | 1543 }).then(endOfMicrotask).then((_) { |
| 1428 assertNodesAre(div, ['Hi Alex', 'Hi Raf', 'Hi Erik', 'Hi Neal']); | 1544 assertNodesAre(div, ['Hi Alex', 'Hi Raf', 'Hi Erik', 'Hi Neal']); |
| 1429 }); | 1545 }); |
| 1430 }); | 1546 }); |
| 1431 | 1547 |
| 1432 test('TwoLevelsDeepBug', () { | 1548 test('TwoLevelsDeepBug', () { |
| 1433 var div = createTestHtml( | 1549 var div = createTestHtml( |
| 1434 '<template bind="{{}}"><span><span>{{ foo }}</span></span></template>'); | 1550 '<template bind="{{}}"><span><span>{{ foo }}</span></span></template>'); |
| 1435 | 1551 var template = div.firstChild; |
| 1436 var model = toObservable({'foo': 'bar'}); | 1552 var model = toObservable({'foo': 'bar'}); |
| 1437 recursivelySetTemplateModel(div, model); | 1553 templateBind(template).model = model; |
| 1438 return new Future(() { | 1554 return new Future(() { |
| 1439 expect(div.nodes[1].nodes[0].nodes[0].text, 'bar'); | 1555 expect(div.nodes[1].nodes[0].nodes[0].text, 'bar'); |
| 1440 }); | 1556 }); |
| 1441 }); | 1557 }); |
| 1442 | 1558 |
| 1443 test('Checked', () { | 1559 test('Checked', () { |
| 1444 var div = createTestHtml( | 1560 var div = createTestHtml( |
| 1445 '<template bind>' | 1561 '<template bind>' |
| 1446 '<input type="checkbox" checked="{{a}}">' | 1562 '<input type="checkbox" checked="{{a}}">' |
| 1447 '</template>'); | 1563 '</template>'); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 expect(div.nodes[i++].tagName, 'TEMPLATE'); | 1595 expect(div.nodes[i++].tagName, 'TEMPLATE'); |
| 1480 expect(div.nodes[i++].text, '2'); | 1596 expect(div.nodes[i++].text, '2'); |
| 1481 | 1597 |
| 1482 m['a']['b'] = 11; | 1598 m['a']['b'] = 11; |
| 1483 }).then(endOfMicrotask).then((_) { | 1599 }).then(endOfMicrotask).then((_) { |
| 1484 expect(div.nodes[start].text, '11'); | 1600 expect(div.nodes[start].text, '11'); |
| 1485 | 1601 |
| 1486 m['a']['c'] = toObservable({'d': 22}); | 1602 m['a']['c'] = toObservable({'d': 22}); |
| 1487 }).then(endOfMicrotask).then((_) { | 1603 }).then(endOfMicrotask).then((_) { |
| 1488 expect(div.nodes[start + 2].text, '22'); | 1604 expect(div.nodes[start + 2].text, '22'); |
| 1605 |
| 1606 //clearAllTemplates(div); |
| 1489 }); | 1607 }); |
| 1490 } | 1608 } |
| 1491 | 1609 |
| 1492 test('Nested', () => nestedHelper( | 1610 test('Nested', () => nestedHelper( |
| 1493 '<template bind="{{a}}">' | 1611 '<template bind="{{a}}">' |
| 1494 '{{b}}' | 1612 '{{b}}' |
| 1495 '<template bind="{{c}}">' | 1613 '<template bind="{{c}}">' |
| 1496 '{{d}}' | 1614 '{{d}}' |
| 1497 '</template>' | 1615 '</template>' |
| 1498 '</template>', 1)); | 1616 '</template>', 1)); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 '<template ref="inner" repeat="{{c}}"></template>' | 1737 '<template ref="inner" repeat="{{c}}"></template>' |
| 1620 '</template>', 2)); | 1738 '</template>', 2)); |
| 1621 | 1739 |
| 1622 test('NestedRepeatSelfRef', () { | 1740 test('NestedRepeatSelfRef', () { |
| 1623 var div = createTestHtml( | 1741 var div = createTestHtml( |
| 1624 '<template id="t" repeat="{{}}">' | 1742 '<template id="t" repeat="{{}}">' |
| 1625 '{{name}}' | 1743 '{{name}}' |
| 1626 '<template ref="t" repeat="{{items}}"></template>' | 1744 '<template ref="t" repeat="{{items}}"></template>' |
| 1627 '</template>'); | 1745 '</template>'); |
| 1628 | 1746 |
| 1747 var template = div.firstChild; |
| 1748 |
| 1629 var m = toObservable([ | 1749 var m = toObservable([ |
| 1630 { | 1750 { |
| 1631 'name': 'Item 1', | 1751 'name': 'Item 1', |
| 1632 'items': [ | 1752 'items': [ |
| 1633 { | 1753 { |
| 1634 'name': 'Item 1.1', | 1754 'name': 'Item 1.1', |
| 1635 'items': [ | 1755 'items': [ |
| 1636 { | 1756 { |
| 1637 'name': 'Item 1.1.1', | 1757 'name': 'Item 1.1.1', |
| 1638 'items': [] | 1758 'items': [] |
| 1639 } | 1759 } |
| 1640 ] | 1760 ] |
| 1641 }, | 1761 }, |
| 1642 { | 1762 { |
| 1643 'name': 'Item 1.2' | 1763 'name': 'Item 1.2' |
| 1644 } | 1764 } |
| 1645 ] | 1765 ] |
| 1646 }, | 1766 }, |
| 1647 { | 1767 { |
| 1648 'name': 'Item 2', | 1768 'name': 'Item 2', |
| 1649 'items': [] | 1769 'items': [] |
| 1650 }, | 1770 }, |
| 1651 ]); | 1771 ]); |
| 1652 | 1772 |
| 1653 recursivelySetTemplateModel(div, m); | 1773 templateBind(template).model = m; |
| 1654 | 1774 |
| 1655 int i = 1; | 1775 int i = 1; |
| 1656 return new Future(() { | 1776 return new Future(() { |
| 1657 expect(div.nodes[i++].text, 'Item 1'); | 1777 expect(div.nodes[i++].text, 'Item 1'); |
| 1658 expect(div.nodes[i++].tagName, 'TEMPLATE'); | 1778 expect(div.nodes[i++].tagName, 'TEMPLATE'); |
| 1659 expect(div.nodes[i++].text, 'Item 1.1'); | 1779 expect(div.nodes[i++].text, 'Item 1.1'); |
| 1660 expect(div.nodes[i++].tagName, 'TEMPLATE'); | 1780 expect(div.nodes[i++].tagName, 'TEMPLATE'); |
| 1661 expect(div.nodes[i++].text, 'Item 1.1.1'); | 1781 expect(div.nodes[i++].text, 'Item 1.1.1'); |
| 1662 expect(div.nodes[i++].tagName, 'TEMPLATE'); | 1782 expect(div.nodes[i++].tagName, 'TEMPLATE'); |
| 1663 expect(div.nodes[i++].text, 'Item 1.2'); | 1783 expect(div.nodes[i++].text, 'Item 1.2'); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1679 test('Attribute Template Option/Optgroup', () { | 1799 test('Attribute Template Option/Optgroup', () { |
| 1680 var div = createTestHtml( | 1800 var div = createTestHtml( |
| 1681 '<template bind>' | 1801 '<template bind>' |
| 1682 '<select selectedIndex="{{ selected }}">' | 1802 '<select selectedIndex="{{ selected }}">' |
| 1683 '<optgroup template repeat="{{ groups }}" label="{{ name }}">' | 1803 '<optgroup template repeat="{{ groups }}" label="{{ name }}">' |
| 1684 '<option template repeat="{{ items }}">{{ val }}</option>' | 1804 '<option template repeat="{{ items }}">{{ val }}</option>' |
| 1685 '</optgroup>' | 1805 '</optgroup>' |
| 1686 '</select>' | 1806 '</select>' |
| 1687 '</template>'); | 1807 '</template>'); |
| 1688 | 1808 |
| 1809 var template = div.firstChild; |
| 1689 var m = toObservable({ | 1810 var m = toObservable({ |
| 1690 'selected': 1, | 1811 'selected': 1, |
| 1691 'groups': [{ | 1812 'groups': [{ |
| 1692 'name': 'one', 'items': [{ 'val': 0 }, { 'val': 1 }] | 1813 'name': 'one', 'items': [{ 'val': 0 }, { 'val': 1 }] |
| 1693 }], | 1814 }], |
| 1694 }); | 1815 }); |
| 1695 | 1816 |
| 1696 recursivelySetTemplateModel(div, m); | 1817 templateBind(template).model = m; |
| 1697 | 1818 |
| 1698 var completer = new Completer(); | 1819 var completer = new Completer(); |
| 1699 | 1820 |
| 1700 new MutationObserver((records, observer) { | 1821 new MutationObserver((records, observer) { |
| 1701 var select = div.nodes[0].nextNode; | 1822 var select = div.nodes[0].nextNode; |
| 1702 if (select == null || select.querySelector('option') == null) return; | 1823 if (select == null || select.querySelector('option') == null) return; |
| 1703 | 1824 |
| 1704 observer.disconnect(); | 1825 observer.disconnect(); |
| 1705 new Future(() { | 1826 new Future(() { |
| 1706 expect(select.nodes.length, 2); | 1827 expect(select.nodes.length, 2); |
| 1707 | 1828 |
| 1708 expect(select.selectedIndex, 1, reason: 'selected index should update ' | 1829 expect(select.selectedIndex, 1, reason: 'selected index should update ' |
| 1709 'after template expands.'); | 1830 'after template expands.'); |
| 1710 | 1831 |
| 1711 expect(select.nodes[0].tagName, 'TEMPLATE'); | 1832 expect(select.nodes[0].tagName, 'TEMPLATE'); |
| 1712 expect((templateBind(templateBind(select.nodes[0]).ref) | |
| 1713 .content.nodes[0] as Element).tagName, 'OPTGROUP'); | |
| 1714 | |
| 1715 var optgroup = select.nodes[1]; | 1833 var optgroup = select.nodes[1]; |
| 1716 expect(optgroup.nodes[0].tagName, 'TEMPLATE'); | 1834 expect(optgroup.nodes[0].tagName, 'TEMPLATE'); |
| 1717 expect(optgroup.nodes[1].tagName, 'OPTION'); | 1835 expect(optgroup.nodes[1].tagName, 'OPTION'); |
| 1718 expect(optgroup.nodes[1].text, '0'); | 1836 expect(optgroup.nodes[1].text, '0'); |
| 1719 expect(optgroup.nodes[2].tagName, 'OPTION'); | 1837 expect(optgroup.nodes[2].tagName, 'OPTION'); |
| 1720 expect(optgroup.nodes[2].text, '1'); | 1838 expect(optgroup.nodes[2].text, '1'); |
| 1721 | 1839 |
| 1722 completer.complete(); | 1840 completer.complete(); |
| 1723 }); | 1841 }); |
| 1724 })..observe(div, childList: true, subtree: true); | 1842 })..observe(div, childList: true, subtree: true); |
| 1725 | 1843 |
| 1726 Observable.dirtyCheck(); | 1844 Observable.dirtyCheck(); |
| 1727 | 1845 |
| 1728 return completer.future; | 1846 return completer.future; |
| 1729 }); | 1847 }); |
| 1730 | 1848 |
| 1731 test('NestedIterateTableMixedSemanticNative', () { | 1849 test('NestedIterateTableMixedSemanticNative', () { |
| 1732 if (!parserHasNativeTemplate) return null; | 1850 if (!parserHasNativeTemplate) return null; |
| 1733 | 1851 |
| 1734 var div = createTestHtml( | 1852 var div = createTestHtml( |
| 1735 '<table><tbody>' | 1853 '<table><tbody>' |
| 1736 '<template repeat="{{}}">' | 1854 '<template repeat="{{}}">' |
| 1737 '<tr>' | 1855 '<tr>' |
| 1738 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>' | 1856 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>' |
| 1739 '</tr>' | 1857 '</tr>' |
| 1740 '</template>' | 1858 '</template>' |
| 1741 '</tbody></table>'); | 1859 '</tbody></table>'); |
| 1860 var template = div.firstChild.firstChild.firstChild; |
| 1742 | 1861 |
| 1743 var m = toObservable([ | 1862 var m = toObservable([ |
| 1744 [{ 'val': 0 }, { 'val': 1 }], | 1863 [{ 'val': 0 }, { 'val': 1 }], |
| 1745 [{ 'val': 2 }, { 'val': 3 }] | 1864 [{ 'val': 2 }, { 'val': 3 }] |
| 1746 ]); | 1865 ]); |
| 1747 | 1866 |
| 1748 recursivelySetTemplateModel(div, m); | 1867 templateBind(template).model = m; |
| 1749 return new Future(() { | 1868 return new Future(() { |
| 1750 var tbody = div.nodes[0].nodes[0]; | 1869 var tbody = div.nodes[0].nodes[0]; |
| 1751 | 1870 |
| 1752 // 1 for the <tr template>, 2 * (1 tr) | 1871 // 1 for the <tr template>, 2 * (1 tr) |
| 1753 expect(tbody.nodes.length, 3); | 1872 expect(tbody.nodes.length, 3); |
| 1754 | 1873 |
| 1755 // 1 for the <td template>, 2 * (1 td) | 1874 // 1 for the <td template>, 2 * (1 td) |
| 1756 expect(tbody.nodes[1].nodes.length, 3); | 1875 expect(tbody.nodes[1].nodes.length, 3); |
| 1757 | 1876 |
| 1758 expect(tbody.nodes[1].nodes[1].text, '0'); | 1877 expect(tbody.nodes[1].nodes[1].text, '0'); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1769 }); | 1888 }); |
| 1770 }); | 1889 }); |
| 1771 | 1890 |
| 1772 test('NestedIterateTable', () { | 1891 test('NestedIterateTable', () { |
| 1773 var div = createTestHtml( | 1892 var div = createTestHtml( |
| 1774 '<table><tbody>' | 1893 '<table><tbody>' |
| 1775 '<tr template repeat="{{}}">' | 1894 '<tr template repeat="{{}}">' |
| 1776 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>' | 1895 '<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>' |
| 1777 '</tr>' | 1896 '</tr>' |
| 1778 '</tbody></table>'); | 1897 '</tbody></table>'); |
| 1898 var template = div.firstChild.firstChild.firstChild; |
| 1779 | 1899 |
| 1780 var m = toObservable([ | 1900 var m = toObservable([ |
| 1781 [{ 'val': 0 }, { 'val': 1 }], | 1901 [{ 'val': 0 }, { 'val': 1 }], |
| 1782 [{ 'val': 2 }, { 'val': 3 }] | 1902 [{ 'val': 2 }, { 'val': 3 }] |
| 1783 ]); | 1903 ]); |
| 1784 | 1904 |
| 1785 recursivelySetTemplateModel(div, m); | 1905 templateBind(template).model = m; |
| 1786 return new Future(() { | 1906 return new Future(() { |
| 1787 | 1907 |
| 1788 var i = 1; | 1908 var i = 1; |
| 1789 var tbody = div.nodes[0].nodes[0]; | 1909 var tbody = div.nodes[0].nodes[0]; |
| 1790 | 1910 |
| 1791 // 1 for the <tr template>, 2 * (1 tr) | 1911 // 1 for the <tr template>, 2 * (1 tr) |
| 1792 expect(tbody.nodes.length, 3); | 1912 expect(tbody.nodes.length, 3); |
| 1793 | 1913 |
| 1794 // 1 for the <td template>, 2 * (1 td) | 1914 // 1 for the <td template>, 2 * (1 td) |
| 1795 expect(tbody.nodes[1].nodes.length, 3); | 1915 expect(tbody.nodes[1].nodes.length, 3); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1806 expect(tbody.nodes[2].nodes[2].attributes['class'], '3'); | 1926 expect(tbody.nodes[2].nodes[2].attributes['class'], '3'); |
| 1807 }); | 1927 }); |
| 1808 }); | 1928 }); |
| 1809 | 1929 |
| 1810 test('NestedRepeatDeletionOfMultipleSubTemplates', () { | 1930 test('NestedRepeatDeletionOfMultipleSubTemplates', () { |
| 1811 var div = createTestHtml( | 1931 var div = createTestHtml( |
| 1812 '<ul>' | 1932 '<ul>' |
| 1813 '<template repeat="{{}}" id=t1>' | 1933 '<template repeat="{{}}" id=t1>' |
| 1814 '<li>{{name}}' | 1934 '<li>{{name}}' |
| 1815 '<ul>' | 1935 '<ul>' |
| 1816 '<template ref=t1 repaet="{{items}}"></template>' | 1936 '<template ref=t1 repeat="{{items}}"></template>' |
| 1817 '</ul>' | 1937 '</ul>' |
| 1818 '</li>' | 1938 '</li>' |
| 1819 '</template>' | 1939 '</template>' |
| 1820 '</ul>'); | 1940 '</ul>'); |
| 1821 | 1941 |
| 1822 var m = toObservable([ | 1942 var m = toObservable([ |
| 1823 { | 1943 { |
| 1824 'name': 'Item 1', | 1944 'name': 'Item 1', |
| 1825 'items': [ | 1945 'items': [ |
| 1826 { | 1946 { |
| 1827 'name': 'Item 1.1' | 1947 'name': 'Item 1.1' |
| 1828 } | 1948 } |
| 1829 ] | 1949 ] |
| 1830 } | 1950 } |
| 1831 ]); | 1951 ]); |
| 1952 var ul = div.firstChild; |
| 1953 var t = ul.firstChild; |
| 1832 | 1954 |
| 1833 recursivelySetTemplateModel(div, m); | 1955 templateBind(t).model = m; |
| 1834 return new Future(() => m.removeAt(0)); | 1956 return new Future(() { |
| 1957 expect(ul.nodes.length, 2); |
| 1958 var ul2 = ul.nodes[1].nodes[1]; |
| 1959 expect(ul2.nodes.length, 2); |
| 1960 var ul3 = ul2.nodes[1].nodes[1]; |
| 1961 expect(ul3.nodes.length, 1); |
| 1962 |
| 1963 m.removeAt(0); |
| 1964 }).then(endOfMicrotask).then((_) { |
| 1965 expect(ul.nodes.length, 1); |
| 1966 }); |
| 1835 }); | 1967 }); |
| 1836 | 1968 |
| 1837 test('DeepNested', () { | 1969 test('DeepNested', () { |
| 1838 var div = createTestHtml( | 1970 var div = createTestHtml( |
| 1839 '<template bind="{{a}}">' | 1971 '<template bind="{{a}}">' |
| 1840 '<p>' | 1972 '<p>' |
| 1841 '<template bind="{{b}}">' | 1973 '<template bind="{{b}}">' |
| 1842 '{{ c }}' | 1974 '{{ c }}' |
| 1843 '</template>' | 1975 '</template>' |
| 1844 '</p>' | 1976 '</p>' |
| 1845 '</template>'); | 1977 '</template>'); |
| 1846 | 1978 var template = div.firstChild; |
| 1847 var m = toObservable({ | 1979 var m = toObservable({ |
| 1848 'a': { | 1980 'a': { |
| 1849 'b': { | 1981 'b': { |
| 1850 'c': 42 | 1982 'c': 42 |
| 1851 } | 1983 } |
| 1852 } | 1984 } |
| 1853 }); | 1985 }); |
| 1854 recursivelySetTemplateModel(div, m); | 1986 templateBind(template).model = m; |
| 1855 return new Future(() { | 1987 return new Future(() { |
| 1856 expect(div.nodes[1].tagName, 'P'); | 1988 expect(div.nodes[1].tagName, 'P'); |
| 1857 expect(div.nodes[1].nodes.first.tagName, 'TEMPLATE'); | 1989 expect(div.nodes[1].nodes.first.tagName, 'TEMPLATE'); |
| 1858 expect(div.nodes[1].nodes[1].text, '42'); | 1990 expect(div.nodes[1].nodes[1].text, '42'); |
| 1859 }); | 1991 }); |
| 1860 }); | 1992 }); |
| 1861 | 1993 |
| 1862 test('TemplateContentRemoved', () { | 1994 test('TemplateContentRemoved', () { |
| 1863 var div = createTestHtml('<template bind="{{}}">{{ }}</template>'); | 1995 var div = createTestHtml('<template bind="{{}}">{{ }}</template>'); |
| 1996 var template = div.firstChild; |
| 1864 var model = 42; | 1997 var model = 42; |
| 1865 | 1998 |
| 1866 recursivelySetTemplateModel(div, model); | 1999 templateBind(template).model = model; |
| 1867 return new Future(() { | 2000 return new Future(() { |
| 1868 expect(div.nodes[1].text, '42'); | 2001 expect(div.nodes[1].text, '42'); |
| 1869 expect(div.nodes[0].text, ''); | 2002 expect(div.nodes[0].text, ''); |
| 1870 }); | 2003 }); |
| 1871 }); | 2004 }); |
| 1872 | 2005 |
| 1873 test('TemplateContentRemovedEmptyArray', () { | 2006 test('TemplateContentRemovedEmptyArray', () { |
| 1874 var div = createTestHtml('<template iterate>Remove me</template>'); | 2007 var div = createTestHtml('<template iterate>Remove me</template>'); |
| 1875 var model = toObservable([]); | 2008 var template = div.firstChild; |
| 1876 | 2009 templateBind(template).model = []; |
| 1877 recursivelySetTemplateModel(div, model); | |
| 1878 return new Future(() { | 2010 return new Future(() { |
| 1879 expect(div.nodes.length, 1); | 2011 expect(div.nodes.length, 1); |
| 1880 expect(div.nodes[0].text, ''); | 2012 expect(div.nodes[0].text, ''); |
| 1881 }); | 2013 }); |
| 1882 }); | 2014 }); |
| 1883 | 2015 |
| 1884 test('TemplateContentRemovedNested', () { | 2016 test('TemplateContentRemovedNested', () { |
| 1885 var div = createTestHtml( | 2017 var div = createTestHtml( |
| 1886 '<template bind="{{}}">' | 2018 '<template bind="{{}}">' |
| 1887 '{{ a }}' | 2019 '{{ a }}' |
| 1888 '<template bind="{{}}">' | 2020 '<template bind="{{}}">' |
| 1889 '{{ b }}' | 2021 '{{ b }}' |
| 1890 '</template>' | 2022 '</template>' |
| 1891 '</template>'); | 2023 '</template>'); |
| 1892 | 2024 var template = div.firstChild; |
| 1893 var model = toObservable({ | 2025 var model = toObservable({ |
| 1894 'a': 1, | 2026 'a': 1, |
| 1895 'b': 2 | 2027 'b': 2 |
| 1896 }); | 2028 }); |
| 1897 recursivelySetTemplateModel(div, model); | 2029 templateBind(template).model = model; |
| 1898 return new Future(() { | 2030 return new Future(() { |
| 1899 expect(div.nodes[0].text, ''); | 2031 expect(div.nodes[0].text, ''); |
| 1900 expect(div.nodes[1].text, '1'); | 2032 expect(div.nodes[1].text, '1'); |
| 1901 expect(div.nodes[2].text, ''); | 2033 expect(div.nodes[2].text, ''); |
| 1902 expect(div.nodes[3].text, '2'); | 2034 expect(div.nodes[3].text, '2'); |
| 1903 }); | 2035 }); |
| 1904 }); | 2036 }); |
| 1905 | 2037 |
| 1906 test('BindWithUndefinedModel', () { | 2038 test('BindWithUndefinedModel', () { |
| 1907 var div = createTestHtml( | 2039 var div = createTestHtml( |
| 1908 '<template bind="{{}}" if="{{}}">{{ a }}</template>'); | 2040 '<template bind="{{}}" if="{{}}">{{ a }}</template>'); |
| 2041 var template = div.firstChild; |
| 1909 | 2042 |
| 1910 var model = toObservable({'a': 42}); | 2043 var model = toObservable({'a': 42}); |
| 1911 recursivelySetTemplateModel(div, model); | 2044 templateBind(template).model = model; |
| 1912 return new Future(() { | 2045 return new Future(() { |
| 1913 expect(div.nodes[1].text, '42'); | 2046 expect(div.nodes[1].text, '42'); |
| 1914 | 2047 |
| 1915 model = null; | 2048 model = null; |
| 1916 recursivelySetTemplateModel(div, model); | 2049 templateBind(template).model = model; |
| 1917 }).then(endOfMicrotask).then((_) { | 2050 }).then(endOfMicrotask).then((_) { |
| 1918 expect(div.nodes.length, 1); | 2051 expect(div.nodes.length, 1); |
| 1919 | 2052 |
| 1920 model = toObservable({'a': 42}); | 2053 model = toObservable({'a': 42}); |
| 1921 recursivelySetTemplateModel(div, model); | 2054 templateBind(template).model = model; |
| 1922 }).then(endOfMicrotask).then((_) { | 2055 }).then(endOfMicrotask).then((_) { |
| 1923 expect(div.nodes[1].text, '42'); | 2056 expect(div.nodes[1].text, '42'); |
| 1924 }); | 2057 }); |
| 1925 }); | 2058 }); |
| 1926 | 2059 |
| 1927 test('BindNested', () { | 2060 test('BindNested', () { |
| 1928 var div = createTestHtml( | 2061 var div = createTestHtml( |
| 1929 '<template bind="{{}}">' | 2062 '<template bind="{{}}">' |
| 1930 'Name: {{ name }}' | 2063 'Name: {{ name }}' |
| 1931 '<template bind="{{wife}}" if="{{wife}}">' | 2064 '<template bind="{{wife}}" if="{{wife}}">' |
| 1932 'Wife: {{ name }}' | 2065 'Wife: {{ name }}' |
| 1933 '</template>' | 2066 '</template>' |
| 1934 '<template bind="{{child}}" if="{{child}}">' | 2067 '<template bind="{{child}}" if="{{child}}">' |
| 1935 'Child: {{ name }}' | 2068 'Child: {{ name }}' |
| 1936 '</template>' | 2069 '</template>' |
| 1937 '</template>'); | 2070 '</template>'); |
| 1938 | 2071 var template = div.firstChild; |
| 1939 var m = toObservable({ | 2072 var m = toObservable({ |
| 1940 'name': 'Hermes', | 2073 'name': 'Hermes', |
| 1941 'wife': { | 2074 'wife': { |
| 1942 'name': 'LaBarbara' | 2075 'name': 'LaBarbara' |
| 1943 } | 2076 } |
| 1944 }); | 2077 }); |
| 1945 recursivelySetTemplateModel(div, m); | 2078 templateBind(template).model = m; |
| 2079 |
| 1946 return new Future(() { | 2080 return new Future(() { |
| 1947 expect(div.nodes.length, 5); | 2081 expect(div.nodes.length, 5); |
| 1948 expect(div.nodes[1].text, 'Name: Hermes'); | 2082 expect(div.nodes[1].text, 'Name: Hermes'); |
| 1949 expect(div.nodes[3].text, 'Wife: LaBarbara'); | 2083 expect(div.nodes[3].text, 'Wife: LaBarbara'); |
| 1950 | 2084 |
| 1951 m['child'] = toObservable({'name': 'Dwight'}); | 2085 m['child'] = toObservable({'name': 'Dwight'}); |
| 2086 |
| 1952 }).then(endOfMicrotask).then((_) { | 2087 }).then(endOfMicrotask).then((_) { |
| 1953 expect(div.nodes.length, 6); | 2088 expect(div.nodes.length, 6); |
| 1954 expect(div.nodes[5].text, 'Child: Dwight'); | 2089 expect(div.nodes[5].text, 'Child: Dwight'); |
| 1955 | 2090 |
| 1956 m.remove('wife'); | 2091 m.remove('wife'); |
| 2092 |
| 1957 }).then(endOfMicrotask).then((_) { | 2093 }).then(endOfMicrotask).then((_) { |
| 1958 expect(div.nodes.length, 5); | 2094 expect(div.nodes.length, 5); |
| 1959 expect(div.nodes[4].text, 'Child: Dwight'); | 2095 expect(div.nodes[4].text, 'Child: Dwight'); |
| 1960 }); | 2096 }); |
| 1961 }); | 2097 }); |
| 1962 | 2098 |
| 1963 test('BindRecursive', () { | 2099 test('BindRecursive', () { |
| 1964 var div = createTestHtml( | 2100 var div = createTestHtml( |
| 1965 '<template bind="{{}}" if="{{}}" id="t">' | 2101 '<template bind="{{}}" if="{{}}" id="t">' |
| 1966 'Name: {{ name }}' | 2102 'Name: {{ name }}' |
| 1967 '<template bind="{{friend}}" if="{{friend}}" ref="t"></template>' | 2103 '<template bind="{{friend}}" if="{{friend}}" ref="t"></template>' |
| 1968 '</template>'); | 2104 '</template>'); |
| 1969 | 2105 var template = div.firstChild; |
| 1970 var m = toObservable({ | 2106 var m = toObservable({ |
| 1971 'name': 'Fry', | 2107 'name': 'Fry', |
| 1972 'friend': { | 2108 'friend': { |
| 1973 'name': 'Bender' | 2109 'name': 'Bender' |
| 1974 } | 2110 } |
| 1975 }); | 2111 }); |
| 1976 recursivelySetTemplateModel(div, m); | 2112 templateBind(template).model = m; |
| 1977 return new Future(() { | 2113 return new Future(() { |
| 1978 expect(div.nodes.length, 5); | 2114 expect(div.nodes.length, 5); |
| 1979 expect(div.nodes[1].text, 'Name: Fry'); | 2115 expect(div.nodes[1].text, 'Name: Fry'); |
| 1980 expect(div.nodes[3].text, 'Name: Bender'); | 2116 expect(div.nodes[3].text, 'Name: Bender'); |
| 1981 | 2117 |
| 1982 m['friend']['friend'] = toObservable({'name': 'Leela'}); | 2118 m['friend']['friend'] = toObservable({'name': 'Leela'}); |
| 1983 }).then(endOfMicrotask).then((_) { | 2119 }).then(endOfMicrotask).then((_) { |
| 1984 expect(div.nodes.length, 7); | 2120 expect(div.nodes.length, 7); |
| 1985 expect(div.nodes[5].text, 'Name: Leela'); | 2121 expect(div.nodes[5].text, 'Name: Leela'); |
| 1986 | 2122 |
| 1987 m['friend'] = toObservable({'name': 'Leela'}); | 2123 m['friend'] = toObservable({'name': 'Leela'}); |
| 1988 }).then(endOfMicrotask).then((_) { | 2124 }).then(endOfMicrotask).then((_) { |
| 1989 expect(div.nodes.length, 5); | 2125 expect(div.nodes.length, 5); |
| 1990 expect(div.nodes[3].text, 'Name: Leela'); | 2126 expect(div.nodes[3].text, 'Name: Leela'); |
| 1991 }); | 2127 }); |
| 1992 }); | 2128 }); |
| 1993 | 2129 |
| 1994 test('Template - Self is terminator', () { | 2130 test('Template - Self is terminator', () { |
| 1995 var div = createTestHtml( | 2131 var div = createTestHtml( |
| 1996 '<template repeat>{{ foo }}' | 2132 '<template repeat>{{ foo }}' |
| 1997 '<template bind></template>' | 2133 '<template bind></template>' |
| 1998 '</template>'); | 2134 '</template>'); |
| 2135 var template = div.firstChild; |
| 1999 | 2136 |
| 2000 var m = toObservable([{ 'foo': 'bar' }]); | 2137 var m = toObservable([{ 'foo': 'bar' }]); |
| 2001 recursivelySetTemplateModel(div, m); | 2138 templateBind(template).model = m; |
| 2002 return new Future(() { | 2139 return new Future(() { |
| 2003 | 2140 |
| 2004 m.add(toObservable({ 'foo': 'baz' })); | 2141 m.add(toObservable({ 'foo': 'baz' })); |
| 2005 recursivelySetTemplateModel(div, m); | 2142 templateBind(template).model = m; |
| 2006 }).then(endOfMicrotask).then((_) { | 2143 }).then(endOfMicrotask).then((_) { |
| 2007 | 2144 |
| 2008 expect(div.nodes.length, 5); | 2145 expect(div.nodes.length, 5); |
| 2009 expect(div.nodes[1].text, 'bar'); | 2146 expect(div.nodes[1].text, 'bar'); |
| 2010 expect(div.nodes[3].text, 'baz'); | 2147 expect(div.nodes[3].text, 'baz'); |
| 2011 }); | 2148 }); |
| 2012 }); | 2149 }); |
| 2013 | 2150 |
| 2014 test('Template - Same Contents, Different Array has no effect', () { | 2151 test('Template - Same Contents, Different Array has no effect', () { |
| 2015 if (!MutationObserver.supported) return null; | 2152 if (!MutationObserver.supported) return null; |
| 2016 | 2153 |
| 2017 var div = createTestHtml('<template repeat>{{ foo }}</template>'); | 2154 var div = createTestHtml('<template repeat>{{ foo }}</template>'); |
| 2155 var template = div.firstChild; |
| 2018 | 2156 |
| 2019 var m = toObservable([{ 'foo': 'bar' }, { 'foo': 'bat'}]); | 2157 var m = toObservable([{ 'foo': 'bar' }, { 'foo': 'bat'}]); |
| 2020 recursivelySetTemplateModel(div, m); | 2158 templateBind(template).model = m; |
| 2021 var observer = new MutationObserver((x, y) {}); | 2159 var observer = new MutationObserver((x, y) {}); |
| 2022 return new Future(() { | 2160 return new Future(() { |
| 2023 observer.observe(div, childList: true); | 2161 observer.observe(div, childList: true); |
| 2024 | 2162 |
| 2025 var template = div.firstChild; | 2163 var template = div.firstChild; |
| 2026 templateBind(template).model = new ObservableList.from(m); | 2164 templateBind(template).model = new ObservableList.from(m); |
| 2027 }).then(endOfMicrotask).then((_) { | 2165 }).then(endOfMicrotask).then((_) { |
| 2028 var records = observer.takeRecords(); | 2166 var records = observer.takeRecords(); |
| 2029 expect(records.length, 0); | 2167 expect(records.length, 0); |
| 2030 }); | 2168 }); |
| 2031 }); | 2169 }); |
| 2032 | 2170 |
| 2033 test('RecursiveRef', () { | 2171 test('RecursiveRef', () { |
| 2034 var div = createTestHtml( | 2172 var div = createTestHtml( |
| 2035 '<template bind>' | 2173 '<template bind>' |
| 2036 '<template id=src>{{ foo }}</template>' | 2174 '<template id=src>{{ foo }}</template>' |
| 2037 '<template bind ref=src></template>' | 2175 '<template bind ref=src></template>' |
| 2038 '</template>'); | 2176 '</template>'); |
| 2039 | 2177 |
| 2040 var m = toObservable({'foo': 'bar'}); | 2178 var m = toObservable({'foo': 'bar'}); |
| 2041 recursivelySetTemplateModel(div, m); | 2179 templateBind(div.firstChild).model = m; |
| 2042 return new Future(() { | 2180 return new Future(() { |
| 2043 expect(div.nodes.length, 4); | 2181 expect(div.nodes.length, 4); |
| 2044 expect(div.nodes[3].text, 'bar'); | 2182 expect(div.nodes[3].text, 'bar'); |
| 2045 }); | 2183 }); |
| 2046 }); | 2184 }); |
| 2047 | 2185 |
| 2186 test('baseURI', () { |
| 2187 // TODO(jmesserly): Dart's setInnerHtml breaks this test -- the template |
| 2188 // URL is created as blank despite the NullTreeSanitizer. |
| 2189 // Use JS interop as a workaround. |
| 2190 //var div = createTestHtml('<template bind>' |
| 2191 // '<div style="background: url(foo.jpg)"></div></template>'); |
| 2192 var div = new DivElement(); |
| 2193 new JsObject.fromBrowserObject(div)['innerHTML'] = '<template bind>' |
| 2194 '<div style="background: url(foo.jpg)"></div></template>'; |
| 2195 testDiv.append(div); |
| 2196 TemplateBindExtension.decorate(div.firstChild); |
| 2197 |
| 2198 var local = document.createElement('div'); |
| 2199 local.attributes['style'] = 'background: url(foo.jpg)'; |
| 2200 div.append(local); |
| 2201 var template = div.firstChild; |
| 2202 templateBind(template).model = {}; |
| 2203 return new Future(() { |
| 2204 expect(div.nodes[1].style.backgroundImage, local.style.backgroundImage); |
| 2205 }); |
| 2206 }); |
| 2207 |
| 2048 test('ChangeRefId', () { | 2208 test('ChangeRefId', () { |
| 2049 var div = createTestHtml( | 2209 var div = createTestHtml( |
| 2050 '<template id="a">a:{{ }}</template>' | 2210 '<template id="a">a:{{ }}</template>' |
| 2051 '<template id="b">b:{{ }}</template>' | 2211 '<template id="b">b:{{ }}</template>' |
| 2052 '<template repeat="{{}}">' | 2212 '<template repeat="{{}}">' |
| 2053 '<template ref="a" bind="{{}}"></template>' | 2213 '<template ref="a" bind="{{}}"></template>' |
| 2054 '</template>'); | 2214 '</template>'); |
| 2215 var template = div.nodes[2]; |
| 2055 var model = toObservable([]); | 2216 var model = toObservable([]); |
| 2056 recursivelySetTemplateModel(div, model); | 2217 templateBind(template).model = model; |
| 2057 return new Future(() { | 2218 return new Future(() { |
| 2058 expect(div.nodes.length, 3); | 2219 expect(div.nodes.length, 3); |
| 2059 | 2220 |
| 2060 document.getElementById('a').id = 'old-a'; | 2221 document.getElementById('a').id = 'old-a'; |
| 2061 document.getElementById('b').id = 'a'; | 2222 document.getElementById('b').id = 'a'; |
| 2062 | 2223 |
| 2063 model..add(1)..add(2); | 2224 model..add(1)..add(2); |
| 2064 }).then(endOfMicrotask).then((_) { | 2225 }).then(endOfMicrotask).then((_) { |
| 2065 | 2226 |
| 2066 expect(div.nodes.length, 7); | 2227 expect(div.nodes.length, 7); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2111 expect(templateBind(templateB).content.ownerDocument, | 2272 expect(templateBind(templateB).content.ownerDocument, |
| 2112 templateBind(templateA).content.ownerDocument); | 2273 templateBind(templateA).content.ownerDocument); |
| 2113 }); | 2274 }); |
| 2114 | 2275 |
| 2115 test('BindShadowDOM', () { | 2276 test('BindShadowDOM', () { |
| 2116 if (!ShadowRoot.supported) return null; | 2277 if (!ShadowRoot.supported) return null; |
| 2117 | 2278 |
| 2118 var root = createShadowTestHtml( | 2279 var root = createShadowTestHtml( |
| 2119 '<template bind="{{}}">Hi {{ name }}</template>'); | 2280 '<template bind="{{}}">Hi {{ name }}</template>'); |
| 2120 var model = toObservable({'name': 'Leela'}); | 2281 var model = toObservable({'name': 'Leela'}); |
| 2121 recursivelySetTemplateModel(root, model); | 2282 templateBind(root.firstChild).model = model; |
| 2122 return new Future(() => expect(root.nodes[1].text, 'Hi Leela')); | 2283 return new Future(() => expect(root.nodes[1].text, 'Hi Leela')); |
| 2123 }); | 2284 }); |
| 2124 | 2285 |
| 2125 // Dart note: this test seems gone from JS. Keeping for posterity sake. | 2286 // Dart note: this test seems gone from JS. Keeping for posterity sake. |
| 2126 test('BindShadowDOM createInstance', () { | 2287 test('BindShadowDOM createInstance', () { |
| 2127 if (!ShadowRoot.supported) return null; | 2288 if (!ShadowRoot.supported) return null; |
| 2128 | 2289 |
| 2129 var model = toObservable({'name': 'Leela'}); | 2290 var model = toObservable({'name': 'Leela'}); |
| 2130 var template = new Element.html('<template>Hi {{ name }}</template>'); | 2291 var template = new Element.html('<template>Hi {{ name }}</template>'); |
| 2131 var root = createShadowTestHtml(''); | 2292 var root = createShadowTestHtml(''); |
| 2132 root.nodes.add(templateBind(template).createInstance(model)); | 2293 root.nodes.add(templateBind(template).createInstance(model)); |
| 2133 | 2294 |
| 2134 return new Future(() { | 2295 return new Future(() { |
| 2135 expect(root.text, 'Hi Leela'); | 2296 expect(root.text, 'Hi Leela'); |
| 2136 | 2297 |
| 2137 model['name'] = 'Fry'; | 2298 model['name'] = 'Fry'; |
| 2138 }).then(endOfMicrotask).then((_) { | 2299 }).then(endOfMicrotask).then((_) { |
| 2139 expect(root.text, 'Hi Fry'); | 2300 expect(root.text, 'Hi Fry'); |
| 2140 }); | 2301 }); |
| 2141 }); | 2302 }); |
| 2142 | 2303 |
| 2143 test('BindShadowDOM Template Ref', () { | 2304 test('BindShadowDOM Template Ref', () { |
| 2144 if (!ShadowRoot.supported) return null; | 2305 if (!ShadowRoot.supported) return null; |
| 2145 var root = createShadowTestHtml( | 2306 var root = createShadowTestHtml( |
| 2146 '<template id=foo>Hi</template><template bind ref=foo></template>'); | 2307 '<template id=foo>Hi</template><template bind ref=foo></template>'); |
| 2147 recursivelySetTemplateModel(root, toObservable({})); | 2308 var template = root.nodes[1]; |
| 2148 return new Future(() => expect(root.nodes.length, 3)); | 2309 templateBind(template).model = toObservable({}); |
| 2310 return new Future(() { |
| 2311 expect(root.nodes.length, 3); |
| 2312 clearAllTemplates(root); |
| 2313 }); |
| 2149 }); | 2314 }); |
| 2150 | 2315 |
| 2151 // https://github.com/Polymer/TemplateBinding/issues/8 | 2316 // https://github.com/Polymer/TemplateBinding/issues/8 |
| 2152 test('UnbindingInNestedBind', () { | 2317 test('UnbindingInNestedBind', () { |
| 2153 var div = createTestHtml( | 2318 var div = createTestHtml( |
| 2154 '<template bind="{{outer}}" if="{{outer}}" syntax="testHelper">' | 2319 '<template bind="{{outer}}" if="{{outer}}" syntax="testHelper">' |
| 2155 '<template bind="{{inner}}" if="{{inner}}">' | 2320 '<template bind="{{inner}}" if="{{inner}}">' |
| 2156 '{{ age }}' | 2321 '{{ age }}' |
| 2157 '</template>' | 2322 '</template>' |
| 2158 '</template>'); | 2323 '</template>'); |
| 2159 | 2324 var template = div.firstChild; |
| 2160 var syntax = new UnbindingInNestedBindSyntax(); | 2325 var syntax = new UnbindingInNestedBindSyntax(); |
| 2161 var model = toObservable({'outer': {'inner': {'age': 42}}}); | 2326 var model = toObservable({'outer': {'inner': {'age': 42}}}); |
| 2162 | 2327 |
| 2163 recursivelySetTemplateModel(div, model, syntax); | 2328 templateBind(template)..model = model..bindingDelegate = syntax; |
| 2164 | 2329 |
| 2165 return new Future(() { | 2330 return new Future(() { |
| 2166 expect(syntax.count, 1); | 2331 expect(syntax.count, 1); |
| 2167 | 2332 |
| 2168 var inner = model['outer']['inner']; | 2333 var inner = model['outer']['inner']; |
| 2169 model['outer'] = null; | 2334 model['outer'] = null; |
| 2170 | 2335 |
| 2171 }).then(endOfMicrotask).then((_) { | 2336 }).then(endOfMicrotask).then((_) { |
| 2172 expect(syntax.count, 1); | 2337 expect(syntax.count, 1); |
| 2173 | 2338 |
| 2174 model['outer'] = toObservable({'inner': {'age': 2}}); | 2339 model['outer'] = toObservable({'inner': {'age': 2}}); |
| 2175 syntax.expectedAge = 2; | 2340 syntax.expectedAge = 2; |
| 2176 | 2341 |
| 2177 }).then(endOfMicrotask).then((_) { | 2342 }).then(endOfMicrotask).then((_) { |
| 2178 expect(syntax.count, 2); | 2343 expect(syntax.count, 2); |
| 2179 }); | 2344 }); |
| 2180 }); | 2345 }); |
| 2181 | 2346 |
| 2182 // https://github.com/toolkitchen/mdv/issues/8 | 2347 // https://github.com/toolkitchen/mdv/issues/8 |
| 2183 test('DontCreateInstancesForAbandonedIterators', () { | 2348 test('DontCreateInstancesForAbandonedIterators', () { |
| 2184 var div = createTestHtml( | 2349 var div = createTestHtml( |
| 2185 '<template bind="{{}} {{}}">' | 2350 '<template bind="{{}} {{}}">' |
| 2186 '<template bind="{{}}">Foo</template>' | 2351 '<template bind="{{}}">Foo</template>' |
| 2187 '</template>'); | 2352 '</template>'); |
| 2188 recursivelySetTemplateModel(div, null); | 2353 var template = div.firstChild; |
| 2354 templateBind(template).model = null; |
| 2189 return nextMicrotask; | 2355 return nextMicrotask; |
| 2190 }); | 2356 }); |
| 2191 | 2357 |
| 2192 test('CreateInstance', () { | 2358 test('CreateInstance', () { |
| 2193 var div = createTestHtml( | 2359 var div = createTestHtml( |
| 2194 '<template bind="{{a}}">' | 2360 '<template bind="{{a}}">' |
| 2195 '<template bind="{{b}}">' | 2361 '<template bind="{{b}}">' |
| 2196 '{{ foo }}:{{ replaceme }}' | 2362 '{{ foo }}:{{ replaceme }}' |
| 2197 '</template>' | 2363 '</template>' |
| 2198 '</template>'); | 2364 '</template>'); |
| 2199 var outer = templateBind(div.nodes.first); | 2365 var outer = templateBind(div.nodes.first); |
| 2200 var model = toObservable({'b': {'foo': 'bar'}}); | 2366 var model = toObservable({'b': {'foo': 'bar'}}); |
| 2201 | 2367 |
| 2202 var host = new DivElement(); | |
| 2203 var instance = outer.createInstance(model, new TestBindingSyntax()); | 2368 var instance = outer.createInstance(model, new TestBindingSyntax()); |
| 2204 expect(outer.content.nodes.first, | 2369 expect(instance.firstChild.nextNode.text, 'bar:replaced'); |
| 2205 templateBind(instance.nodes.first).ref); | |
| 2206 | 2370 |
| 2207 host.append(instance); | 2371 clearAllTemplates(instance); |
| 2208 return new Future(() { | |
| 2209 expect(host.firstChild.nextNode.text, 'bar:replaced'); | |
| 2210 }); | |
| 2211 }); | 2372 }); |
| 2212 | 2373 |
| 2213 test('CreateInstance - sync error', () { | 2374 test('CreateInstance - sync error', () { |
| 2214 var div = createTestHtml('<template>{{foo}}</template>'); | 2375 var div = createTestHtml('<template>{{foo}}</template>'); |
| 2215 var outer = templateBind(div.nodes.first); | 2376 var outer = templateBind(div.nodes.first); |
| 2216 var model = 1; // model is missing 'foo' should throw. | 2377 var model = 1; // model is missing 'foo' should throw. |
| 2217 expect(() => outer.createInstance(model, new TestBindingSyntax()), | 2378 expect(() => outer.createInstance(model, new TestBindingSyntax()), |
| 2218 throwsA(isNoSuchMethodError)); | 2379 throwsA(isNoSuchMethodError)); |
| 2219 }); | 2380 }); |
| 2220 | 2381 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2317 return new Future(() { | 2478 return new Future(() { |
| 2318 expect(template.nextNode.nextNode.nextNode.text, '2'); | 2479 expect(template.nextNode.nextNode.nextNode.text, '2'); |
| 2319 model['show'] = false; | 2480 model['show'] = false; |
| 2320 }).then(endOfMicrotask).then((_) { | 2481 }).then(endOfMicrotask).then((_) { |
| 2321 model['show'] = true; | 2482 model['show'] = true; |
| 2322 }).then(endOfMicrotask).then((_) { | 2483 }).then(endOfMicrotask).then((_) { |
| 2323 expect(template.nextNode.nextNode.nextNode.text, '2'); | 2484 expect(template.nextNode.nextNode.nextNode.text, '2'); |
| 2324 }); | 2485 }); |
| 2325 }); | 2486 }); |
| 2326 | 2487 |
| 2488 test('Accessor value retrieval count', () { |
| 2489 var div = createTestHtml( |
| 2490 '<template bind>{{ prop }}</template>'); |
| 2491 |
| 2492 var model = new TestAccessorModel(); |
| 2493 |
| 2494 templateBind(div.firstChild).model = model; |
| 2495 |
| 2496 return new Future(() { |
| 2497 expect(model.count, 1); |
| 2498 |
| 2499 model.value++; |
| 2500 // Dart note: we don't handle getters in @observable, so we need to |
| 2501 // notify regardless. |
| 2502 model.notifyPropertyChange(#prop, 1, model.value); |
| 2503 |
| 2504 }).then(endOfMicrotask).then((_) { |
| 2505 expect(model.count, 2); |
| 2506 }); |
| 2507 }); |
| 2508 |
| 2327 test('issue-141', () { | 2509 test('issue-141', () { |
| 2328 var div = createTestHtml( | 2510 var div = createTestHtml( |
| 2329 '<template bind>' | 2511 '<template bind>' |
| 2330 '<div foo="{{foo1}} {{foo2}}" bar="{{bar}}"></div>' | 2512 '<div foo="{{foo1}} {{foo2}}" bar="{{bar}}"></div>' |
| 2331 '</template>'); | 2513 '</template>'); |
| 2332 | 2514 |
| 2515 var template = div.firstChild; |
| 2333 var model = toObservable({ | 2516 var model = toObservable({ |
| 2334 'foo1': 'foo1Value', | 2517 'foo1': 'foo1Value', |
| 2335 'foo2': 'foo2Value', | 2518 'foo2': 'foo2Value', |
| 2336 'bar': 'barValue' | 2519 'bar': 'barValue' |
| 2337 }); | 2520 }); |
| 2338 | 2521 |
| 2339 recursivelySetTemplateModel(div, model); | 2522 templateBind(template).model = model; |
| 2340 return new Future(() { | 2523 return new Future(() { |
| 2341 expect(div.lastChild.attributes['bar'], 'barValue'); | 2524 expect(div.lastChild.attributes['bar'], 'barValue'); |
| 2342 }); | 2525 }); |
| 2343 }); | 2526 }); |
| 2344 | 2527 |
| 2345 test('issue-18', () { | 2528 test('issue-18', () { |
| 2346 var delegate = new Issue18Syntax(); | 2529 var delegate = new Issue18Syntax(); |
| 2347 | 2530 |
| 2348 var div = createTestHtml( | 2531 var div = createTestHtml( |
| 2349 '<template bind>' | 2532 '<template bind>' |
| 2350 '<div class="foo: {{ bar }}"></div>' | 2533 '<div class="foo: {{ bar }}"></div>' |
| 2351 '</template>'); | 2534 '</template>'); |
| 2352 | 2535 |
| 2536 var template = div.firstChild; |
| 2353 var model = toObservable({'bar': 2}); | 2537 var model = toObservable({'bar': 2}); |
| 2354 | 2538 |
| 2355 recursivelySetTemplateModel(div, model, delegate); | 2539 templateBind(template)..model = model..bindingDelegate = delegate; |
| 2356 | 2540 |
| 2357 return new Future(() { | 2541 return new Future(() { |
| 2358 expect(div.lastChild.attributes['class'], 'foo: 2'); | 2542 expect(div.lastChild.attributes['class'], 'foo: 2'); |
| 2359 }); | 2543 }); |
| 2360 }); | 2544 }); |
| 2361 | 2545 |
| 2362 test('issue-152', () { | 2546 test('issue-152', () { |
| 2363 var div = createTestHtml('<template ref=notThere></template>'); | 2547 var div = createTestHtml( |
| 2548 '<template ref=notThere bind>XXX</template>'); |
| 2549 |
| 2364 var template = div.firstChild; | 2550 var template = div.firstChild; |
| 2551 templateBind(template).model = {}; |
| 2365 | 2552 |
| 2366 // if a ref cannot be located, a template will continue to use itself | 2553 return new Future(() { |
| 2367 // as the source of template instances. | 2554 // if a ref cannot be located, a template will continue to use itself |
| 2368 expect(template, templateBind(template).ref); | 2555 // as the source of template instances. |
| 2556 expect(div.nodes[1].text, 'XXX'); |
| 2557 }); |
| 2369 }); | 2558 }); |
| 2370 } | 2559 } |
| 2371 | 2560 |
| 2372 compatTests() { | 2561 compatTests() { |
| 2373 test('underbar bindings', () { | 2562 test('underbar bindings', () { |
| 2374 var div = createTestHtml( | 2563 var div = createTestHtml( |
| 2375 '<template bind>' | 2564 '<template bind>' |
| 2376 '<div _style="color: {{ color }};"></div>' | 2565 '<div _style="color: {{ color }};"></div>' |
| 2377 '<img _src="{{ url }}">' | 2566 '<img _src="{{ url }}">' |
| 2378 '<a _href="{{ url2 }}">Link</a>' | 2567 '<a _href="{{ url2 }}">Link</a>' |
| 2379 '<input type="number" _value="{{ number }}">' | 2568 '<input type="number" _value="{{ number }}">' |
| 2380 '</template>'); | 2569 '</template>'); |
| 2381 | 2570 |
| 2571 var template = div.firstChild; |
| 2382 var model = toObservable({ | 2572 var model = toObservable({ |
| 2383 'color': 'red', | 2573 'color': 'red', |
| 2384 'url': 'pic.jpg', | 2574 'url': 'pic.jpg', |
| 2385 'url2': 'link.html', | 2575 'url2': 'link.html', |
| 2386 'number': 4 | 2576 'number': 4 |
| 2387 }); | 2577 }); |
| 2388 | 2578 |
| 2389 recursivelySetTemplateModel(div, model); | 2579 templateBind(template).model = model; |
| 2390 return new Future(() { | 2580 return new Future(() { |
| 2391 var subDiv = div.firstChild.nextNode; | 2581 var subDiv = div.firstChild.nextNode; |
| 2392 expect(subDiv.attributes['style'], 'color: red;'); | 2582 expect(subDiv.attributes['style'], 'color: red;'); |
| 2393 | 2583 |
| 2394 var img = subDiv.nextNode; | 2584 var img = subDiv.nextNode; |
| 2395 expect(img.attributes['src'], 'pic.jpg'); | 2585 expect(img.attributes['src'], 'pic.jpg'); |
| 2396 | 2586 |
| 2397 var a = img.nextNode; | 2587 var a = img.nextNode; |
| 2398 expect(a.attributes['href'], 'link.html'); | 2588 expect(a.attributes['href'], 'link.html'); |
| 2399 | 2589 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2433 } | 2623 } |
| 2434 } | 2624 } |
| 2435 | 2625 |
| 2436 class Issue18Syntax extends BindingDelegate { | 2626 class Issue18Syntax extends BindingDelegate { |
| 2437 prepareBinding(path, name, node) { | 2627 prepareBinding(path, name, node) { |
| 2438 if (name != 'class') return null; | 2628 if (name != 'class') return null; |
| 2439 | 2629 |
| 2440 return (model, _, oneTime) => new PathObserver(model, path); | 2630 return (model, _, oneTime) => new PathObserver(model, path); |
| 2441 } | 2631 } |
| 2442 } | 2632 } |
| 2633 |
| 2634 class TestAccessorModel extends Observable { |
| 2635 @observable var value = 1; |
| 2636 var count = 0; |
| 2637 |
| 2638 @reflectable |
| 2639 get prop { |
| 2640 count++; |
| 2641 return value; |
| 2642 } |
| 2643 } |
| OLD | NEW |