| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 // This code was auto-generated, is not intended to be edited, and is subject to | 5 // This code was auto-generated, is not intended to be edited, and is subject to |
| 6 // significant change. Please see the README file for more information. | 6 // significant change. Please see the README file for more information. |
| 7 | 7 |
| 8 library engine.all_the_rest_test; | 8 library engine.all_the_rest_test; |
| 9 | 9 |
| 10 import 'dart:collection'; | 10 import 'dart:collection'; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 import 'package:unittest/unittest.dart'; | 33 import 'package:unittest/unittest.dart'; |
| 34 | 34 |
| 35 import '../reflective_tests.dart'; | 35 import '../reflective_tests.dart'; |
| 36 import 'parser_test.dart'; | 36 import 'parser_test.dart'; |
| 37 import 'resolver_test.dart'; | 37 import 'resolver_test.dart'; |
| 38 import 'test_support.dart'; | 38 import 'test_support.dart'; |
| 39 | 39 |
| 40 | 40 |
| 41 main() { | 41 main() { |
| 42 groupSep = ' | '; | 42 groupSep = ' | '; |
| 43 runReflectiveTests(AngularCompilationUnitBuilderTest); | |
| 44 runReflectiveTests(AngularHtmlUnitResolverTest); | |
| 45 runReflectiveTests(AngularHtmlUnitUtilsTest); | |
| 46 runReflectiveTests(ConstantEvaluatorTest); | 43 runReflectiveTests(ConstantEvaluatorTest); |
| 47 runReflectiveTests(ConstantFinderTest); | 44 runReflectiveTests(ConstantFinderTest); |
| 48 runReflectiveTests(ConstantValueComputerTest); | 45 runReflectiveTests(ConstantValueComputerTest); |
| 49 runReflectiveTests(ConstantVisitorTest); | 46 runReflectiveTests(ConstantVisitorTest); |
| 50 runReflectiveTests(ContentCacheTest); | 47 runReflectiveTests(ContentCacheTest); |
| 51 runReflectiveTests(DartObjectImplTest); | 48 runReflectiveTests(DartObjectImplTest); |
| 52 runReflectiveTests(DartUriResolverTest); | 49 runReflectiveTests(DartUriResolverTest); |
| 53 runReflectiveTests(DeclaredVariablesTest); | 50 runReflectiveTests(DeclaredVariablesTest); |
| 54 runReflectiveTests(DirectoryBasedDartSdkTest); | 51 runReflectiveTests(DirectoryBasedDartSdkTest); |
| 55 runReflectiveTests(DirectoryBasedSourceContainerTest); | 52 runReflectiveTests(DirectoryBasedSourceContainerTest); |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 buffer.write(", "); | 443 buffer.write(", "); |
| 447 } | 444 } |
| 448 fail(buffer.toString()); | 445 fail(buffer.toString()); |
| 449 } | 446 } |
| 450 return firstToken; | 447 return firstToken; |
| 451 } | 448 } |
| 452 } | 449 } |
| 453 | 450 |
| 454 | 451 |
| 455 @ReflectiveTestCase() | 452 @ReflectiveTestCase() |
| 456 class AngularCompilationUnitBuilderTest extends AngularTest { | |
| 457 void test_bad_notConstructorAnnotation() { | |
| 458 String mainContent = r''' | |
| 459 const MY_ANNOTATION = null; | |
| 460 @MY_ANNOTATION() | |
| 461 class MyFilter { | |
| 462 }'''; | |
| 463 resolveMainSource(mainContent); | |
| 464 // prepare AngularFilterElement | |
| 465 ClassElement classElement = mainUnitElement.getType("MyFilter"); | |
| 466 AngularFormatterElement filter = | |
| 467 getAngularElement(classElement, (e) => e is AngularFormatterElement); | |
| 468 expect(filter, isNull); | |
| 469 } | |
| 470 | |
| 471 void test_Decorator() { | |
| 472 String mainContent = _createAngularSource(r''' | |
| 473 @Decorator(selector: '[my-dir]', | |
| 474 map: const { | |
| 475 'my-dir' : '=>myPropA', | |
| 476 '.' : '&myPropB', | |
| 477 }) | |
| 478 class MyDirective { | |
| 479 set myPropA(value) {} | |
| 480 set myPropB(value) {} | |
| 481 @NgTwoWay('my-prop-c') | |
| 482 String myPropC; | |
| 483 }'''); | |
| 484 resolveMainSourceNoErrors(mainContent); | |
| 485 // prepare AngularDirectiveElement | |
| 486 ClassElement classElement = mainUnitElement.getType("MyDirective"); | |
| 487 AngularDecoratorElement directive = | |
| 488 getAngularElement(classElement, (e) => e is AngularDecoratorElement); | |
| 489 expect(directive, isNotNull); | |
| 490 // verify | |
| 491 expect(directive.name, null); | |
| 492 expect(directive.nameOffset, -1); | |
| 493 _assertHasAttributeSelector(directive.selector, "my-dir"); | |
| 494 // verify properties | |
| 495 List<AngularPropertyElement> properties = directive.properties; | |
| 496 expect(properties, hasLength(3)); | |
| 497 _assertProperty( | |
| 498 properties[0], | |
| 499 "my-dir", | |
| 500 findMainOffset("my-dir' :"), | |
| 501 AngularPropertyKind.ONE_WAY, | |
| 502 "myPropA", | |
| 503 findMainOffset("myPropA'")); | |
| 504 _assertProperty( | |
| 505 properties[1], | |
| 506 ".", | |
| 507 findMainOffset(".' :"), | |
| 508 AngularPropertyKind.CALLBACK, | |
| 509 "myPropB", | |
| 510 findMainOffset("myPropB'")); | |
| 511 _assertProperty( | |
| 512 properties[2], | |
| 513 "my-prop-c", | |
| 514 findMainOffset("my-prop-c'"), | |
| 515 AngularPropertyKind.TWO_WAY, | |
| 516 "myPropC", | |
| 517 -1); | |
| 518 } | |
| 519 | |
| 520 void test_Decorator_bad_cannotParseSelector() { | |
| 521 String mainContent = _createAngularSource(r''' | |
| 522 @Decorator(selector: '~bad-selector', | |
| 523 map: const { | |
| 524 'my-dir' : '=>myPropA', | |
| 525 '.' : '&myPropB', | |
| 526 }) | |
| 527 class MyDirective { | |
| 528 set myPropA(value) {} | |
| 529 set myPropB(value) {} | |
| 530 }'''); | |
| 531 resolveMainSource(mainContent); | |
| 532 // has error | |
| 533 assertMainErrors([AngularCode.CANNOT_PARSE_SELECTOR]); | |
| 534 } | |
| 535 | |
| 536 void test_Decorator_bad_missingSelector() { | |
| 537 String mainContent = _createAngularSource(r''' | |
| 538 @Decorator(/*selector: '[my-dir]',*/ | |
| 539 map: const { | |
| 540 'my-dir' : '=>myPropA', | |
| 541 '.' : '&myPropB', | |
| 542 }) | |
| 543 class MyDirective { | |
| 544 set myPropA(value) {} | |
| 545 set myPropB(value) {} | |
| 546 }'''); | |
| 547 resolveMainSource(mainContent); | |
| 548 // has error | |
| 549 assertMainErrors([AngularCode.MISSING_SELECTOR]); | |
| 550 } | |
| 551 | |
| 552 void test_Formatter() { | |
| 553 String mainContent = _createAngularSource(r''' | |
| 554 @Formatter(name: 'myFilter') | |
| 555 class MyFilter { | |
| 556 call(p1, p2) {} | |
| 557 }'''); | |
| 558 resolveMainSourceNoErrors(mainContent); | |
| 559 // prepare AngularFilterElement | |
| 560 ClassElement classElement = mainUnitElement.getType("MyFilter"); | |
| 561 AngularFormatterElement filter = | |
| 562 getAngularElement(classElement, (e) => e is AngularFormatterElement); | |
| 563 expect(filter, isNotNull); | |
| 564 // verify | |
| 565 expect(filter.name, "myFilter"); | |
| 566 expect(filter.nameOffset, AngularTest.findOffset(mainContent, "myFilter'")); | |
| 567 } | |
| 568 | |
| 569 void test_Formatter_missingName() { | |
| 570 String mainContent = _createAngularSource(r''' | |
| 571 @Formatter() | |
| 572 class MyFilter { | |
| 573 call(p1, p2) {} | |
| 574 }'''); | |
| 575 resolveMainSource(mainContent); | |
| 576 // has error | |
| 577 assertMainErrors([AngularCode.MISSING_NAME]); | |
| 578 // no filter | |
| 579 ClassElement classElement = mainUnitElement.getType("MyFilter"); | |
| 580 AngularFormatterElement filter = | |
| 581 getAngularElement(classElement, (e) => e is AngularFormatterElement); | |
| 582 expect(filter, isNull); | |
| 583 } | |
| 584 | |
| 585 void test_getElement_component_name() { | |
| 586 resolveMainSource(_createAngularSource(r''' | |
| 587 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 588 templateUrl: 'my_template.html', cssUrl: 'my_styles.css') | |
| 589 class MyComponent {}''')); | |
| 590 SimpleStringLiteral node = | |
| 591 _findMainNode("ctrl'", (n) => n is SimpleStringLiteral); | |
| 592 int offset = node.offset; | |
| 593 // find AngularComponentElement | |
| 594 Element element = AngularCompilationUnitBuilder.getElement(node, offset); | |
| 595 EngineTestCase.assertInstanceOf( | |
| 596 (obj) => obj is AngularComponentElement, | |
| 597 AngularComponentElement, | |
| 598 element); | |
| 599 } | |
| 600 | |
| 601 void test_getElement_component_property_fromFieldAnnotation() { | |
| 602 resolveMainSource(_createAngularSource(r''' | |
| 603 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 604 templateUrl: 'my_template.html', cssUrl: 'my_styles.css') | |
| 605 class MyComponent { | |
| 606 @NgOneWay('prop') | |
| 607 var field; | |
| 608 }''')); | |
| 609 // prepare node | |
| 610 SimpleStringLiteral node = | |
| 611 _findMainNode("prop'", (n) => n is SimpleStringLiteral); | |
| 612 int offset = node.offset; | |
| 613 // prepare Element | |
| 614 Element element = AngularCompilationUnitBuilder.getElement(node, offset); | |
| 615 expect(element, isNotNull); | |
| 616 // check AngularPropertyElement | |
| 617 AngularPropertyElement property = element as AngularPropertyElement; | |
| 618 expect(property.name, "prop"); | |
| 619 } | |
| 620 | |
| 621 void test_getElement_component_property_fromMap() { | |
| 622 resolveMainSource(_createAngularSource(r''' | |
| 623 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 624 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 625 map: const { | |
| 626 'prop' : '@field', | |
| 627 }) | |
| 628 class MyComponent { | |
| 629 var field; | |
| 630 }''')); | |
| 631 // AngularPropertyElement | |
| 632 { | |
| 633 SimpleStringLiteral node = | |
| 634 _findMainNode("prop'", (n) => n is SimpleStringLiteral); | |
| 635 int offset = node.offset; | |
| 636 // prepare Element | |
| 637 Element element = AngularCompilationUnitBuilder.getElement(node, offset); | |
| 638 expect(element, isNotNull); | |
| 639 // check AngularPropertyElement | |
| 640 AngularPropertyElement property = element as AngularPropertyElement; | |
| 641 expect(property.name, "prop"); | |
| 642 } | |
| 643 // FieldElement | |
| 644 { | |
| 645 SimpleStringLiteral node = | |
| 646 _findMainNode("@field'", (n) => n is SimpleStringLiteral); | |
| 647 int offset = node.offset; | |
| 648 // prepare Element | |
| 649 Element element = AngularCompilationUnitBuilder.getElement(node, offset); | |
| 650 expect(element, isNotNull); | |
| 651 // check FieldElement | |
| 652 FieldElement field = element as FieldElement; | |
| 653 expect(field.name, "field"); | |
| 654 } | |
| 655 } | |
| 656 | |
| 657 void test_getElement_component_selector() { | |
| 658 resolveMainSource(_createAngularSource(r''' | |
| 659 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 660 templateUrl: 'my_template.html', cssUrl: 'my_styles.css') | |
| 661 class MyComponent {}''')); | |
| 662 SimpleStringLiteral node = | |
| 663 _findMainNode("myComp'", (n) => n is SimpleStringLiteral); | |
| 664 int offset = node.offset; | |
| 665 // find AngularSelectorElement | |
| 666 Element element = AngularCompilationUnitBuilder.getElement(node, offset); | |
| 667 EngineTestCase.assertInstanceOf( | |
| 668 (obj) => obj is AngularSelectorElement, | |
| 669 AngularSelectorElement, | |
| 670 element); | |
| 671 } | |
| 672 | |
| 673 void test_getElement_controller_name() { | |
| 674 resolveMainSource(_createAngularSource(r''' | |
| 675 @Controller(publishAs: 'ctrl', selector: '[myApp]') | |
| 676 class MyController { | |
| 677 }''')); | |
| 678 SimpleStringLiteral node = | |
| 679 _findMainNode("ctrl'", (n) => n is SimpleStringLiteral); | |
| 680 int offset = node.offset; | |
| 681 // find AngularControllerElement | |
| 682 Element element = AngularCompilationUnitBuilder.getElement(node, offset); | |
| 683 EngineTestCase.assertInstanceOf( | |
| 684 (obj) => obj is AngularControllerElement, | |
| 685 AngularControllerElement, | |
| 686 element); | |
| 687 } | |
| 688 | |
| 689 void test_getElement_directive_property() { | |
| 690 resolveMainSource(_createAngularSource(r''' | |
| 691 @Decorator(selector: '[my-dir]', | |
| 692 map: const { | |
| 693 'my-dir' : '=>field' | |
| 694 }) | |
| 695 class MyDirective { | |
| 696 set field(value) {} | |
| 697 }''')); | |
| 698 // prepare node | |
| 699 SimpleStringLiteral node = | |
| 700 _findMainNode("my-dir'", (n) => n is SimpleStringLiteral); | |
| 701 int offset = node.offset; | |
| 702 // prepare Element | |
| 703 Element element = AngularCompilationUnitBuilder.getElement(node, offset); | |
| 704 expect(element, isNotNull); | |
| 705 // check AngularPropertyElement | |
| 706 AngularPropertyElement property = element as AngularPropertyElement; | |
| 707 expect(property.name, "my-dir"); | |
| 708 } | |
| 709 | |
| 710 void test_getElement_directive_selector() { | |
| 711 resolveMainSource(_createAngularSource(r''' | |
| 712 @Decorator(selector: '[my-dir]') | |
| 713 class MyDirective {}''')); | |
| 714 SimpleStringLiteral node = | |
| 715 _findMainNode("my-dir]'", (n) => n is SimpleStringLiteral); | |
| 716 int offset = node.offset; | |
| 717 // find AngularSelectorElement | |
| 718 Element element = AngularCompilationUnitBuilder.getElement(node, offset); | |
| 719 EngineTestCase.assertInstanceOf( | |
| 720 (obj) => obj is AngularSelectorElement, | |
| 721 AngularSelectorElement, | |
| 722 element); | |
| 723 } | |
| 724 | |
| 725 void test_getElement_filter_name() { | |
| 726 resolveMainSource(_createAngularSource(r''' | |
| 727 @Formatter(name: 'myFilter') | |
| 728 class MyFilter { | |
| 729 call(p1, p2) {} | |
| 730 }''')); | |
| 731 SimpleStringLiteral node = | |
| 732 _findMainNode("myFilter'", (n) => n is SimpleStringLiteral); | |
| 733 int offset = node.offset; | |
| 734 // find FilterElement | |
| 735 Element element = AngularCompilationUnitBuilder.getElement(node, offset); | |
| 736 EngineTestCase.assertInstanceOf( | |
| 737 (obj) => obj is AngularFormatterElement, | |
| 738 AngularFormatterElement, | |
| 739 element); | |
| 740 } | |
| 741 | |
| 742 void test_getElement_noClassDeclaration() { | |
| 743 resolveMainSource("var foo = 'bar';"); | |
| 744 SimpleStringLiteral node = | |
| 745 _findMainNode("bar'", (n) => n is SimpleStringLiteral); | |
| 746 Element element = AngularCompilationUnitBuilder.getElement(node, 0); | |
| 747 expect(element, isNull); | |
| 748 } | |
| 749 | |
| 750 void test_getElement_noClassElement() { | |
| 751 resolveMainSource(r''' | |
| 752 class A { | |
| 753 const A(p); | |
| 754 } | |
| 755 | |
| 756 @A('bar') | |
| 757 class B {}'''); | |
| 758 SimpleStringLiteral node = | |
| 759 _findMainNode("bar'", (n) => n is SimpleStringLiteral); | |
| 760 // reset B element | |
| 761 ClassDeclaration classDeclaration = | |
| 762 node.getAncestor((node) => node is ClassDeclaration); | |
| 763 classDeclaration.name.staticElement = null; | |
| 764 // class is not resolved - no element | |
| 765 Element element = AngularCompilationUnitBuilder.getElement(node, 0); | |
| 766 expect(element, isNull); | |
| 767 } | |
| 768 | |
| 769 void test_getElement_noNode() { | |
| 770 Element element = AngularCompilationUnitBuilder.getElement(null, 0); | |
| 771 expect(element, isNull); | |
| 772 } | |
| 773 | |
| 774 void test_getElement_notFound() { | |
| 775 resolveMainSource(r''' | |
| 776 class MyComponent { | |
| 777 var str = 'some string'; | |
| 778 }'''); | |
| 779 // prepare node | |
| 780 SimpleStringLiteral node = | |
| 781 _findMainNode("some string'", (n) => n is SimpleStringLiteral); | |
| 782 int offset = node.offset; | |
| 783 // no Element | |
| 784 Element element = AngularCompilationUnitBuilder.getElement(node, offset); | |
| 785 expect(element, isNull); | |
| 786 } | |
| 787 | |
| 788 void test_getElement_SimpleStringLiteral_withToolkitElement() { | |
| 789 SimpleStringLiteral literal = AstFactory.string2("foo"); | |
| 790 Element element = new AngularScopePropertyElementImpl("foo", 0, null); | |
| 791 literal.toolkitElement = element; | |
| 792 expect( | |
| 793 AngularCompilationUnitBuilder.getElement(literal, -1), | |
| 794 same(element)); | |
| 795 } | |
| 796 | |
| 797 void test_NgComponent_bad_cannotParseSelector() { | |
| 798 contextHelper.addSource("/my_template.html", ""); | |
| 799 contextHelper.addSource("/my_styles.css", ""); | |
| 800 String mainContent = _createAngularSource(r''' | |
| 801 @Component(publishAs: 'ctrl', selector: '~myComp', | |
| 802 templateUrl: 'my_template.html', cssUrl: 'my_styles.css') | |
| 803 class MyComponent { | |
| 804 }'''); | |
| 805 resolveMainSource(mainContent); | |
| 806 // has error | |
| 807 assertMainErrors([AngularCode.CANNOT_PARSE_SELECTOR]); | |
| 808 } | |
| 809 | |
| 810 void test_NgComponent_bad_missingSelector() { | |
| 811 contextHelper.addSource("/my_template.html", ""); | |
| 812 contextHelper.addSource("/my_styles.css", ""); | |
| 813 String mainContent = _createAngularSource(r''' | |
| 814 @Component(publishAs: 'ctrl', /*selector: 'myComp',*/ | |
| 815 templateUrl: 'my_template.html', cssUrl: 'my_styles.css') | |
| 816 class MyComponent { | |
| 817 }'''); | |
| 818 resolveMainSource(mainContent); | |
| 819 // has error | |
| 820 assertMainErrors([AngularCode.MISSING_SELECTOR]); | |
| 821 } | |
| 822 | |
| 823 /** | |
| 824 * | |
| 825 * https://code.google.com/p/dart/issues/detail?id=16346 | |
| 826 */ | |
| 827 void test_NgComponent_bad_notHtmlTemplate() { | |
| 828 contextHelper.addSource("/my_template", ""); | |
| 829 contextHelper.addSource("/my_styles.css", ""); | |
| 830 addMainSource(_createAngularSource(r''' | |
| 831 @NgComponent(publishAs: 'ctrl', selector: 'myComp', | |
| 832 templateUrl: 'my_template', cssUrl: 'my_styles.css') | |
| 833 class MyComponent { | |
| 834 }''')); | |
| 835 contextHelper.runTasks(); | |
| 836 } | |
| 837 | |
| 838 void test_NgComponent_bad_properties_invalidBinding() { | |
| 839 contextHelper.addSource("/my_template.html", ""); | |
| 840 contextHelper.addSource("/my_styles.css", ""); | |
| 841 String mainContent = _createAngularSource(r''' | |
| 842 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 843 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 844 map: const {'name' : '?field'}) | |
| 845 class MyComponent { | |
| 846 }'''); | |
| 847 resolveMainSource(mainContent); | |
| 848 // has error | |
| 849 assertMainErrors([AngularCode.INVALID_PROPERTY_KIND]); | |
| 850 } | |
| 851 | |
| 852 void test_NgComponent_bad_properties_nameNotStringLiteral() { | |
| 853 contextHelper.addSource("/my_template.html", ""); | |
| 854 contextHelper.addSource("/my_styles.css", ""); | |
| 855 String mainContent = _createAngularSource(r''' | |
| 856 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 857 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 858 map: const {null : 'field'}) | |
| 859 class MyComponent { | |
| 860 }'''); | |
| 861 resolveMainSource(mainContent); | |
| 862 // has error | |
| 863 assertMainErrors([AngularCode.INVALID_PROPERTY_NAME]); | |
| 864 } | |
| 865 | |
| 866 void test_NgComponent_bad_properties_noSuchField() { | |
| 867 contextHelper.addSource("/my_template.html", ""); | |
| 868 contextHelper.addSource("/my_styles.css", ""); | |
| 869 String mainContent = _createAngularSource(r''' | |
| 870 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 871 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 872 map: const {'name' : '=>field'}) | |
| 873 class MyComponent { | |
| 874 }'''); | |
| 875 resolveMainSource(mainContent); | |
| 876 // has error | |
| 877 assertMainErrors([AngularCode.INVALID_PROPERTY_FIELD]); | |
| 878 } | |
| 879 | |
| 880 void test_NgComponent_bad_properties_notMapLiteral() { | |
| 881 contextHelper.addSource("/my_template.html", ""); | |
| 882 contextHelper.addSource("/my_styles.css", ""); | |
| 883 String mainContent = _createAngularSource(r''' | |
| 884 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 885 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 886 map: null) | |
| 887 class MyComponent { | |
| 888 }'''); | |
| 889 resolveMainSource(mainContent); | |
| 890 // has error | |
| 891 assertMainErrors([AngularCode.INVALID_PROPERTY_MAP]); | |
| 892 } | |
| 893 | |
| 894 void test_NgComponent_bad_properties_specNotStringLiteral() { | |
| 895 contextHelper.addSource("/my_template.html", ""); | |
| 896 contextHelper.addSource("/my_styles.css", ""); | |
| 897 String mainContent = _createAngularSource(r''' | |
| 898 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 899 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 900 map: const {'name' : null}) | |
| 901 class MyComponent { | |
| 902 }'''); | |
| 903 resolveMainSource(mainContent); | |
| 904 // has error | |
| 905 assertMainErrors([AngularCode.INVALID_PROPERTY_SPEC]); | |
| 906 } | |
| 907 | |
| 908 void test_NgComponent_no_cssUrl() { | |
| 909 contextHelper.addSource("/my_template.html", ""); | |
| 910 contextHelper.addSource("/my_styles.css", ""); | |
| 911 String mainContent = _createAngularSource(r''' | |
| 912 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 913 templateUrl: 'my_template.html'/*, cssUrl: 'my_styles.css'*/) | |
| 914 class MyComponent { | |
| 915 }'''); | |
| 916 resolveMainSource(mainContent); | |
| 917 // prepare AngularComponentElement | |
| 918 ClassElement classElement = mainUnitElement.getType("MyComponent"); | |
| 919 AngularComponentElement component = | |
| 920 getAngularElement(classElement, (e) => e is AngularComponentElement); | |
| 921 expect(component, isNotNull); | |
| 922 // no CSS | |
| 923 expect(component.styleUri, null); | |
| 924 expect(component.styleUriOffset, -1); | |
| 925 } | |
| 926 | |
| 927 void test_NgComponent_no_publishAs() { | |
| 928 contextHelper.addSource("/my_template.html", ""); | |
| 929 contextHelper.addSource("/my_styles.css", ""); | |
| 930 String mainContent = _createAngularSource(r''' | |
| 931 @Component(/*publishAs: 'ctrl',*/ selector: 'myComp', | |
| 932 templateUrl: 'my_template.html', cssUrl: 'my_styles.css') | |
| 933 class MyComponent { | |
| 934 }'''); | |
| 935 resolveMainSource(mainContent); | |
| 936 // prepare AngularComponentElement | |
| 937 ClassElement classElement = mainUnitElement.getType("MyComponent"); | |
| 938 AngularComponentElement component = | |
| 939 getAngularElement(classElement, (e) => e is AngularComponentElement); | |
| 940 expect(component, isNotNull); | |
| 941 // no name | |
| 942 expect(component.name, null); | |
| 943 expect(component.nameOffset, -1); | |
| 944 } | |
| 945 | |
| 946 void test_NgComponent_no_templateUrl() { | |
| 947 contextHelper.addSource("/my_template.html", ""); | |
| 948 contextHelper.addSource("/my_styles.css", ""); | |
| 949 String mainContent = _createAngularSource(r''' | |
| 950 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 951 /*templateUrl: 'my_template.html',*/ cssUrl: 'my_styles.css') | |
| 952 class MyComponent { | |
| 953 }'''); | |
| 954 resolveMainSource(mainContent); | |
| 955 // prepare AngularComponentElement | |
| 956 ClassElement classElement = mainUnitElement.getType("MyComponent"); | |
| 957 AngularComponentElement component = | |
| 958 getAngularElement(classElement, (e) => e is AngularComponentElement); | |
| 959 expect(component, isNotNull); | |
| 960 // no template | |
| 961 expect(component.templateUri, null); | |
| 962 expect(component.templateSource, null); | |
| 963 expect(component.templateUriOffset, -1); | |
| 964 } | |
| 965 | |
| 966 /** | |
| 967 * https://code.google.com/p/dart/issues/detail?id=19023 | |
| 968 */ | |
| 969 void test_NgComponent_notAngular() { | |
| 970 contextHelper.addSource("/my_template.html", ""); | |
| 971 contextHelper.addSource("/my_styles.css", ""); | |
| 972 String mainContent = r''' | |
| 973 class Component { | |
| 974 const Component(a, b); | |
| 975 } | |
| 976 | |
| 977 @Component('foo', 42) | |
| 978 class MyComponent { | |
| 979 }'''; | |
| 980 resolveMainSource(mainContent); | |
| 981 assertNoMainErrors(); | |
| 982 } | |
| 983 | |
| 984 void test_NgComponent_properties_fieldFromSuper() { | |
| 985 contextHelper.addSource("/my_template.html", ""); | |
| 986 contextHelper.addSource("/my_styles.css", ""); | |
| 987 resolveMainSourceNoErrors(_createAngularSource(r''' | |
| 988 class MySuper { | |
| 989 var myPropA; | |
| 990 } | |
| 991 | |
| 992 | |
| 993 | |
| 994 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 995 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 996 map: const { | |
| 997 'prop-a' : '@myPropA' | |
| 998 }) | |
| 999 class MyComponent extends MySuper { | |
| 1000 }''')); | |
| 1001 // prepare AngularComponentElement | |
| 1002 ClassElement classElement = mainUnitElement.getType("MyComponent"); | |
| 1003 AngularComponentElement component = | |
| 1004 getAngularElement(classElement, (e) => e is AngularComponentElement); | |
| 1005 expect(component, isNotNull); | |
| 1006 // verify | |
| 1007 List<AngularPropertyElement> properties = component.properties; | |
| 1008 expect(properties, hasLength(1)); | |
| 1009 _assertProperty( | |
| 1010 properties[0], | |
| 1011 "prop-a", | |
| 1012 findMainOffset("prop-a' :"), | |
| 1013 AngularPropertyKind.ATTR, | |
| 1014 "myPropA", | |
| 1015 findMainOffset("myPropA'")); | |
| 1016 } | |
| 1017 | |
| 1018 void test_NgComponent_properties_fromFields() { | |
| 1019 contextHelper.addSource("/my_template.html", ""); | |
| 1020 contextHelper.addSource("/my_styles.css", ""); | |
| 1021 resolveMainSourceNoErrors(_createAngularSource(r''' | |
| 1022 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 1023 templateUrl: 'my_template.html', cssUrl: 'my_styles.css') | |
| 1024 class MyComponent { | |
| 1025 @NgAttr('prop-a') | |
| 1026 var myPropA; | |
| 1027 @NgCallback('prop-b') | |
| 1028 var myPropB; | |
| 1029 @NgOneWay('prop-c') | |
| 1030 var myPropC; | |
| 1031 @NgOneWayOneTime('prop-d') | |
| 1032 var myPropD; | |
| 1033 @NgTwoWay('prop-e') | |
| 1034 var myPropE; | |
| 1035 }''')); | |
| 1036 // prepare AngularComponentElement | |
| 1037 ClassElement classElement = mainUnitElement.getType("MyComponent"); | |
| 1038 AngularComponentElement component = | |
| 1039 getAngularElement(classElement, (e) => e is AngularComponentElement); | |
| 1040 expect(component, isNotNull); | |
| 1041 // verify | |
| 1042 List<AngularPropertyElement> properties = component.properties; | |
| 1043 expect(properties, hasLength(5)); | |
| 1044 _assertProperty( | |
| 1045 properties[0], | |
| 1046 "prop-a", | |
| 1047 findMainOffset("prop-a')"), | |
| 1048 AngularPropertyKind.ATTR, | |
| 1049 "myPropA", | |
| 1050 -1); | |
| 1051 _assertProperty( | |
| 1052 properties[1], | |
| 1053 "prop-b", | |
| 1054 findMainOffset("prop-b')"), | |
| 1055 AngularPropertyKind.CALLBACK, | |
| 1056 "myPropB", | |
| 1057 -1); | |
| 1058 _assertProperty( | |
| 1059 properties[2], | |
| 1060 "prop-c", | |
| 1061 findMainOffset("prop-c')"), | |
| 1062 AngularPropertyKind.ONE_WAY, | |
| 1063 "myPropC", | |
| 1064 -1); | |
| 1065 _assertProperty( | |
| 1066 properties[3], | |
| 1067 "prop-d", | |
| 1068 findMainOffset("prop-d')"), | |
| 1069 AngularPropertyKind.ONE_WAY_ONE_TIME, | |
| 1070 "myPropD", | |
| 1071 -1); | |
| 1072 _assertProperty( | |
| 1073 properties[4], | |
| 1074 "prop-e", | |
| 1075 findMainOffset("prop-e')"), | |
| 1076 AngularPropertyKind.TWO_WAY, | |
| 1077 "myPropE", | |
| 1078 -1); | |
| 1079 } | |
| 1080 | |
| 1081 void test_NgComponent_properties_fromMap() { | |
| 1082 contextHelper.addSource("/my_template.html", ""); | |
| 1083 contextHelper.addSource("/my_styles.css", ""); | |
| 1084 resolveMainSourceNoErrors(_createAngularSource(r''' | |
| 1085 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 1086 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 1087 map: const { | |
| 1088 'prop-a' : '@myPropA', | |
| 1089 'prop-b' : '&myPropB', | |
| 1090 'prop-c' : '=>myPropC', | |
| 1091 'prop-d' : '=>!myPropD', | |
| 1092 'prop-e' : '<=>myPropE' | |
| 1093 }) | |
| 1094 class MyComponent { | |
| 1095 var myPropA; | |
| 1096 var myPropB; | |
| 1097 var myPropC; | |
| 1098 var myPropD; | |
| 1099 var myPropE; | |
| 1100 }''')); | |
| 1101 // prepare AngularComponentElement | |
| 1102 ClassElement classElement = mainUnitElement.getType("MyComponent"); | |
| 1103 AngularComponentElement component = | |
| 1104 getAngularElement(classElement, (e) => e is AngularComponentElement); | |
| 1105 expect(component, isNotNull); | |
| 1106 // verify | |
| 1107 List<AngularPropertyElement> properties = component.properties; | |
| 1108 expect(properties, hasLength(5)); | |
| 1109 _assertProperty( | |
| 1110 properties[0], | |
| 1111 "prop-a", | |
| 1112 findMainOffset("prop-a' :"), | |
| 1113 AngularPropertyKind.ATTR, | |
| 1114 "myPropA", | |
| 1115 findMainOffset("myPropA'")); | |
| 1116 _assertProperty( | |
| 1117 properties[1], | |
| 1118 "prop-b", | |
| 1119 findMainOffset("prop-b' :"), | |
| 1120 AngularPropertyKind.CALLBACK, | |
| 1121 "myPropB", | |
| 1122 findMainOffset("myPropB'")); | |
| 1123 _assertProperty( | |
| 1124 properties[2], | |
| 1125 "prop-c", | |
| 1126 findMainOffset("prop-c' :"), | |
| 1127 AngularPropertyKind.ONE_WAY, | |
| 1128 "myPropC", | |
| 1129 findMainOffset("myPropC'")); | |
| 1130 _assertProperty( | |
| 1131 properties[3], | |
| 1132 "prop-d", | |
| 1133 findMainOffset("prop-d' :"), | |
| 1134 AngularPropertyKind.ONE_WAY_ONE_TIME, | |
| 1135 "myPropD", | |
| 1136 findMainOffset("myPropD'")); | |
| 1137 _assertProperty( | |
| 1138 properties[4], | |
| 1139 "prop-e", | |
| 1140 findMainOffset("prop-e' :"), | |
| 1141 AngularPropertyKind.TWO_WAY, | |
| 1142 "myPropE", | |
| 1143 findMainOffset("myPropE'")); | |
| 1144 } | |
| 1145 | |
| 1146 void test_NgComponent_properties_no() { | |
| 1147 contextHelper.addSource("/my_template.html", ""); | |
| 1148 contextHelper.addSource("/my_styles.css", ""); | |
| 1149 String mainContent = _createAngularSource(r''' | |
| 1150 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 1151 templateUrl: 'my_template.html', cssUrl: 'my_styles.css') | |
| 1152 class MyComponent { | |
| 1153 }'''); | |
| 1154 resolveMainSourceNoErrors(mainContent); | |
| 1155 // prepare AngularComponentElement | |
| 1156 ClassElement classElement = mainUnitElement.getType("MyComponent"); | |
| 1157 AngularComponentElement component = | |
| 1158 getAngularElement(classElement, (e) => e is AngularComponentElement); | |
| 1159 expect(component, isNotNull); | |
| 1160 // verify | |
| 1161 expect(component.name, "ctrl"); | |
| 1162 expect(component.nameOffset, AngularTest.findOffset(mainContent, "ctrl'")); | |
| 1163 _assertIsTagSelector(component.selector, "myComp"); | |
| 1164 expect(component.templateUri, "my_template.html"); | |
| 1165 expect( | |
| 1166 component.templateUriOffset, | |
| 1167 AngularTest.findOffset(mainContent, "my_template.html'")); | |
| 1168 expect(component.styleUri, "my_styles.css"); | |
| 1169 expect( | |
| 1170 component.styleUriOffset, | |
| 1171 AngularTest.findOffset(mainContent, "my_styles.css'")); | |
| 1172 expect(component.properties, hasLength(0)); | |
| 1173 } | |
| 1174 | |
| 1175 void test_NgComponent_scopeProperties() { | |
| 1176 contextHelper.addSource("/my_template.html", ""); | |
| 1177 contextHelper.addSource("/my_styles.css", ""); | |
| 1178 String mainContent = _createAngularSource(r''' | |
| 1179 @Component(publishAs: 'ctrl', selector: 'myComp', | |
| 1180 templateUrl: 'my_template.html', cssUrl: 'my_styles.css') | |
| 1181 class MyComponent { | |
| 1182 MyComponent(Scope scope) { | |
| 1183 scope.context['boolProp'] = true; | |
| 1184 scope.context['intProp'] = 42; | |
| 1185 scope.context['stringProp'] = 'foo'; | |
| 1186 // duplicate is ignored | |
| 1187 scope.context['boolProp'] = true; | |
| 1188 // LHS is not an IndexExpression | |
| 1189 var v1; | |
| 1190 v1 = 1; | |
| 1191 // LHS is not a Scope access | |
| 1192 var v2; | |
| 1193 v2['name'] = 2; | |
| 1194 } | |
| 1195 }'''); | |
| 1196 resolveMainSourceNoErrors(mainContent); | |
| 1197 // prepare AngularComponentElement | |
| 1198 ClassElement classElement = mainUnitElement.getType("MyComponent"); | |
| 1199 AngularComponentElement component = | |
| 1200 getAngularElement(classElement, (e) => e is AngularComponentElement); | |
| 1201 expect(component, isNotNull); | |
| 1202 // verify | |
| 1203 List<AngularScopePropertyElement> scopeProperties = | |
| 1204 component.scopeProperties; | |
| 1205 expect(scopeProperties, hasLength(3)); | |
| 1206 { | |
| 1207 AngularScopePropertyElement property = scopeProperties[0]; | |
| 1208 expect(findMainElement2("boolProp"), same(property)); | |
| 1209 expect(property.name, "boolProp"); | |
| 1210 expect( | |
| 1211 property.nameOffset, | |
| 1212 AngularTest.findOffset(mainContent, "boolProp'")); | |
| 1213 expect(property.type.name, "bool"); | |
| 1214 } | |
| 1215 { | |
| 1216 AngularScopePropertyElement property = scopeProperties[1]; | |
| 1217 expect(findMainElement2("intProp"), same(property)); | |
| 1218 expect(property.name, "intProp"); | |
| 1219 expect( | |
| 1220 property.nameOffset, | |
| 1221 AngularTest.findOffset(mainContent, "intProp'")); | |
| 1222 expect(property.type.name, "int"); | |
| 1223 } | |
| 1224 { | |
| 1225 AngularScopePropertyElement property = scopeProperties[2]; | |
| 1226 expect(findMainElement2("stringProp"), same(property)); | |
| 1227 expect(property.name, "stringProp"); | |
| 1228 expect( | |
| 1229 property.nameOffset, | |
| 1230 AngularTest.findOffset(mainContent, "stringProp'")); | |
| 1231 expect(property.type.name, "String"); | |
| 1232 } | |
| 1233 } | |
| 1234 | |
| 1235 void test_NgController() { | |
| 1236 String mainContent = _createAngularSource(r''' | |
| 1237 @Controller(publishAs: 'ctrl', selector: '[myApp]') | |
| 1238 class MyController { | |
| 1239 }'''); | |
| 1240 resolveMainSourceNoErrors(mainContent); | |
| 1241 // prepare AngularControllerElement | |
| 1242 ClassElement classElement = mainUnitElement.getType("MyController"); | |
| 1243 AngularControllerElement controller = | |
| 1244 getAngularElement(classElement, (e) => e is AngularControllerElement); | |
| 1245 expect(controller, isNotNull); | |
| 1246 // verify | |
| 1247 expect(controller.name, "ctrl"); | |
| 1248 expect(controller.nameOffset, AngularTest.findOffset(mainContent, "ctrl'")); | |
| 1249 _assertHasAttributeSelector(controller.selector, "myApp"); | |
| 1250 } | |
| 1251 | |
| 1252 void test_NgController_cannotParseSelector() { | |
| 1253 String mainContent = _createAngularSource(r''' | |
| 1254 @Controller(publishAs: 'ctrl', selector: '~unknown') | |
| 1255 class MyController { | |
| 1256 }'''); | |
| 1257 resolveMainSource(mainContent); | |
| 1258 // has error | |
| 1259 assertMainErrors([AngularCode.CANNOT_PARSE_SELECTOR]); | |
| 1260 } | |
| 1261 | |
| 1262 void test_NgController_missingPublishAs() { | |
| 1263 String mainContent = _createAngularSource(r''' | |
| 1264 @Controller(selector: '[myApp]') | |
| 1265 class MyController { | |
| 1266 }'''); | |
| 1267 resolveMainSource(mainContent); | |
| 1268 // has error | |
| 1269 assertMainErrors([AngularCode.MISSING_PUBLISH_AS]); | |
| 1270 } | |
| 1271 | |
| 1272 void test_NgController_missingSelector() { | |
| 1273 String mainContent = _createAngularSource(r''' | |
| 1274 @Controller(publishAs: 'ctrl') | |
| 1275 class MyController { | |
| 1276 }'''); | |
| 1277 resolveMainSource(mainContent); | |
| 1278 // has error | |
| 1279 assertMainErrors([AngularCode.MISSING_SELECTOR]); | |
| 1280 } | |
| 1281 | |
| 1282 void test_NgController_noAnnotationArguments() { | |
| 1283 String mainContent = _createAngularSource(r''' | |
| 1284 @NgController | |
| 1285 class MyController { | |
| 1286 }'''); | |
| 1287 resolveMainSource(mainContent); | |
| 1288 } | |
| 1289 | |
| 1290 void test_parseSelector_hasAttribute() { | |
| 1291 AngularSelectorElement selector = | |
| 1292 AngularCompilationUnitBuilder.parseSelector(42, "[name]"); | |
| 1293 _assertHasAttributeSelector(selector, "name"); | |
| 1294 expect(selector.nameOffset, 42 + 1); | |
| 1295 } | |
| 1296 | |
| 1297 void test_parseSelector_hasClass() { | |
| 1298 AngularSelectorElement selector = | |
| 1299 AngularCompilationUnitBuilder.parseSelector(42, ".my-class"); | |
| 1300 AngularHasClassSelectorElementImpl classSelector = | |
| 1301 selector as AngularHasClassSelectorElementImpl; | |
| 1302 expect(classSelector.name, "my-class"); | |
| 1303 expect(classSelector.toString(), ".my-class"); | |
| 1304 expect(selector.nameOffset, 42 + 1); | |
| 1305 // test apply() | |
| 1306 { | |
| 1307 ht.XmlTagNode node = | |
| 1308 HtmlFactory.tagNode("div", [HtmlFactory.attribute("class", "one two")]
); | |
| 1309 expect(classSelector.apply(node), isFalse); | |
| 1310 } | |
| 1311 { | |
| 1312 ht.XmlTagNode node = HtmlFactory.tagNode( | |
| 1313 "div", | |
| 1314 [HtmlFactory.attribute("class", "one my-class two")]); | |
| 1315 expect(classSelector.apply(node), isTrue); | |
| 1316 } | |
| 1317 } | |
| 1318 | |
| 1319 void test_parseSelector_isTag() { | |
| 1320 AngularSelectorElement selector = | |
| 1321 AngularCompilationUnitBuilder.parseSelector(42, "name"); | |
| 1322 _assertIsTagSelector(selector, "name"); | |
| 1323 expect(selector.nameOffset, 42); | |
| 1324 } | |
| 1325 | |
| 1326 void test_parseSelector_isTag_hasAttribute() { | |
| 1327 AngularSelectorElement selector = | |
| 1328 AngularCompilationUnitBuilder.parseSelector(42, "tag[attr]"); | |
| 1329 EngineTestCase.assertInstanceOf( | |
| 1330 (obj) => obj is IsTagHasAttributeSelectorElementImpl, | |
| 1331 IsTagHasAttributeSelectorElementImpl, | |
| 1332 selector); | |
| 1333 expect(selector.name, "tag[attr]"); | |
| 1334 expect(selector.nameOffset, -1); | |
| 1335 expect((selector as IsTagHasAttributeSelectorElementImpl).tagName, "tag"); | |
| 1336 expect( | |
| 1337 (selector as IsTagHasAttributeSelectorElementImpl).attributeName, | |
| 1338 "attr"); | |
| 1339 } | |
| 1340 | |
| 1341 void test_parseSelector_unknown() { | |
| 1342 AngularSelectorElement selector = | |
| 1343 AngularCompilationUnitBuilder.parseSelector(0, "~unknown"); | |
| 1344 expect(selector, isNull); | |
| 1345 } | |
| 1346 | |
| 1347 void test_view() { | |
| 1348 contextHelper.addSource("/wrong.html", ""); | |
| 1349 contextHelper.addSource("/my_templateA.html", ""); | |
| 1350 contextHelper.addSource("/my_templateB.html", ""); | |
| 1351 String mainContent = _createAngularSource(r''' | |
| 1352 class MyRouteInitializer { | |
| 1353 init(ViewFactory view, foo) { | |
| 1354 foo.view('wrong.html'); // has target | |
| 1355 foo(); // less than one argument | |
| 1356 foo('wrong.html', 'bar'); // more than one argument | |
| 1357 foo('wrong' + '.html'); // not literal | |
| 1358 foo('wrong.html'); // not ViewFactory | |
| 1359 view('my_templateA.html'); | |
| 1360 view('my_templateB.html'); | |
| 1361 } | |
| 1362 }'''); | |
| 1363 resolveMainSourceNoErrors(mainContent); | |
| 1364 // prepare AngularViewElement(s) | |
| 1365 List<AngularViewElement> views = mainUnitElement.angularViews; | |
| 1366 expect(views, hasLength(2)); | |
| 1367 { | |
| 1368 AngularViewElement view = views[0]; | |
| 1369 expect(view.templateUri, "my_templateA.html"); | |
| 1370 expect(view.name, null); | |
| 1371 expect(view.nameOffset, -1); | |
| 1372 expect( | |
| 1373 view.templateUriOffset, | |
| 1374 AngularTest.findOffset(mainContent, "my_templateA.html'")); | |
| 1375 } | |
| 1376 { | |
| 1377 AngularViewElement view = views[1]; | |
| 1378 expect(view.templateUri, "my_templateB.html"); | |
| 1379 expect(view.name, null); | |
| 1380 expect(view.nameOffset, -1); | |
| 1381 expect( | |
| 1382 view.templateUriOffset, | |
| 1383 AngularTest.findOffset(mainContent, "my_templateB.html'")); | |
| 1384 } | |
| 1385 } | |
| 1386 | |
| 1387 void _assertProperty(AngularPropertyElement property, String expectedName, | |
| 1388 int expectedNameOffset, AngularPropertyKind expectedKind, | |
| 1389 String expectedFieldName, int expectedFieldOffset) { | |
| 1390 expect(property.name, expectedName); | |
| 1391 expect(property.nameOffset, expectedNameOffset); | |
| 1392 expect(property.propertyKind, same(expectedKind)); | |
| 1393 expect(property.field.name, expectedFieldName); | |
| 1394 expect(property.fieldNameOffset, expectedFieldOffset); | |
| 1395 } | |
| 1396 | |
| 1397 /** | |
| 1398 * Find [AstNode] of the given type in [mainUnit]. | |
| 1399 */ | |
| 1400 AstNode _findMainNode(String search, Predicate<AstNode> predicate) { | |
| 1401 return EngineTestCase.findNode(mainUnit, mainContent, search, predicate); | |
| 1402 } | |
| 1403 | |
| 1404 static AngularElement getAngularElement(Element element, | |
| 1405 Predicate<Element> predicate) { | |
| 1406 List<ToolkitObjectElement> toolkitObjects = null; | |
| 1407 if (element is ClassElement) { | |
| 1408 ClassElement classElement = element; | |
| 1409 toolkitObjects = classElement.toolkitObjects; | |
| 1410 } | |
| 1411 if (element is LocalVariableElement) { | |
| 1412 LocalVariableElement variableElement = element; | |
| 1413 toolkitObjects = variableElement.toolkitObjects; | |
| 1414 } | |
| 1415 if (toolkitObjects != null) { | |
| 1416 for (ToolkitObjectElement toolkitObject in toolkitObjects) { | |
| 1417 if (predicate(toolkitObject)) { | |
| 1418 return toolkitObject as AngularElement; | |
| 1419 } | |
| 1420 } | |
| 1421 } | |
| 1422 return null; | |
| 1423 } | |
| 1424 | |
| 1425 static void _assertHasAttributeSelector(AngularSelectorElement selector, | |
| 1426 String name) { | |
| 1427 EngineTestCase.assertInstanceOf( | |
| 1428 (obj) => obj is HasAttributeSelectorElementImpl, | |
| 1429 HasAttributeSelectorElementImpl, | |
| 1430 selector); | |
| 1431 expect((selector as HasAttributeSelectorElementImpl).name, name); | |
| 1432 } | |
| 1433 | |
| 1434 static void _assertIsTagSelector(AngularSelectorElement selector, | |
| 1435 String name) { | |
| 1436 EngineTestCase.assertInstanceOf( | |
| 1437 (obj) => obj is AngularTagSelectorElementImpl, | |
| 1438 AngularTagSelectorElementImpl, | |
| 1439 selector); | |
| 1440 expect((selector as AngularTagSelectorElementImpl).name, name); | |
| 1441 } | |
| 1442 | |
| 1443 static String _createAngularSource(String code) { | |
| 1444 return "import 'angular.dart';\n" + code; | |
| 1445 } | |
| 1446 } | |
| 1447 | |
| 1448 | |
| 1449 @ReflectiveTestCase() | |
| 1450 class AngularHtmlUnitResolverTest extends AngularTest { | |
| 1451 void fail_analysisContext_changeDart_invalidateApplication() { | |
| 1452 addMainSource(r''' | |
| 1453 | |
| 1454 import 'angular.dart'; | |
| 1455 | |
| 1456 @Component( | |
| 1457 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 1458 publishAs: 'ctrl', | |
| 1459 selector: 'myComponent') | |
| 1460 class MyComponent { | |
| 1461 }'''); | |
| 1462 contextHelper.addSource( | |
| 1463 "/entry-point.html", | |
| 1464 AngularTest.createHtmlWithAngular('')); | |
| 1465 addIndexSource2("/my_template.html", r''' | |
| 1466 <div> | |
| 1467 {{ctrl.noMethod()}} | |
| 1468 </div>'''); | |
| 1469 contextHelper.addSource("/my_styles.css", ""); | |
| 1470 contextHelper.runTasks(); | |
| 1471 // there are some errors in my_template.html | |
| 1472 { | |
| 1473 List<AnalysisError> errors = context.getErrors(indexSource).errors; | |
| 1474 expect(errors.length != 0, isTrue); | |
| 1475 } | |
| 1476 // change main.dart, there are no MyComponent anymore | |
| 1477 context.setContents(mainSource, ""); | |
| 1478 // ...errors in my_template.html should be removed | |
| 1479 { | |
| 1480 List<AnalysisError> errors = context.getErrors(indexSource).errors; | |
| 1481 expect(errors, isEmpty); | |
| 1482 expect(errors.length == 0, isTrue); | |
| 1483 } | |
| 1484 } | |
| 1485 | |
| 1486 void fail_ngRepeat_additionalVariables() { | |
| 1487 addMyController(); | |
| 1488 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1489 <li ng-repeat='name in ctrl.names'> | |
| 1490 {{$index}} {{$first}} {{$middle}} {{$last}} {{$even}} {{$odd}} | |
| 1491 </li>''')); | |
| 1492 assertResolvedIdentifier2("\$index", "int"); | |
| 1493 assertResolvedIdentifier2("\$first", "bool"); | |
| 1494 assertResolvedIdentifier2("\$middle", "bool"); | |
| 1495 assertResolvedIdentifier2("\$last", "bool"); | |
| 1496 assertResolvedIdentifier2("\$even", "bool"); | |
| 1497 assertResolvedIdentifier2("\$odd", "bool"); | |
| 1498 } | |
| 1499 | |
| 1500 void fail_ngRepeat_bad_expectedIdentifier() { | |
| 1501 addMyController(); | |
| 1502 resolveIndex2(AngularTest.createHtmlWithMyController(r''' | |
| 1503 <li ng-repeat='name + 42 in ctrl.names'> | |
| 1504 </li>''')); | |
| 1505 assertErrors(indexSource, [AngularCode.INVALID_REPEAT_ITEM_SYNTAX]); | |
| 1506 } | |
| 1507 | |
| 1508 void fail_ngRepeat_bad_expectedIn() { | |
| 1509 addMyController(); | |
| 1510 resolveIndex2(AngularTest.createHtmlWithMyController(r''' | |
| 1511 <li ng-repeat='name : ctrl.names'> | |
| 1512 </li>''')); | |
| 1513 assertErrors(indexSource, [AngularCode.INVALID_REPEAT_SYNTAX]); | |
| 1514 } | |
| 1515 | |
| 1516 void fail_ngRepeat_filters_filter_literal() { | |
| 1517 addMyController(); | |
| 1518 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1519 <li ng-repeat='item in ctrl.items | filter:42:null'/> | |
| 1520 </li>''')); | |
| 1521 // filter "filter" is resolved | |
| 1522 Element filterElement = assertResolvedIdentifier("filter"); | |
| 1523 EngineTestCase.assertInstanceOf( | |
| 1524 (obj) => obj is AngularFormatterElement, | |
| 1525 AngularFormatterElement, | |
| 1526 filterElement); | |
| 1527 } | |
| 1528 | |
| 1529 void fail_ngRepeat_filters_filter_propertyMap() { | |
| 1530 addMyController(); | |
| 1531 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1532 <li ng-repeat='item in ctrl.items | filter:{name:null, done:false}'/> | |
| 1533 </li>''')); | |
| 1534 assertResolvedIdentifier2("name:", "String"); | |
| 1535 assertResolvedIdentifier2("done:", "bool"); | |
| 1536 } | |
| 1537 | |
| 1538 void fail_ngRepeat_filters_missingColon() { | |
| 1539 addMyController(); | |
| 1540 resolveIndex2(AngularTest.createHtmlWithMyController(r''' | |
| 1541 <li ng-repeat="item in ctrl.items | orderBy:'' true"/> | |
| 1542 </li>''')); | |
| 1543 assertErrors(indexSource, [AngularCode.MISSING_FORMATTER_COLON]); | |
| 1544 } | |
| 1545 | |
| 1546 void fail_ngRepeat_filters_noArgs() { | |
| 1547 addMyController(); | |
| 1548 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1549 <li ng-repeat="item in ctrl.items | orderBy"/> | |
| 1550 </li>''')); | |
| 1551 // filter "orderBy" is resolved | |
| 1552 Element filterElement = assertResolvedIdentifier("orderBy"); | |
| 1553 EngineTestCase.assertInstanceOf( | |
| 1554 (obj) => obj is AngularFormatterElement, | |
| 1555 AngularFormatterElement, | |
| 1556 filterElement); | |
| 1557 } | |
| 1558 | |
| 1559 void fail_ngRepeat_filters_orderBy_emptyString() { | |
| 1560 addMyController(); | |
| 1561 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1562 <li ng-repeat="item in ctrl.items | orderBy:'':true"/> | |
| 1563 </li>''')); | |
| 1564 // filter "orderBy" is resolved | |
| 1565 Element filterElement = assertResolvedIdentifier("orderBy"); | |
| 1566 EngineTestCase.assertInstanceOf( | |
| 1567 (obj) => obj is AngularFormatterElement, | |
| 1568 AngularFormatterElement, | |
| 1569 filterElement); | |
| 1570 } | |
| 1571 | |
| 1572 void fail_ngRepeat_filters_orderBy_propertyList() { | |
| 1573 addMyController(); | |
| 1574 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1575 <li ng-repeat="item in ctrl.items | orderBy:['name', 'done']"/> | |
| 1576 </li>''')); | |
| 1577 assertResolvedIdentifier2("name'", "String"); | |
| 1578 assertResolvedIdentifier2("done'", "bool"); | |
| 1579 } | |
| 1580 | |
| 1581 void fail_ngRepeat_filters_orderBy_propertyName() { | |
| 1582 addMyController(); | |
| 1583 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1584 <li ng-repeat="item in ctrl.items | orderBy:'name'"/> | |
| 1585 </li>''')); | |
| 1586 assertResolvedIdentifier2("name'", "String"); | |
| 1587 } | |
| 1588 | |
| 1589 void fail_ngRepeat_filters_orderBy_propertyName_minus() { | |
| 1590 addMyController(); | |
| 1591 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1592 <li ng-repeat="item in ctrl.items | orderBy:'-name'"/> | |
| 1593 </li>''')); | |
| 1594 assertResolvedIdentifier2("name'", "String"); | |
| 1595 } | |
| 1596 | |
| 1597 void fail_ngRepeat_filters_orderBy_propertyName_plus() { | |
| 1598 addMyController(); | |
| 1599 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1600 <li ng-repeat="item in ctrl.items | orderBy:'+name'"/> | |
| 1601 </li>''')); | |
| 1602 assertResolvedIdentifier2("name'", "String"); | |
| 1603 } | |
| 1604 | |
| 1605 void fail_ngRepeat_filters_orderBy_propertyName_untypedItems() { | |
| 1606 addMyController(); | |
| 1607 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1608 <li ng-repeat="item in ctrl.untypedItems | orderBy:'name'"/> | |
| 1609 </li>''')); | |
| 1610 assertResolvedIdentifier2("name'", "dynamic"); | |
| 1611 } | |
| 1612 | |
| 1613 void fail_ngRepeat_filters_two() { | |
| 1614 addMyController(); | |
| 1615 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1616 <li ng-repeat="item in ctrl.items | orderBy:'+' | orderBy:'-'"/> | |
| 1617 </li>''')); | |
| 1618 EngineTestCase.assertInstanceOf( | |
| 1619 (obj) => obj is AngularFormatterElement, | |
| 1620 AngularFormatterElement, | |
| 1621 assertResolvedIdentifier("orderBy:'+'")); | |
| 1622 EngineTestCase.assertInstanceOf( | |
| 1623 (obj) => obj is AngularFormatterElement, | |
| 1624 AngularFormatterElement, | |
| 1625 assertResolvedIdentifier("orderBy:'-'")); | |
| 1626 } | |
| 1627 | |
| 1628 void fail_ngRepeat_resolvedExpressions() { | |
| 1629 addMyController(); | |
| 1630 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1631 <li ng-repeat='name in ctrl.names'> | |
| 1632 {{name}} | |
| 1633 </li>''')); | |
| 1634 assertResolvedIdentifier2("name in", "String"); | |
| 1635 assertResolvedIdentifier2("ctrl.", "MyController"); | |
| 1636 assertResolvedIdentifier2("names'", "List<String>"); | |
| 1637 assertResolvedIdentifier2("name}}", "String"); | |
| 1638 } | |
| 1639 | |
| 1640 void fail_ngRepeat_trackBy() { | |
| 1641 addMyController(); | |
| 1642 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1643 <li ng-repeat='name in ctrl.names track by name.length'/> | |
| 1644 </li>''')); | |
| 1645 assertResolvedIdentifier2("length'", "int"); | |
| 1646 } | |
| 1647 | |
| 1648 void test_analysisContext_changeEntryPoint_clearAngularErrors_inDart() { | |
| 1649 addMainSource(r''' | |
| 1650 | |
| 1651 import 'angular.dart'; | |
| 1652 | |
| 1653 @Component( | |
| 1654 templateUrl: 'no-such-template.html', cssUrl: 'my_styles.css', | |
| 1655 publishAs: 'ctrl', | |
| 1656 selector: 'myComponent') | |
| 1657 class MyComponent { | |
| 1658 }'''); | |
| 1659 Source entrySource = contextHelper.addSource( | |
| 1660 "/entry-point.html", | |
| 1661 AngularTest.createHtmlWithAngular('')); | |
| 1662 contextHelper.addSource("/my_styles.css", ""); | |
| 1663 contextHelper.runTasks(); | |
| 1664 // there are some errors in MyComponent | |
| 1665 { | |
| 1666 List<AnalysisError> errors = context.getErrors(mainSource).errors; | |
| 1667 expect(errors.length != 0, isTrue); | |
| 1668 } | |
| 1669 // make entry-point.html non-Angular | |
| 1670 context.setContents(entrySource, "<html/>"); | |
| 1671 // ...errors in MyComponent should be removed | |
| 1672 { | |
| 1673 List<AnalysisError> errors = context.getErrors(mainSource).errors; | |
| 1674 expect(errors.length == 0, isTrue); | |
| 1675 } | |
| 1676 } | |
| 1677 | |
| 1678 void test_analysisContext_changeEntryPoint_clearAngularErrors_inTemplate() { | |
| 1679 addMainSource(r''' | |
| 1680 | |
| 1681 import 'angular.dart'; | |
| 1682 | |
| 1683 @Component( | |
| 1684 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 1685 publishAs: 'ctrl', | |
| 1686 selector: 'myComponent') | |
| 1687 class MyComponent { | |
| 1688 }'''); | |
| 1689 Source entrySource = contextHelper.addSource( | |
| 1690 "/entry-point.html", | |
| 1691 AngularTest.createHtmlWithAngular('')); | |
| 1692 addIndexSource2("/my_template.html", r''' | |
| 1693 <div> | |
| 1694 {{ctrl.noMethod()}} | |
| 1695 </div>'''); | |
| 1696 contextHelper.addSource("/my_styles.css", ""); | |
| 1697 contextHelper.runTasks(); | |
| 1698 // there are some errors in my_template.html | |
| 1699 { | |
| 1700 List<AnalysisError> errors = context.getErrors(indexSource).errors; | |
| 1701 expect(errors.length != 0, isTrue); | |
| 1702 } | |
| 1703 // make entry-point.html non-Angular | |
| 1704 context.setContents(entrySource, "<html/>"); | |
| 1705 // ...errors in my_template.html should be removed | |
| 1706 { | |
| 1707 List<AnalysisError> errors = context.getErrors(indexSource).errors; | |
| 1708 expect(errors.length == 0, isTrue); | |
| 1709 } | |
| 1710 } | |
| 1711 | |
| 1712 void test_analysisContext_removeEntryPoint_clearAngularErrors_inDart() { | |
| 1713 addMainSource(r''' | |
| 1714 | |
| 1715 import 'angular.dart'; | |
| 1716 | |
| 1717 @Component( | |
| 1718 templateUrl: 'no-such-template.html', cssUrl: 'my_styles.css', | |
| 1719 publishAs: 'ctrl', | |
| 1720 selector: 'myComponent') | |
| 1721 class MyComponent { | |
| 1722 }'''); | |
| 1723 Source entrySource = contextHelper.addSource( | |
| 1724 "/entry-point.html", | |
| 1725 AngularTest.createHtmlWithAngular('')); | |
| 1726 contextHelper.addSource("/my_styles.css", ""); | |
| 1727 contextHelper.runTasks(); | |
| 1728 // there are some errors in MyComponent | |
| 1729 { | |
| 1730 List<AnalysisError> errors = context.getErrors(mainSource).errors; | |
| 1731 expect(errors.length != 0, isTrue); | |
| 1732 } | |
| 1733 // remove entry-point.html | |
| 1734 { | |
| 1735 ChangeSet changeSet = new ChangeSet(); | |
| 1736 changeSet.removedSource(entrySource); | |
| 1737 context.applyChanges(changeSet); | |
| 1738 } | |
| 1739 // ...errors in MyComponent should be removed | |
| 1740 { | |
| 1741 List<AnalysisError> errors = context.getErrors(mainSource).errors; | |
| 1742 expect(errors.length == 0, isTrue); | |
| 1743 } | |
| 1744 } | |
| 1745 | |
| 1746 void test_contextProperties() { | |
| 1747 addMyController(); | |
| 1748 _resolveIndexNoErrors(AngularTest.createHtmlWithAngular(r''' | |
| 1749 <div> | |
| 1750 {{$id}} | |
| 1751 {{$parent}} | |
| 1752 {{$root}} | |
| 1753 </div>''')); | |
| 1754 assertResolvedIdentifier("\$id"); | |
| 1755 assertResolvedIdentifier("\$parent"); | |
| 1756 assertResolvedIdentifier("\$root"); | |
| 1757 } | |
| 1758 | |
| 1759 void test_getAngularElement_isAngular() { | |
| 1760 // prepare local variable "name" in compilation unit | |
| 1761 CompilationUnitElementImpl unit = | |
| 1762 ElementFactory.compilationUnit("test.dart"); | |
| 1763 FunctionElementImpl function = ElementFactory.functionElement("main"); | |
| 1764 unit.functions = <FunctionElement>[function]; | |
| 1765 LocalVariableElementImpl local = | |
| 1766 ElementFactory.localVariableElement2("name"); | |
| 1767 function.localVariables = <LocalVariableElement>[local]; | |
| 1768 // set AngularElement | |
| 1769 AngularElement angularElement = new AngularControllerElementImpl("ctrl", 0); | |
| 1770 local.toolkitObjects = <AngularElement>[angularElement]; | |
| 1771 expect( | |
| 1772 AngularHtmlUnitResolver.getAngularElement(local), | |
| 1773 same(angularElement)); | |
| 1774 } | |
| 1775 | |
| 1776 void test_getAngularElement_notAngular() { | |
| 1777 Element element = ElementFactory.localVariableElement2("name"); | |
| 1778 expect(AngularHtmlUnitResolver.getAngularElement(element), isNull); | |
| 1779 } | |
| 1780 | |
| 1781 void test_getAngularElement_notLocal() { | |
| 1782 Element element = ElementFactory.classElement2("Test"); | |
| 1783 expect(AngularHtmlUnitResolver.getAngularElement(element), isNull); | |
| 1784 } | |
| 1785 | |
| 1786 /** | |
| 1787 * Test that we resolve "ng-click" expression. | |
| 1788 */ | |
| 1789 void test_ngClick() { | |
| 1790 addMyController(); | |
| 1791 _resolveIndexNoErrors( | |
| 1792 AngularTest.createHtmlWithMyController( | |
| 1793 r"<button ng-click='ctrl.doSomething($event)'/>")); | |
| 1794 assertResolvedIdentifier("doSomething"); | |
| 1795 } | |
| 1796 | |
| 1797 void test_NgComponent_resolveTemplateFile() { | |
| 1798 addMainSource(r''' | |
| 1799 import 'angular.dart'; | |
| 1800 | |
| 1801 @Component( | |
| 1802 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 1803 publishAs: 'ctrl', | |
| 1804 selector: 'myComponent') | |
| 1805 class MyComponent { | |
| 1806 String field; | |
| 1807 }'''); | |
| 1808 contextHelper.addSource( | |
| 1809 "/entry-point.html", | |
| 1810 AngularTest.createHtmlWithAngular('')); | |
| 1811 addIndexSource2("/my_template.html", r''' | |
| 1812 <div> | |
| 1813 {{ctrl.field}} | |
| 1814 </div>'''); | |
| 1815 contextHelper.addSource("/my_styles.css", ""); | |
| 1816 contextHelper.runTasks(); | |
| 1817 resolveIndex(); | |
| 1818 assertNoErrors(); | |
| 1819 assertResolvedIdentifier2("ctrl.", "MyComponent"); | |
| 1820 assertResolvedIdentifier2("field}}", "String"); | |
| 1821 } | |
| 1822 | |
| 1823 void test_NgComponent_updateDartFile() { | |
| 1824 Source componentSource = contextHelper.addSource("/my_component.dart", r''' | |
| 1825 library my.component; | |
| 1826 import 'angular.dart'; | |
| 1827 @Component(selector: 'myComponent') | |
| 1828 class MyComponent { | |
| 1829 }'''); | |
| 1830 contextHelper.addSource("/my_module.dart", r''' | |
| 1831 library my.module; | |
| 1832 import 'my_component.dart';'''); | |
| 1833 addMainSource(r''' | |
| 1834 library main; | |
| 1835 import 'my_module.dart';'''); | |
| 1836 _resolveIndexNoErrors( | |
| 1837 AngularTest.createHtmlWithMyController("<myComponent/>")); | |
| 1838 // "myComponent" tag was resolved | |
| 1839 { | |
| 1840 ht.XmlTagNode tagNode = | |
| 1841 ht.HtmlUnitUtils.getTagNode(indexUnit, findOffset2("myComponent")); | |
| 1842 AngularSelectorElement tagElement = | |
| 1843 tagNode.element as AngularSelectorElement; | |
| 1844 expect(tagElement, isNotNull); | |
| 1845 expect(tagElement.name, "myComponent"); | |
| 1846 } | |
| 1847 // replace "myComponent" with "myComponent2" | |
| 1848 // in my_component.dart and index.html | |
| 1849 { | |
| 1850 context.setContents( | |
| 1851 componentSource, | |
| 1852 _getSourceContent(componentSource).replaceAll("myComponent", "myCompon
ent2")); | |
| 1853 indexContent = | |
| 1854 _getSourceContent(indexSource).replaceAll("myComponent", "myComponent2
"); | |
| 1855 context.setContents(indexSource, indexContent); | |
| 1856 } | |
| 1857 contextHelper.runTasks(); | |
| 1858 resolveIndex(); | |
| 1859 // "myComponent2" tag should be resolved | |
| 1860 { | |
| 1861 ht.XmlTagNode tagNode = | |
| 1862 ht.HtmlUnitUtils.getTagNode(indexUnit, findOffset2("myComponent2")); | |
| 1863 AngularSelectorElement tagElement = | |
| 1864 tagNode.element as AngularSelectorElement; | |
| 1865 expect(tagElement, isNotNull); | |
| 1866 expect(tagElement.name, "myComponent2"); | |
| 1867 } | |
| 1868 } | |
| 1869 | |
| 1870 void test_NgComponent_use_resolveAttributes() { | |
| 1871 contextHelper.addSource("/my_template.html", r''' | |
| 1872 <div> | |
| 1873 {{ctrl.field}} | |
| 1874 </div>'''); | |
| 1875 addMainSource(r''' | |
| 1876 | |
| 1877 import 'angular.dart'; | |
| 1878 | |
| 1879 @Component( | |
| 1880 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 1881 publishAs: 'ctrl', | |
| 1882 selector: 'myComponent', // selector | |
| 1883 map: const {'attrA' : '=>setA', 'attrB' : '@setB'}) | |
| 1884 class MyComponent { | |
| 1885 set setA(value) {} | |
| 1886 set setB(value) {} | |
| 1887 }'''); | |
| 1888 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1889 <input type='text' ng-model='someModel'/> | |
| 1890 <myComponent attrA='someModel' attrB='bbb'/>''')); | |
| 1891 // "attrA" attribute expression was resolved | |
| 1892 expect(findIdentifier("someModel"), isNotNull); | |
| 1893 // "myComponent" tag was resolved | |
| 1894 ht.XmlTagNode tagNode = | |
| 1895 ht.HtmlUnitUtils.getTagNode(indexUnit, findOffset2("myComponent")); | |
| 1896 AngularSelectorElement tagElement = | |
| 1897 tagNode.element as AngularSelectorElement; | |
| 1898 expect(tagElement, isNotNull); | |
| 1899 expect(tagElement.name, "myComponent"); | |
| 1900 expect(tagElement.nameOffset, findMainOffset("myComponent', // selector")); | |
| 1901 // "attrA" attribute was resolved | |
| 1902 { | |
| 1903 ht.XmlAttributeNode node = | |
| 1904 ht.HtmlUnitUtils.getAttributeNode(indexUnit, findOffset2("attrA='")); | |
| 1905 AngularPropertyElement element = node.element as AngularPropertyElement; | |
| 1906 expect(element, isNotNull); | |
| 1907 expect(element.name, "attrA"); | |
| 1908 expect(element.field.name, "setA"); | |
| 1909 } | |
| 1910 // "attrB" attribute was resolved, even if it @binding | |
| 1911 { | |
| 1912 ht.XmlAttributeNode node = | |
| 1913 ht.HtmlUnitUtils.getAttributeNode(indexUnit, findOffset2("attrB='")); | |
| 1914 AngularPropertyElement element = node.element as AngularPropertyElement; | |
| 1915 expect(element, isNotNull); | |
| 1916 expect(element.name, "attrB"); | |
| 1917 expect(element.field.name, "setB"); | |
| 1918 } | |
| 1919 } | |
| 1920 | |
| 1921 void test_NgDirective_noAttribute() { | |
| 1922 addMainSource(r''' | |
| 1923 | |
| 1924 import 'angular.dart'; | |
| 1925 | |
| 1926 @NgDirective(selector: '[my-directive]', map: const {'foo': '=>input'}) | |
| 1927 class MyDirective { | |
| 1928 set input(value) {} | |
| 1929 }'''); | |
| 1930 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1931 <div my-directive> | |
| 1932 </div>''')); | |
| 1933 } | |
| 1934 | |
| 1935 void test_NgDirective_noExpression() { | |
| 1936 addMainSource(r''' | |
| 1937 | |
| 1938 import 'angular.dart'; | |
| 1939 | |
| 1940 @NgDirective(selector: '[my-directive]', map: const {'.': '=>input'}) | |
| 1941 class MyDirective { | |
| 1942 set input(value) {} | |
| 1943 }'''); | |
| 1944 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1945 <div my-directive> | |
| 1946 </div>''')); | |
| 1947 } | |
| 1948 | |
| 1949 void test_NgDirective_resolvedExpression() { | |
| 1950 addMainSource(r''' | |
| 1951 | |
| 1952 import 'angular.dart'; | |
| 1953 | |
| 1954 @Decorator(selector: '[my-directive]') | |
| 1955 class MyDirective { | |
| 1956 @NgOneWay('my-property') | |
| 1957 String condition; | |
| 1958 }'''); | |
| 1959 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1960 <input type='text' ng-model='name'> | |
| 1961 <div my-directive my-property='name != null'> | |
| 1962 </div>''')); | |
| 1963 resolveMainNoErrors(); | |
| 1964 // "my-directive" attribute was resolved | |
| 1965 { | |
| 1966 AngularSelectorElement selector = | |
| 1967 findMainElement(ElementKind.ANGULAR_SELECTOR, "my-directive"); | |
| 1968 ht.XmlAttributeNode attrNodeSelector = | |
| 1969 ht.HtmlUnitUtils.getAttributeNode(indexUnit, findOffset2("my-directive
")); | |
| 1970 expect(attrNodeSelector, isNotNull); | |
| 1971 expect(attrNodeSelector.element, same(selector)); | |
| 1972 } | |
| 1973 // "my-property" attribute was resolved | |
| 1974 { | |
| 1975 ht.XmlAttributeNode attrNodeProperty = | |
| 1976 ht.HtmlUnitUtils.getAttributeNode(indexUnit, findOffset2("my-property=
'")); | |
| 1977 AngularPropertyElement propertyElement = | |
| 1978 attrNodeProperty.element as AngularPropertyElement; | |
| 1979 expect(propertyElement, isNotNull); | |
| 1980 expect(propertyElement.propertyKind, same(AngularPropertyKind.ONE_WAY)); | |
| 1981 expect(propertyElement.field.name, "condition"); | |
| 1982 } | |
| 1983 // "name" expression was resolved | |
| 1984 expect(findIdentifier("name != null"), isNotNull); | |
| 1985 } | |
| 1986 | |
| 1987 void test_NgDirective_resolvedExpression_attrString() { | |
| 1988 addMainSource(r''' | |
| 1989 | |
| 1990 import 'angular.dart'; | |
| 1991 | |
| 1992 @NgDirective(selector: '[my-directive]) | |
| 1993 class MyDirective { | |
| 1994 @NgAttr('my-property') | |
| 1995 String property; | |
| 1996 }'''); | |
| 1997 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 1998 <input type='text' ng-model='name'> | |
| 1999 <div my-directive my-property='name != null'> | |
| 2000 </div>''')); | |
| 2001 resolveMain(); | |
| 2002 // @NgAttr means "string attribute", which we don't parse | |
| 2003 expect(findIdentifierMaybe("name != null"), isNull); | |
| 2004 } | |
| 2005 | |
| 2006 void test_NgDirective_resolvedExpression_dotAsName() { | |
| 2007 addMainSource(r''' | |
| 2008 | |
| 2009 import 'angular.dart'; | |
| 2010 | |
| 2011 @Decorator( | |
| 2012 selector: '[my-directive]', | |
| 2013 map: const {'.' : '=>condition'}) | |
| 2014 class MyDirective { | |
| 2015 set condition(value) {} | |
| 2016 }'''); | |
| 2017 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 2018 <input type='text' ng-model='name'> | |
| 2019 <div my-directive='name != null'> | |
| 2020 </div>''')); | |
| 2021 // "name" attribute was resolved | |
| 2022 expect(findIdentifier("name != null"), isNotNull); | |
| 2023 } | |
| 2024 | |
| 2025 /** | |
| 2026 * Test that we resolve "ng-if" expression. | |
| 2027 */ | |
| 2028 void test_ngIf() { | |
| 2029 addMyController(); | |
| 2030 _resolveIndexNoErrors( | |
| 2031 AngularTest.createHtmlWithMyController("<div ng-if='ctrl.field != null'/
>")); | |
| 2032 assertResolvedIdentifier("field"); | |
| 2033 } | |
| 2034 | |
| 2035 void test_ngModel_modelAfterUsage() { | |
| 2036 addMyController(); | |
| 2037 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 2038 <h3>Hello {{name}}!</h3> | |
| 2039 <input type='text' ng-model='name'>''')); | |
| 2040 assertResolvedIdentifier2("name}}!", "String"); | |
| 2041 assertResolvedIdentifier2("name'>", "String"); | |
| 2042 } | |
| 2043 | |
| 2044 void test_ngModel_modelBeforeUsage() { | |
| 2045 addMyController(); | |
| 2046 _resolveIndexNoErrors(AngularTest.createHtmlWithMyController(r''' | |
| 2047 <input type='text' ng-model='name'> | |
| 2048 <h3>Hello {{name}}!</h3>''')); | |
| 2049 assertResolvedIdentifier2("name}}!", "String"); | |
| 2050 Element element = assertResolvedIdentifier2("name'>", "String"); | |
| 2051 expect(element.name, "name"); | |
| 2052 expect(element.nameOffset, findOffset2("name'>")); | |
| 2053 } | |
| 2054 | |
| 2055 void test_ngModel_notIdentifier() { | |
| 2056 addMyController(); | |
| 2057 _resolveIndexNoErrors( | |
| 2058 AngularTest.createHtmlWithMyController( | |
| 2059 "<input type='text' ng-model='ctrl.field'>")); | |
| 2060 assertResolvedIdentifier2("field'>", "String"); | |
| 2061 } | |
| 2062 | |
| 2063 /** | |
| 2064 * Test that we resolve "ng-mouseout" expression. | |
| 2065 */ | |
| 2066 void test_ngMouseOut() { | |
| 2067 addMyController(); | |
| 2068 _resolveIndexNoErrors( | |
| 2069 AngularTest.createHtmlWithMyController( | |
| 2070 r"<button ng-mouseout='ctrl.doSomething($event)'/>")); | |
| 2071 assertResolvedIdentifier("doSomething"); | |
| 2072 } | |
| 2073 | |
| 2074 /** | |
| 2075 * Test that we resolve "ng-show" expression. | |
| 2076 */ | |
| 2077 void test_ngShow() { | |
| 2078 addMyController(); | |
| 2079 _resolveIndexNoErrors( | |
| 2080 AngularTest.createHtmlWithMyController("<div ng-show='ctrl.field != null
'/>")); | |
| 2081 assertResolvedIdentifier("field"); | |
| 2082 } | |
| 2083 | |
| 2084 void test_notResolved_noDartScript() { | |
| 2085 resolveIndex2(r''' | |
| 2086 <html ng-app> | |
| 2087 <body> | |
| 2088 <div my-marker> | |
| 2089 {{ctrl.field}} | |
| 2090 </div> | |
| 2091 </body> | |
| 2092 </html>'''); | |
| 2093 assertNoErrors(); | |
| 2094 // Angular is not initialized, so "ctrl" is not parsed | |
| 2095 Expression expression = | |
| 2096 ht.HtmlUnitUtils.getExpression(indexUnit, findOffset2("ctrl")); | |
| 2097 expect(expression, isNull); | |
| 2098 } | |
| 2099 | |
| 2100 void test_notResolved_notAngular() { | |
| 2101 resolveIndex2(r''' | |
| 2102 <html no-ng-app> | |
| 2103 <body> | |
| 2104 <div my-marker> | |
| 2105 {{ctrl.field}} | |
| 2106 </div> | |
| 2107 </body> | |
| 2108 </html>'''); | |
| 2109 assertNoErrors(); | |
| 2110 // Angular is not initialized, so "ctrl" is not parsed | |
| 2111 Expression expression = | |
| 2112 ht.HtmlUnitUtils.getExpression(indexUnit, findOffset2("ctrl")); | |
| 2113 expect(expression, isNull); | |
| 2114 } | |
| 2115 | |
| 2116 void test_notResolved_wrongControllerMarker() { | |
| 2117 addMyController(); | |
| 2118 addIndexSource(r''' | |
| 2119 <html ng-app> | |
| 2120 <body> | |
| 2121 <div not-my-marker> | |
| 2122 {{ctrl.field}} | |
| 2123 </div> | |
| 2124 <script type='application/dart' src='main.dart'></script> | |
| 2125 </body> | |
| 2126 </html>'''); | |
| 2127 contextHelper.runTasks(); | |
| 2128 resolveIndex(); | |
| 2129 // no errors, because we decided to ignore them at the moment | |
| 2130 assertNoErrors(); | |
| 2131 // "ctrl" is not resolved | |
| 2132 SimpleIdentifier identifier = findIdentifier("ctrl"); | |
| 2133 expect(identifier.bestElement, isNull); | |
| 2134 } | |
| 2135 | |
| 2136 void test_resolveExpression_evenWithout_ngBootstrap() { | |
| 2137 resolveMainSource(r''' | |
| 2138 | |
| 2139 import 'angular.dart'; | |
| 2140 | |
| 2141 @Controller( | |
| 2142 selector: '[my-controller]', | |
| 2143 publishAs: 'ctrl') | |
| 2144 class MyController { | |
| 2145 String field; | |
| 2146 }'''); | |
| 2147 _resolveIndexNoErrors(r''' | |
| 2148 <html ng-app> | |
| 2149 <body> | |
| 2150 <div my-controller> | |
| 2151 {{ctrl.field}} | |
| 2152 </div> | |
| 2153 <script type='application/dart' src='main.dart'></script> | |
| 2154 </body> | |
| 2155 </html>'''); | |
| 2156 assertResolvedIdentifier2("ctrl.", "MyController"); | |
| 2157 } | |
| 2158 | |
| 2159 void test_resolveExpression_ignoreUnresolved() { | |
| 2160 resolveMainSource(r''' | |
| 2161 | |
| 2162 import 'angular.dart'; | |
| 2163 | |
| 2164 @Controller( | |
| 2165 selector: '[my-controller]', | |
| 2166 publishAs: 'ctrl') | |
| 2167 class MyController { | |
| 2168 Map map; | |
| 2169 Object obj; | |
| 2170 }'''); | |
| 2171 resolveIndex2(r''' | |
| 2172 <html ng-app> | |
| 2173 <body> | |
| 2174 <div my-controller> | |
| 2175 {{ctrl.map.property}} | |
| 2176 {{ctrl.obj.property}} | |
| 2177 {{invisibleScopeProperty}} | |
| 2178 </div> | |
| 2179 <script type='application/dart' src='main.dart'></script> | |
| 2180 </body> | |
| 2181 </html>'''); | |
| 2182 assertNoErrors(); | |
| 2183 // "ctrl.map" and "ctrl.obj" are resolved | |
| 2184 assertResolvedIdentifier2("map", "Map<dynamic, dynamic>"); | |
| 2185 assertResolvedIdentifier2("obj", "Object"); | |
| 2186 // ...but not "invisibleScopeProperty" | |
| 2187 { | |
| 2188 SimpleIdentifier identifier = findIdentifier("invisibleScopeProperty"); | |
| 2189 expect(identifier.bestElement, isNull); | |
| 2190 } | |
| 2191 } | |
| 2192 | |
| 2193 void test_resolveExpression_inAttribute() { | |
| 2194 addMyController(); | |
| 2195 _resolveIndexNoErrors( | |
| 2196 AngularTest.createHtmlWithMyController( | |
| 2197 "<button title='{{ctrl.field}}'></button>")); | |
| 2198 assertResolvedIdentifier2("ctrl", "MyController"); | |
| 2199 } | |
| 2200 | |
| 2201 void test_resolveExpression_ngApp_onBody() { | |
| 2202 addMyController(); | |
| 2203 _resolveIndexNoErrors(r''' | |
| 2204 <html> | |
| 2205 <body ng-app> | |
| 2206 <div my-controller> | |
| 2207 {{ctrl.field}} | |
| 2208 </div> | |
| 2209 <script type='application/dart' src='main.dart'></script> | |
| 2210 </body> | |
| 2211 </html>'''); | |
| 2212 assertResolvedIdentifier2("ctrl", "MyController"); | |
| 2213 } | |
| 2214 | |
| 2215 void test_resolveExpression_withFormatter() { | |
| 2216 addMyController(); | |
| 2217 _resolveIndexNoErrors( | |
| 2218 AngularTest.createHtmlWithMyController("{{ctrl.field | uppercase}}")); | |
| 2219 assertResolvedIdentifier2("ctrl", "MyController"); | |
| 2220 assertResolvedIdentifier("uppercase"); | |
| 2221 } | |
| 2222 | |
| 2223 void test_resolveExpression_withFormatter_missingColon() { | |
| 2224 addMyController(); | |
| 2225 resolveIndex2( | |
| 2226 AngularTest.createHtmlWithMyController( | |
| 2227 "{{ctrl.field | uppercase, lowercase}}")); | |
| 2228 assertErrors(indexSource, [AngularCode.MISSING_FORMATTER_COLON]); | |
| 2229 } | |
| 2230 | |
| 2231 void test_resolveExpression_withFormatter_notSimpleIdentifier() { | |
| 2232 addMyController(); | |
| 2233 resolveIndex2( | |
| 2234 AngularTest.createHtmlWithMyController("{{ctrl.field | not.supported}}")
); | |
| 2235 assertErrors(indexSource, [AngularCode.INVALID_FORMATTER_NAME]); | |
| 2236 } | |
| 2237 | |
| 2238 void test_scopeProperties() { | |
| 2239 addMainSource(r''' | |
| 2240 | |
| 2241 import 'angular.dart'; | |
| 2242 | |
| 2243 @Component( | |
| 2244 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 2245 publishAs: 'ctrl', | |
| 2246 selector: 'myComponent') | |
| 2247 class MyComponent { | |
| 2248 String field; | |
| 2249 MyComponent(Scope scope) { | |
| 2250 scope.context['scopeProperty'] = 'abc'; | |
| 2251 } | |
| 2252 } | |
| 2253 '''); | |
| 2254 contextHelper.addSource( | |
| 2255 "/entry-point.html", | |
| 2256 AngularTest.createHtmlWithAngular('')); | |
| 2257 addIndexSource2("/my_template.html", r''' | |
| 2258 <div> | |
| 2259 {{scopeProperty}} | |
| 2260 </div>'''); | |
| 2261 contextHelper.addSource("/my_styles.css", ""); | |
| 2262 contextHelper.runTasks(); | |
| 2263 resolveIndex(); | |
| 2264 assertNoErrors(); | |
| 2265 // "scopeProperty" is resolved | |
| 2266 Element element = assertResolvedIdentifier2("scopeProperty}}", "String"); | |
| 2267 EngineTestCase.assertInstanceOf( | |
| 2268 (obj) => obj is AngularScopePropertyElement, | |
| 2269 AngularScopePropertyElement, | |
| 2270 AngularHtmlUnitResolver.getAngularElement(element)); | |
| 2271 } | |
| 2272 | |
| 2273 void test_scopeProperties_hideWithComponent() { | |
| 2274 addMainSource(r''' | |
| 2275 | |
| 2276 import 'angular.dart'; | |
| 2277 | |
| 2278 @Component( | |
| 2279 templateUrl: 'my_template.html', cssUrl: 'my_styles.css', | |
| 2280 publishAs: 'ctrl', | |
| 2281 selector: 'myComponent') | |
| 2282 class MyComponent { | |
| 2283 } | |
| 2284 | |
| 2285 void setScopeProperties(Scope scope) { | |
| 2286 scope.context['ctrl'] = 1; | |
| 2287 } | |
| 2288 '''); | |
| 2289 contextHelper.addSource( | |
| 2290 "/entry-point.html", | |
| 2291 AngularTest.createHtmlWithAngular('')); | |
| 2292 addIndexSource2("/my_template.html", r''' | |
| 2293 <div> | |
| 2294 {{ctrl}} | |
| 2295 </div>'''); | |
| 2296 contextHelper.addSource("/my_styles.css", ""); | |
| 2297 contextHelper.runTasks(); | |
| 2298 resolveIndex(); | |
| 2299 assertNoErrors(); | |
| 2300 // "ctrl" is resolved | |
| 2301 LocalVariableElement element = | |
| 2302 assertResolvedIdentifier("ctrl}}") as LocalVariableElement; | |
| 2303 List<ToolkitObjectElement> toolkitObjects = element.toolkitObjects; | |
| 2304 EngineTestCase.assertInstanceOf( | |
| 2305 (obj) => obj is AngularComponentElement, | |
| 2306 AngularComponentElement, | |
| 2307 toolkitObjects[0]); | |
| 2308 } | |
| 2309 | |
| 2310 void test_view_resolveTemplateFile() { | |
| 2311 addMainSource(r''' | |
| 2312 | |
| 2313 import 'angular.dart'; | |
| 2314 | |
| 2315 @Controller( | |
| 2316 selector: '[my-controller]', | |
| 2317 publishAs: 'ctrl') | |
| 2318 class MyController { | |
| 2319 String field; | |
| 2320 } | |
| 2321 | |
| 2322 class MyRouteInitializer { | |
| 2323 init(ViewFactory view) { | |
| 2324 view('my_template.html'); | |
| 2325 } | |
| 2326 }'''); | |
| 2327 contextHelper.addSource( | |
| 2328 "/entry-point.html", | |
| 2329 AngularTest.createHtmlWithAngular('')); | |
| 2330 addIndexSource2("/my_template.html", r''' | |
| 2331 <div my-controller> | |
| 2332 {{ctrl.field}} | |
| 2333 </div>'''); | |
| 2334 contextHelper.addSource("/my_styles.css", ""); | |
| 2335 contextHelper.runTasks(); | |
| 2336 resolveIndex(); | |
| 2337 assertNoErrors(); | |
| 2338 assertResolvedIdentifier2("ctrl.", "MyController"); | |
| 2339 assertResolvedIdentifier2("field}}", "String"); | |
| 2340 } | |
| 2341 | |
| 2342 String _getSourceContent(Source source) { | |
| 2343 return context.getContents(source).data.toString(); | |
| 2344 } | |
| 2345 | |
| 2346 void _resolveIndexNoErrors(String content) { | |
| 2347 resolveIndex2(content); | |
| 2348 assertNoErrors(); | |
| 2349 verify([indexSource]); | |
| 2350 } | |
| 2351 } | |
| 2352 | |
| 2353 | |
| 2354 /** | |
| 2355 * Tests for [HtmlUnitUtils] for Angular HTMLs. | |
| 2356 */ | |
| 2357 @ReflectiveTestCase() | |
| 2358 class AngularHtmlUnitUtilsTest extends AngularTest { | |
| 2359 void test_getElement_forExpression() { | |
| 2360 addMyController(); | |
| 2361 _resolveSimpleCtrlFieldHtml(); | |
| 2362 // prepare expression | |
| 2363 int offset = indexContent.indexOf("ctrl"); | |
| 2364 Expression expression = ht.HtmlUnitUtils.getExpression(indexUnit, offset); | |
| 2365 // get element | |
| 2366 Element element = ht.HtmlUnitUtils.getElement(expression); | |
| 2367 EngineTestCase.assertInstanceOf( | |
| 2368 (obj) => obj is VariableElement, | |
| 2369 VariableElement, | |
| 2370 element); | |
| 2371 expect(element.name, "ctrl"); | |
| 2372 } | |
| 2373 | |
| 2374 void test_getElement_forExpression_null() { | |
| 2375 Element element = ht.HtmlUnitUtils.getElement(null); | |
| 2376 expect(element, isNull); | |
| 2377 } | |
| 2378 | |
| 2379 void test_getElement_forOffset() { | |
| 2380 addMyController(); | |
| 2381 _resolveSimpleCtrlFieldHtml(); | |
| 2382 // no expression | |
| 2383 { | |
| 2384 Element element = ht.HtmlUnitUtils.getElementAtOffset(indexUnit, 0); | |
| 2385 expect(element, isNull); | |
| 2386 } | |
| 2387 // has expression at offset | |
| 2388 { | |
| 2389 int offset = indexContent.indexOf("field"); | |
| 2390 Element element = ht.HtmlUnitUtils.getElementAtOffset(indexUnit, offset); | |
| 2391 EngineTestCase.assertInstanceOf( | |
| 2392 (obj) => obj is PropertyAccessorElement, | |
| 2393 PropertyAccessorElement, | |
| 2394 element); | |
| 2395 expect(element.name, "field"); | |
| 2396 } | |
| 2397 } | |
| 2398 | |
| 2399 void test_getElementToOpen_controller() { | |
| 2400 addMyController(); | |
| 2401 _resolveSimpleCtrlFieldHtml(); | |
| 2402 // prepare expression | |
| 2403 int offset = indexContent.indexOf("ctrl"); | |
| 2404 Expression expression = ht.HtmlUnitUtils.getExpression(indexUnit, offset); | |
| 2405 // get element | |
| 2406 Element element = ht.HtmlUnitUtils.getElementToOpen(indexUnit, expression); | |
| 2407 EngineTestCase.assertInstanceOf( | |
| 2408 (obj) => obj is AngularControllerElement, | |
| 2409 AngularControllerElement, | |
| 2410 element); | |
| 2411 expect(element.name, "ctrl"); | |
| 2412 } | |
| 2413 | |
| 2414 void test_getElementToOpen_field() { | |
| 2415 addMyController(); | |
| 2416 _resolveSimpleCtrlFieldHtml(); | |
| 2417 // prepare expression | |
| 2418 int offset = indexContent.indexOf("field"); | |
| 2419 Expression expression = ht.HtmlUnitUtils.getExpression(indexUnit, offset); | |
| 2420 // get element | |
| 2421 Element element = ht.HtmlUnitUtils.getElementToOpen(indexUnit, expression); | |
| 2422 EngineTestCase.assertInstanceOf( | |
| 2423 (obj) => obj is PropertyAccessorElement, | |
| 2424 PropertyAccessorElement, | |
| 2425 element); | |
| 2426 expect(element.name, "field"); | |
| 2427 } | |
| 2428 | |
| 2429 void test_getEnclosingTagNode() { | |
| 2430 resolveIndex2(r''' | |
| 2431 <html> | |
| 2432 <body ng-app> | |
| 2433 <badge name='abc'> 123 </badge> | |
| 2434 </body> | |
| 2435 </html>'''); | |
| 2436 // no unit | |
| 2437 expect(ht.HtmlUnitUtils.getEnclosingTagNode(null, 0), isNull); | |
| 2438 // wrong offset | |
| 2439 expect(ht.HtmlUnitUtils.getEnclosingTagNode(indexUnit, -1), isNull); | |
| 2440 // valid offset | |
| 2441 ht.XmlTagNode expected = _getEnclosingTagNode("<badge"); | |
| 2442 expect(expected, isNotNull); | |
| 2443 expect(expected.tag, "badge"); | |
| 2444 expect(_getEnclosingTagNode("badge"), same(expected)); | |
| 2445 expect(_getEnclosingTagNode("name="), same(expected)); | |
| 2446 expect(_getEnclosingTagNode("123"), same(expected)); | |
| 2447 expect(_getEnclosingTagNode("/badge"), same(expected)); | |
| 2448 } | |
| 2449 | |
| 2450 void test_getExpression() { | |
| 2451 addMyController(); | |
| 2452 _resolveSimpleCtrlFieldHtml(); | |
| 2453 // try offset without expression | |
| 2454 expect(ht.HtmlUnitUtils.getExpression(indexUnit, 0), isNull); | |
| 2455 // try offset with expression | |
| 2456 int offset = indexContent.indexOf("ctrl"); | |
| 2457 expect(ht.HtmlUnitUtils.getExpression(indexUnit, offset), isNotNull); | |
| 2458 expect(ht.HtmlUnitUtils.getExpression(indexUnit, offset + 1), isNotNull); | |
| 2459 expect(ht.HtmlUnitUtils.getExpression(indexUnit, offset + 2), isNotNull); | |
| 2460 expect( | |
| 2461 ht.HtmlUnitUtils.getExpression(indexUnit, offset + "ctrl.field".length), | |
| 2462 isNotNull); | |
| 2463 // try without unit | |
| 2464 expect(ht.HtmlUnitUtils.getExpression(null, offset), isNull); | |
| 2465 } | |
| 2466 | |
| 2467 void test_getTagNode() { | |
| 2468 resolveIndex2(r''' | |
| 2469 <html> | |
| 2470 <body ng-app> | |
| 2471 <badge name='abc'> 123 </badge> done | |
| 2472 </body> | |
| 2473 </html>'''); | |
| 2474 // no unit | |
| 2475 expect(ht.HtmlUnitUtils.getTagNode(null, 0), isNull); | |
| 2476 // wrong offset | |
| 2477 expect(ht.HtmlUnitUtils.getTagNode(indexUnit, -1), isNull); | |
| 2478 // on tag name | |
| 2479 ht.XmlTagNode expected = _getTagNode("badge name="); | |
| 2480 expect(expected, isNotNull); | |
| 2481 expect(expected.tag, "badge"); | |
| 2482 expect(_getTagNode("badge"), same(expected)); | |
| 2483 expect(_getTagNode(" name="), same(expected)); | |
| 2484 expect(_getTagNode("adge name="), same(expected)); | |
| 2485 expect(_getTagNode("badge>"), same(expected)); | |
| 2486 expect(_getTagNode("adge>"), same(expected)); | |
| 2487 expect(_getTagNode("> done"), same(expected)); | |
| 2488 // in tag node, but not on the name token | |
| 2489 expect(_getTagNode("name="), isNull); | |
| 2490 expect(_getTagNode("123"), isNull); | |
| 2491 } | |
| 2492 | |
| 2493 ht.XmlTagNode _getEnclosingTagNode(String search) { | |
| 2494 return ht.HtmlUnitUtils.getEnclosingTagNode( | |
| 2495 indexUnit, | |
| 2496 indexContent.indexOf(search)); | |
| 2497 } | |
| 2498 | |
| 2499 ht.XmlTagNode _getTagNode(String search) { | |
| 2500 return ht.HtmlUnitUtils.getTagNode(indexUnit, indexContent.indexOf(search)); | |
| 2501 } | |
| 2502 | |
| 2503 void _resolveSimpleCtrlFieldHtml() { | |
| 2504 resolveIndex2(r''' | |
| 2505 <html> | |
| 2506 <body ng-app> | |
| 2507 <div my-controller> | |
| 2508 {{ctrl.field}} | |
| 2509 </div> | |
| 2510 <script type='application/dart' src='main.dart'></script> | |
| 2511 </body> | |
| 2512 </html>'''); | |
| 2513 } | |
| 2514 } | |
| 2515 | |
| 2516 | |
| 2517 abstract class AngularTest extends EngineTestCase { | |
| 2518 AnalysisContextHelper contextHelper = new AnalysisContextHelper(); | |
| 2519 | |
| 2520 AnalysisContext context; | |
| 2521 | |
| 2522 String mainContent; | |
| 2523 | |
| 2524 Source mainSource; | |
| 2525 | |
| 2526 CompilationUnit mainUnit; | |
| 2527 | |
| 2528 CompilationUnitElement mainUnitElement; | |
| 2529 String indexContent; | |
| 2530 Source indexSource; | |
| 2531 ht.HtmlUnit indexUnit; | |
| 2532 HtmlElement indexHtmlUnit; | |
| 2533 CompilationUnitElement indexDartUnitElement; | |
| 2534 /** | |
| 2535 * Fills [indexContent] and [indexSource]. | |
| 2536 */ | |
| 2537 void addIndexSource(String content) { | |
| 2538 addIndexSource2("/index.html", content); | |
| 2539 } | |
| 2540 /** | |
| 2541 * Fills [indexContent] and [indexSource]. | |
| 2542 */ | |
| 2543 void addIndexSource2(String name, String content) { | |
| 2544 indexContent = content; | |
| 2545 indexSource = contextHelper.addSource(name, indexContent); | |
| 2546 } | |
| 2547 /** | |
| 2548 * Fills [mainContent] and [mainSource]. | |
| 2549 */ | |
| 2550 void addMainSource(String content) { | |
| 2551 mainContent = content; | |
| 2552 mainSource = contextHelper.addSource("/main.dart", content); | |
| 2553 } | |
| 2554 void addMyController() { | |
| 2555 resolveMainSource(r''' | |
| 2556 | |
| 2557 import 'angular.dart'; | |
| 2558 | |
| 2559 class Item { | |
| 2560 String name; | |
| 2561 bool done; | |
| 2562 } | |
| 2563 | |
| 2564 @Controller( | |
| 2565 selector: '[my-controller]', | |
| 2566 publishAs: 'ctrl') | |
| 2567 class MyController { | |
| 2568 String field; | |
| 2569 List<String> names; | |
| 2570 List<Item> items; | |
| 2571 var untypedItems; | |
| 2572 doSomething(event) {} | |
| 2573 }'''); | |
| 2574 } | |
| 2575 /** | |
| 2576 * Assert that the number of errors reported against the given source matches
the number of errors | |
| 2577 * that are given and that they have the expected error codes. The order in wh
ich the errors were | |
| 2578 * gathered is ignored. | |
| 2579 * | |
| 2580 * @param source the source against which the errors should have been reported | |
| 2581 * @param expectedErrorCodes the error codes of the errors that should have be
en reported | |
| 2582 * @throws AnalysisException if the reported errors could not be computed | |
| 2583 * @throws AssertionFailedError if a different number of errors have been repo
rted than were | |
| 2584 * expected | |
| 2585 */ | |
| 2586 void assertErrors(Source source, [List<ErrorCode> expectedErrorCodes = | |
| 2587 ErrorCode.EMPTY_LIST]) { | |
| 2588 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
| 2589 AnalysisErrorInfo errorsInfo = context.getErrors(source); | |
| 2590 for (AnalysisError error in errorsInfo.errors) { | |
| 2591 errorListener.onError(error); | |
| 2592 } | |
| 2593 errorListener.assertErrorsWithCodes(expectedErrorCodes); | |
| 2594 } | |
| 2595 | |
| 2596 void assertMainErrors(List<ErrorCode> expectedErrorCodes) { | |
| 2597 assertErrors(mainSource, expectedErrorCodes); | |
| 2598 } | |
| 2599 | |
| 2600 /** | |
| 2601 * Assert that no errors have been reported against the [indexSource]. | |
| 2602 */ | |
| 2603 void assertNoErrors() { | |
| 2604 assertErrors(indexSource); | |
| 2605 } | |
| 2606 | |
| 2607 void assertNoErrors2(Source source) { | |
| 2608 assertErrors(source); | |
| 2609 } | |
| 2610 | |
| 2611 /** | |
| 2612 * Assert that no errors have been reported against the [mainSource]. | |
| 2613 */ | |
| 2614 void assertNoMainErrors() { | |
| 2615 assertErrors(mainSource); | |
| 2616 } | |
| 2617 | |
| 2618 /** | |
| 2619 * Checks that [indexHtmlUnit] has [SimpleIdentifier] with given name, resolve
d to | |
| 2620 * not `null` [Element]. | |
| 2621 */ | |
| 2622 Element assertResolvedIdentifier(String name) { | |
| 2623 SimpleIdentifier identifier = findIdentifier(name); | |
| 2624 // check Element | |
| 2625 Element element = identifier.bestElement; | |
| 2626 expect(element, isNotNull); | |
| 2627 // return Element for further analysis | |
| 2628 return element; | |
| 2629 } | |
| 2630 | |
| 2631 Element assertResolvedIdentifier2(String name, String expectedTypeName) { | |
| 2632 SimpleIdentifier identifier = findIdentifier(name); | |
| 2633 // check Element | |
| 2634 Element element = identifier.bestElement; | |
| 2635 expect(element, isNotNull); | |
| 2636 // check Type | |
| 2637 DartType type = identifier.bestType; | |
| 2638 expect(type, isNotNull); | |
| 2639 expect(type.toString(), expectedTypeName); | |
| 2640 // return Element for further analysis | |
| 2641 return element; | |
| 2642 } | |
| 2643 | |
| 2644 /** | |
| 2645 * @return [AstNode] which has required offset and type. | |
| 2646 */ | |
| 2647 AstNode findExpression(int offset, Predicate<AstNode> predicate) { | |
| 2648 Expression expression = ht.HtmlUnitUtils.getExpression(indexUnit, offset); | |
| 2649 return expression != null ? expression.getAncestor(predicate) : null; | |
| 2650 } | |
| 2651 | |
| 2652 /** | |
| 2653 * Returns the [SimpleIdentifier] at the given search pattern. Fails if not fo
und. | |
| 2654 */ | |
| 2655 SimpleIdentifier findIdentifier(String search) { | |
| 2656 SimpleIdentifier identifier = findIdentifierMaybe(search); | |
| 2657 expect(identifier, isNotNull, reason: "$search in $indexContent"); | |
| 2658 // check that offset/length of the identifier is valid | |
| 2659 { | |
| 2660 int offset = identifier.offset; | |
| 2661 int end = identifier.end; | |
| 2662 String contentStr = indexContent.substring(offset, end); | |
| 2663 expect(contentStr, identifier.name); | |
| 2664 } | |
| 2665 // done | |
| 2666 return identifier; | |
| 2667 } | |
| 2668 | |
| 2669 /** | |
| 2670 * Returns the [SimpleIdentifier] at the given search pattern, or `null` if no
t found. | |
| 2671 */ | |
| 2672 SimpleIdentifier findIdentifierMaybe(String search) { | |
| 2673 return findExpression( | |
| 2674 findOffset2(search), | |
| 2675 (node) => node is SimpleIdentifier); | |
| 2676 } | |
| 2677 | |
| 2678 /** | |
| 2679 * Returns [Element] from [indexDartUnitElement]. | |
| 2680 */ | |
| 2681 Element findIndexElement(String name) { | |
| 2682 return findElement2(indexDartUnitElement, name); | |
| 2683 } | |
| 2684 | |
| 2685 /** | |
| 2686 * Returns [Element] from [mainUnitElement]. | |
| 2687 */ | |
| 2688 Element findMainElement(ElementKind kind, String name) { | |
| 2689 return findElement(mainUnitElement, kind, name); | |
| 2690 } | |
| 2691 | |
| 2692 /** | |
| 2693 * Returns [Element] from [mainUnitElement]. | |
| 2694 */ | |
| 2695 Element findMainElement2(String name) => findElement2(mainUnitElement, name); | |
| 2696 | |
| 2697 /** | |
| 2698 * @return the offset of given <code>search</code> string in [mainContent]. Fa
ils test if | |
| 2699 * not found. | |
| 2700 */ | |
| 2701 int findMainOffset(String search) => findOffset(mainContent, search); | |
| 2702 | |
| 2703 /** | |
| 2704 * @return the offset of given <code>search</code> string in [indexContent]. F
ails test if | |
| 2705 * not found. | |
| 2706 */ | |
| 2707 int findOffset2(String search) => findOffset(indexContent, search); | |
| 2708 | |
| 2709 /** | |
| 2710 * Resolves [indexSource]. | |
| 2711 */ | |
| 2712 void resolveIndex() { | |
| 2713 indexUnit = context.resolveHtmlUnit(indexSource); | |
| 2714 indexHtmlUnit = indexUnit.element; | |
| 2715 indexDartUnitElement = indexHtmlUnit.angularCompilationUnit; | |
| 2716 } | |
| 2717 | |
| 2718 void resolveIndex2(String content) { | |
| 2719 addIndexSource(content); | |
| 2720 contextHelper.runTasks(); | |
| 2721 resolveIndex(); | |
| 2722 } | |
| 2723 | |
| 2724 /** | |
| 2725 * Resolves [mainSource]. | |
| 2726 */ | |
| 2727 void resolveMain() { | |
| 2728 mainUnit = contextHelper.resolveDefiningUnit(mainSource); | |
| 2729 mainUnitElement = mainUnit.element; | |
| 2730 } | |
| 2731 | |
| 2732 /** | |
| 2733 * Resolves [mainSource]. | |
| 2734 */ | |
| 2735 void resolveMainNoErrors() { | |
| 2736 resolveMain(); | |
| 2737 assertNoErrors2(mainSource); | |
| 2738 } | |
| 2739 | |
| 2740 void resolveMainSource(String content) { | |
| 2741 addMainSource(content); | |
| 2742 resolveMain(); | |
| 2743 } | |
| 2744 | |
| 2745 void resolveMainSourceNoErrors(String content) { | |
| 2746 resolveMainSource(content); | |
| 2747 assertNoErrors2(mainSource); | |
| 2748 } | |
| 2749 | |
| 2750 @override | |
| 2751 void setUp() { | |
| 2752 super.setUp(); | |
| 2753 _configureForAngular(contextHelper); | |
| 2754 context = contextHelper.context; | |
| 2755 } | |
| 2756 | |
| 2757 @override | |
| 2758 void tearDown() { | |
| 2759 contextHelper = null; | |
| 2760 context = null; | |
| 2761 // main | |
| 2762 mainContent = null; | |
| 2763 mainSource = null; | |
| 2764 mainUnit = null; | |
| 2765 mainUnitElement = null; | |
| 2766 // index | |
| 2767 indexContent = null; | |
| 2768 indexSource = null; | |
| 2769 indexUnit = null; | |
| 2770 indexHtmlUnit = null; | |
| 2771 indexDartUnitElement = null; | |
| 2772 // super | |
| 2773 super.tearDown(); | |
| 2774 } | |
| 2775 | |
| 2776 /** | |
| 2777 * Verify that all of the identifiers in the HTML units associated with the gi
ven sources have | |
| 2778 * been resolved. | |
| 2779 * | |
| 2780 * @param sources the sources identifying the compilation units to be verified | |
| 2781 * @throws Exception if the contents of the compilation unit cannot be accesse
d | |
| 2782 */ | |
| 2783 void verify(List<Source> sources) { | |
| 2784 ResolutionVerifier verifier = new ResolutionVerifier(); | |
| 2785 for (Source source in sources) { | |
| 2786 ht.HtmlUnit htmlUnit = context.getResolvedHtmlUnit(source); | |
| 2787 htmlUnit.accept(new ExpressionVisitor_AngularTest_verify(verifier)); | |
| 2788 } | |
| 2789 verifier.assertResolved(); | |
| 2790 } | |
| 2791 | |
| 2792 void _configureForAngular(AnalysisContextHelper contextHelper) { | |
| 2793 contextHelper.addSource("/angular.dart", r''' | |
| 2794 library angular; | |
| 2795 | |
| 2796 class Scope { | |
| 2797 Map context; | |
| 2798 } | |
| 2799 | |
| 2800 class Formatter { | |
| 2801 final String name; | |
| 2802 const Formatter({this.name}); | |
| 2803 } | |
| 2804 | |
| 2805 class Directive { | |
| 2806 const Directive({ | |
| 2807 selector, | |
| 2808 children, | |
| 2809 visibility, | |
| 2810 module, | |
| 2811 map, | |
| 2812 exportedExpressions, | |
| 2813 exportedExpressionAttrs | |
| 2814 }); | |
| 2815 } | |
| 2816 | |
| 2817 class Decorator { | |
| 2818 const Decorator({ | |
| 2819 children/*: Directive.COMPILE_CHILDREN*/, | |
| 2820 map, | |
| 2821 selector, | |
| 2822 module, | |
| 2823 visibility, | |
| 2824 exportedExpressions, | |
| 2825 exportedExpressionAttrs | |
| 2826 }); | |
| 2827 } | |
| 2828 | |
| 2829 class Controller { | |
| 2830 const Controller({ | |
| 2831 children, | |
| 2832 publishAs, | |
| 2833 map, | |
| 2834 selector, | |
| 2835 visibility, | |
| 2836 publishTypes, | |
| 2837 exportedExpressions, | |
| 2838 exportedExpressionAttrs | |
| 2839 }); | |
| 2840 } | |
| 2841 | |
| 2842 class NgAttr { | |
| 2843 const NgAttr(String name); | |
| 2844 } | |
| 2845 class NgCallback { | |
| 2846 const NgCallback(String name); | |
| 2847 } | |
| 2848 class NgOneWay { | |
| 2849 const NgOneWay(String name); | |
| 2850 } | |
| 2851 class NgOneWayOneTime { | |
| 2852 const NgOneWayOneTime(String name); | |
| 2853 } | |
| 2854 class NgTwoWay { | |
| 2855 const NgTwoWay(String name); | |
| 2856 } | |
| 2857 | |
| 2858 class Component extends Directive { | |
| 2859 const Component({ | |
| 2860 this.template, | |
| 2861 this.templateUrl, | |
| 2862 this.cssUrl, | |
| 2863 this.applyAuthorStyles, | |
| 2864 this.resetStyleInheritance, | |
| 2865 publishAs, | |
| 2866 module, | |
| 2867 map, | |
| 2868 selector, | |
| 2869 visibility, | |
| 2870 exportExpressions, | |
| 2871 exportExpressionAttrs | |
| 2872 }) : super(selector: selector, | |
| 2873 children: null/*NgAnnotation.COMPILE_CHILDREN*/, | |
| 2874 visibility: visibility, | |
| 2875 map: map, | |
| 2876 module: module, | |
| 2877 exportExpressions: exportExpressions, | |
| 2878 exportExpressionAttrs: exportExpressionAttrs); | |
| 2879 } | |
| 2880 | |
| 2881 @Decorator(selector: '[ng-click]', map: const {'ng-click': '&onEvent'}) | |
| 2882 @Decorator(selector: '[ng-mouseout]', map: const {'ng-mouseout': '&onEvent'}) | |
| 2883 class NgEventDirective { | |
| 2884 set onEvent(value) {} | |
| 2885 } | |
| 2886 | |
| 2887 @Decorator(selector: '[ng-if]', map: const {'ng-if': '=>condition'}) | |
| 2888 class NgIfDirective { | |
| 2889 set condition(value) {} | |
| 2890 } | |
| 2891 | |
| 2892 @Decorator(selector: '[ng-show]', map: const {'ng-show': '=>show'}) | |
| 2893 class NgShowDirective { | |
| 2894 set show(value) {} | |
| 2895 } | |
| 2896 | |
| 2897 @Formatter(name: 'filter') | |
| 2898 class FilterFormatter {} | |
| 2899 | |
| 2900 @Formatter(name: 'orderBy') | |
| 2901 class OrderByFilter {} | |
| 2902 | |
| 2903 @Formatter(name: 'uppercase') | |
| 2904 class UppercaseFilter {} | |
| 2905 | |
| 2906 class ViewFactory { | |
| 2907 call(String templateUrl) => null; | |
| 2908 } | |
| 2909 | |
| 2910 class Module { | |
| 2911 install(Module m) {} | |
| 2912 type(Type t) {} | |
| 2913 value(Type t, value) {} | |
| 2914 } | |
| 2915 | |
| 2916 class Injector {} | |
| 2917 | |
| 2918 Injector ngBootstrap({ | |
| 2919 Module module: null, | |
| 2920 List<Module> modules: null, | |
| 2921 /*dom.Element*/ element: null, | |
| 2922 String selector: '[ng-app]', | |
| 2923 /*Injector*/ injectorFactory/*(List<Module> modules): _defaultInjectorFa
ctory*/}) {} | |
| 2924 '''); | |
| 2925 } | |
| 2926 | |
| 2927 /** | |
| 2928 * Creates an HTML content that has Angular marker and script with | |
| 2929 * the "main.dart" reference. | |
| 2930 */ | |
| 2931 static String createHtmlWithAngular(String innerCode) { | |
| 2932 String source = ''' | |
| 2933 <html ng-app> | |
| 2934 <body> | |
| 2935 $innerCode | |
| 2936 <script type='application/dart' src='main.dart'></script> | |
| 2937 </body> | |
| 2938 </html>'''; | |
| 2939 return source; | |
| 2940 } | |
| 2941 | |
| 2942 /** | |
| 2943 * Creates an HTML content that has Angular marker, script with "main.dart" re
ference and | |
| 2944 * "MyController" injected. | |
| 2945 */ | |
| 2946 static String createHtmlWithMyController(String innerHtml) { | |
| 2947 String source = ''' | |
| 2948 <html ng-app> | |
| 2949 <body> | |
| 2950 <div my-controller> | |
| 2951 $innerHtml | |
| 2952 </div> | |
| 2953 <script type='application/dart' src='main.dart'></script> | |
| 2954 </body> | |
| 2955 </html>'''; | |
| 2956 return source; | |
| 2957 } | |
| 2958 | |
| 2959 /** | |
| 2960 * Finds an [Element] with the given names inside of the given root [Element]. | |
| 2961 * | |
| 2962 * TODO(scheglov) maybe move this method to Element | |
| 2963 * | |
| 2964 * @param root the root [Element] to start searching from | |
| 2965 * @param kind the kind of the [Element] to find, if `null` then any kind | |
| 2966 * @param name the name of an [Element] to find | |
| 2967 * @return the found [Element] or `null` if not found | |
| 2968 */ | |
| 2969 static Element findElement(Element root, ElementKind kind, String name) { | |
| 2970 _AngularTest_findElement visitor = new _AngularTest_findElement(kind, name); | |
| 2971 root.accept(visitor); | |
| 2972 return visitor.result; | |
| 2973 } | |
| 2974 | |
| 2975 /** | |
| 2976 * Finds an [Element] with the given names inside of the given root [Element]. | |
| 2977 * | |
| 2978 * @param root the root [Element] to start searching from | |
| 2979 * @param name the name of an [Element] to find | |
| 2980 * @return the found [Element] or `null` if not found | |
| 2981 */ | |
| 2982 static Element findElement2(Element root, String name) { | |
| 2983 return findElement(root, null, name); | |
| 2984 } | |
| 2985 | |
| 2986 /** | |
| 2987 * @return the offset of given <code>search</code> string in <code>content</co
de>. Fails test if | |
| 2988 * not found. | |
| 2989 */ | |
| 2990 static int findOffset(String content, String search) { | |
| 2991 int offset = content.indexOf(search); | |
| 2992 expect(offset, isNot(-1)); | |
| 2993 return offset; | |
| 2994 } | |
| 2995 } | |
| 2996 | |
| 2997 | |
| 2998 @ReflectiveTestCase() | |
| 2999 class ConstantEvaluatorTest extends ResolverTestCase { | 453 class ConstantEvaluatorTest extends ResolverTestCase { |
| 3000 void fail_constructor() { | 454 void fail_constructor() { |
| 3001 EvaluationResult result = _getExpressionValue("?"); | 455 EvaluationResult result = _getExpressionValue("?"); |
| 3002 expect(result.isValid, isTrue); | 456 expect(result.isValid, isTrue); |
| 3003 DartObject value = result.value; | 457 DartObject value = result.value; |
| 3004 expect(value, null); | 458 expect(value, null); |
| 3005 } | 459 } |
| 3006 | 460 |
| 3007 void fail_identifier_class() { | 461 void fail_identifier_class() { |
| 3008 EvaluationResult result = _getExpressionValue("?"); | 462 EvaluationResult result = _getExpressionValue("?"); |
| (...skipping 6868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9877 Statement statement = ParserTestCase.parseStatement(source); | 7331 Statement statement = ParserTestCase.parseStatement(source); |
| 9878 expect(statement.accept(detector), same(expectedResult)); | 7332 expect(statement.accept(detector), same(expectedResult)); |
| 9879 } | 7333 } |
| 9880 | 7334 |
| 9881 void _assertTrue(String source) { | 7335 void _assertTrue(String source) { |
| 9882 _assertHasReturn(true, source); | 7336 _assertHasReturn(true, source); |
| 9883 } | 7337 } |
| 9884 } | 7338 } |
| 9885 | 7339 |
| 9886 | 7340 |
| 9887 class ExpressionVisitor_AngularTest_verify extends ExpressionVisitor { | |
| 9888 ResolutionVerifier verifier; | |
| 9889 | |
| 9890 ExpressionVisitor_AngularTest_verify(this.verifier); | |
| 9891 | |
| 9892 @override | |
| 9893 void visitExpression(Expression expression) { | |
| 9894 expression.accept(verifier); | |
| 9895 } | |
| 9896 } | |
| 9897 | |
| 9898 | |
| 9899 @ReflectiveTestCase() | 7341 @ReflectiveTestCase() |
| 9900 class FileBasedSourceTest { | 7342 class FileBasedSourceTest { |
| 9901 void test_equals_false_differentFiles() { | 7343 void test_equals_false_differentFiles() { |
| 9902 JavaFile file1 = FileUtilities2.createFile("/does/not/exist1.dart"); | 7344 JavaFile file1 = FileUtilities2.createFile("/does/not/exist1.dart"); |
| 9903 JavaFile file2 = FileUtilities2.createFile("/does/not/exist2.dart"); | 7345 JavaFile file2 = FileUtilities2.createFile("/does/not/exist2.dart"); |
| 9904 FileBasedSource source1 = new FileBasedSource.con1(file1); | 7346 FileBasedSource source1 = new FileBasedSource.con1(file1); |
| 9905 FileBasedSource source2 = new FileBasedSource.con1(file2); | 7347 FileBasedSource source2 = new FileBasedSource.con1(file2); |
| 9906 expect(source1 == source2, isFalse); | 7348 expect(source1 == source2, isFalse); |
| 9907 } | 7349 } |
| 9908 | 7350 |
| (...skipping 1427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11336 static const List<XmlValidator_Tag> EMPTY_LIST = const <XmlValidator_Tag>[]; | 8778 static const List<XmlValidator_Tag> EMPTY_LIST = const <XmlValidator_Tag>[]; |
| 11337 final String _tag; | 8779 final String _tag; |
| 11338 final XmlValidator_Attributes _attributes; | 8780 final XmlValidator_Attributes _attributes; |
| 11339 final String _content; | 8781 final String _content; |
| 11340 final List<XmlValidator_Tag> _children; | 8782 final List<XmlValidator_Tag> _children; |
| 11341 XmlValidator_Tag(this._tag, this._attributes, this._content, [this._children = | 8783 XmlValidator_Tag(this._tag, this._attributes, this._content, [this._children = |
| 11342 EMPTY_LIST]); | 8784 EMPTY_LIST]); |
| 11343 } | 8785 } |
| 11344 | 8786 |
| 11345 | 8787 |
| 11346 class _AngularTest_findElement extends GeneralizingElementVisitor<Object> { | |
| 11347 final ElementKind kind; | |
| 11348 | |
| 11349 final String name; | |
| 11350 | |
| 11351 Element result; | |
| 11352 | |
| 11353 _AngularTest_findElement(this.kind, this.name); | |
| 11354 | |
| 11355 @override | |
| 11356 Object visitElement(Element element) { | |
| 11357 if ((kind == null || element.kind == kind) && name == element.name) { | |
| 11358 result = element; | |
| 11359 } | |
| 11360 return super.visitElement(element); | |
| 11361 } | |
| 11362 } | |
| 11363 | |
| 11364 | |
| 11365 class _ExpectedScript { | 8788 class _ExpectedScript { |
| 11366 String _expectedExternalScriptName; | 8789 String _expectedExternalScriptName; |
| 11367 HtmlUnitBuilderTest_ExpectedLibrary _expectedLibrary; | 8790 HtmlUnitBuilderTest_ExpectedLibrary _expectedLibrary; |
| 11368 _ExpectedScript.con1(HtmlUnitBuilderTest_ExpectedLibrary expectedLibrary) { | 8791 _ExpectedScript.con1(HtmlUnitBuilderTest_ExpectedLibrary expectedLibrary) { |
| 11369 this._expectedExternalScriptName = null; | 8792 this._expectedExternalScriptName = null; |
| 11370 this._expectedLibrary = expectedLibrary; | 8793 this._expectedLibrary = expectedLibrary; |
| 11371 } | 8794 } |
| 11372 _ExpectedScript.con2(String expectedExternalScriptPath) { | 8795 _ExpectedScript.con2(String expectedExternalScriptPath) { |
| 11373 this._expectedExternalScriptName = expectedExternalScriptPath; | 8796 this._expectedExternalScriptName = expectedExternalScriptPath; |
| 11374 this._expectedLibrary = null; | 8797 this._expectedLibrary = null; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 11402 } else { | 8825 } else { |
| 11403 expect(scriptSource, isNotNull, reason: "script $scriptIndex"); | 8826 expect(scriptSource, isNotNull, reason: "script $scriptIndex"); |
| 11404 String actualExternalScriptName = scriptSource.shortName; | 8827 String actualExternalScriptName = scriptSource.shortName; |
| 11405 expect( | 8828 expect( |
| 11406 actualExternalScriptName, | 8829 actualExternalScriptName, |
| 11407 _expectedExternalScriptName, | 8830 _expectedExternalScriptName, |
| 11408 reason: "script $scriptIndex"); | 8831 reason: "script $scriptIndex"); |
| 11409 } | 8832 } |
| 11410 } | 8833 } |
| 11411 } | 8834 } |
| OLD | NEW |