@@ -74,6 +74,36 @@ main() {
7474 });
7575 }));
7676 });
77+
78+ describe ('Property access' , () {
79+ it ('should distinguish between map and property access' ,
80+ inject ([TestBed , AsyncTestCompleter ], (tb, async ) {
81+ tb.overrideView (Dummy , new View (
82+ template: '<property-access></property-access>' ,
83+ directives: [PropertyAccess ]
84+ ));
85+
86+ tb.createView (Dummy ).then ((view) {
87+ view.detectChanges ();
88+ expect (view.rootNodes).toHaveText ('prop:foo-prop;map:foo-map' );
89+ async .done ();
90+ });
91+ }));
92+
93+ it ('should not fallback on map access if property missing' ,
94+ inject ([TestBed , AsyncTestCompleter ], (tb, async ) {
95+ tb.overrideView (Dummy , new View (
96+ template: '<no-property-access></no-property-access>' ,
97+ directives: [NoPropertyAccess ]
98+ ));
99+
100+ tb.createView (Dummy ).then ((view) {
101+ expect (() => view.detectChanges ())
102+ .toThrowError (new RegExp ('property not found' ));
103+ async .done ();
104+ });
105+ }));
106+ });
77107}
78108
79109@Component (selector: 'dummy' )
@@ -115,3 +145,26 @@ class ThrowingComponent2 {
115145 functionThatThrowsNonError ();
116146 }
117147}
148+
149+ @proxy
150+ class PropModel implements Map {
151+ final String foo = 'foo-prop' ;
152+
153+ operator [](_) => 'foo-map' ;
154+
155+ noSuchMethod (_) {
156+ throw 'property not found' ;
157+ }
158+ }
159+
160+ @Component (selector: 'property-access' )
161+ @View (template: '''prop:{{model.foo}};map:{{model['foo']}}''' )
162+ class PropertyAccess {
163+ final model = new PropModel ();
164+ }
165+
166+ @Component (selector: 'no-property-access' )
167+ @View (template: '''{{model.doesNotExist}}''' )
168+ class NoPropertyAccess {
169+ final model = new PropModel ();
170+ }
0 commit comments