| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  | import { | 
					
						
							|  |  |  |   ddescribe, | 
					
						
							|  |  |  |   describe, | 
					
						
							|  |  |  |   it, | 
					
						
							|  |  |  |   iit, | 
					
						
							|  |  |  |   xit, | 
					
						
							|  |  |  |   expect, | 
					
						
							|  |  |  |   beforeEach, | 
					
						
							|  |  |  |   afterEach, | 
					
						
							|  |  |  |   inject, | 
					
						
							|  |  |  |   beforeEachBindings | 
					
						
							|  |  |  | } from 'angular2/test_lib'; | 
					
						
							|  |  |  | import {bind} from 'angular2/src/core/di'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import {TEST_BINDINGS} from './test_bindings'; | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  | import {isPresent} from 'angular2/src/core/facade/lang'; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | import {TemplateParser, splitClasses} from 'angular2/src/compiler/template_parser'; | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  | import { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |   CompileDirectiveMetadata, | 
					
						
							|  |  |  |   CompileTypeMetadata, | 
					
						
							|  |  |  |   CompileTemplateMetadata | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  | } from 'angular2/src/compiler/directive_metadata'; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | import { | 
					
						
							|  |  |  |   templateVisitAll, | 
					
						
							|  |  |  |   TemplateAstVisitor, | 
					
						
							|  |  |  |   TemplateAst, | 
					
						
							|  |  |  |   NgContentAst, | 
					
						
							|  |  |  |   EmbeddedTemplateAst, | 
					
						
							|  |  |  |   ElementAst, | 
					
						
							|  |  |  |   VariableAst, | 
					
						
							|  |  |  |   BoundEventAst, | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |   BoundElementPropertyAst, | 
					
						
							|  |  |  |   BoundDirectivePropertyAst, | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |   AttrAst, | 
					
						
							|  |  |  |   BoundTextAst, | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |   TextAst, | 
					
						
							|  |  |  |   PropertyBindingType, | 
					
						
							|  |  |  |   DirectiveAst | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | } from 'angular2/src/compiler/template_ast'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  | import {ElementSchemaRegistry} from 'angular2/src/core/render/dom/schema/element_schema_registry'; | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  | import {MockSchemaRegistry} from './schema_registry_mock'; | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | import {Unparser} from '../core/change_detection/parser/unparser'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var expressionUnparser = new Unparser(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export function main() { | 
					
						
							|  |  |  |   describe('TemplateParser', () => { | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  |     beforeEachBindings(() => [ | 
					
						
							|  |  |  |       TEST_BINDINGS, | 
					
						
							|  |  |  |       bind(ElementSchemaRegistry) | 
					
						
							|  |  |  |           .toValue(new MockSchemaRegistry({'invalidProp': false}, {'mappedAttr': 'mappedProp'})) | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     var parser: TemplateParser; | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |     var ngIf; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  |     beforeEach(inject([TemplateParser], (_parser) => { | 
					
						
							|  |  |  |       parser = _parser; | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |       ngIf = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |         selector: '[ng-if]', | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |         type: new CompileTypeMetadata({name: 'NgIf'}), | 
					
						
							|  |  |  |         properties: ['ngIf'] | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  |     })); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |     function parse(template: string, directives: CompileDirectiveMetadata[]): TemplateAst[] { | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  |       return parser.parse(template, directives, 'TestComp'); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('parse', () => { | 
					
						
							|  |  |  |       describe('nodes without bindings', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse text nodes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('a', []))) | 
					
						
							|  |  |  |               .toEqual([[TextAst, 'a', 'TestComp > #text(a):nth-child(0)']]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse elements with attributes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div a=b>', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                 [AttrAst, 'a', 'b', 'TestComp > div:nth-child(0)[a=b]'] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse ngContent', () => { | 
					
						
							|  |  |  |         var parsed = parse('<ng-content select="a">', []); | 
					
						
							|  |  |  |         expect(humanizeTemplateAsts(parsed)) | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |             .toEqual([[NgContentAst, 'TestComp > ng-content:nth-child(0)']]); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse bound text nodes', () => { | 
					
						
							|  |  |  |         expect(humanizeTemplateAsts(parse('{{a}}', []))) | 
					
						
							|  |  |  |             .toEqual([[BoundTextAst, '{{ a }}', 'TestComp > #text({{a}}):nth-child(0)']]); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |       describe('bound properties', () => { | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |         it('should parse and camel case bound properties', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div [some-prop]="v">', []))) | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundElementPropertyAst, | 
					
						
							|  |  |  |                   PropertyBindingType.Property, | 
					
						
							|  |  |  |                   'someProp', | 
					
						
							|  |  |  |                   'v', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[[some-prop]=v]' | 
					
						
							|  |  |  |                 ] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |         it('should normalize property names via the element schema', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div [mapped-attr]="v">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundElementPropertyAst, | 
					
						
							|  |  |  |                   PropertyBindingType.Property, | 
					
						
							|  |  |  |                   'mappedProp', | 
					
						
							|  |  |  |                   'v', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[[mapped-attr]=v]' | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse and camel case bound attributes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div [attr.some-attr]="v">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundElementPropertyAst, | 
					
						
							|  |  |  |                   PropertyBindingType.Attribute, | 
					
						
							|  |  |  |                   'someAttr', | 
					
						
							|  |  |  |                   'v', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[[attr.some-attr]=v]' | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse and dash case bound classes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div [class.some-class]="v">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundElementPropertyAst, | 
					
						
							|  |  |  |                   PropertyBindingType.Class, | 
					
						
							|  |  |  |                   'some-class', | 
					
						
							|  |  |  |                   'v', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[[class.some-class]=v]' | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse and camel case bound styles', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div [style.some-style]="v">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundElementPropertyAst, | 
					
						
							|  |  |  |                   PropertyBindingType.Style, | 
					
						
							|  |  |  |                   'someStyle', | 
					
						
							|  |  |  |                   'v', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[[style.some-style]=v]' | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse bound properties via [...] and not report them as attributes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div [prop]="v">', []))) | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundElementPropertyAst, | 
					
						
							|  |  |  |                   PropertyBindingType.Property, | 
					
						
							|  |  |  |                   'prop', | 
					
						
							|  |  |  |                   'v', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[[prop]=v]' | 
					
						
							|  |  |  |                 ] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse bound properties via bind- and not report them as attributes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div bind-prop="v">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundElementPropertyAst, | 
					
						
							|  |  |  |                   PropertyBindingType.Property, | 
					
						
							|  |  |  |                   'prop', | 
					
						
							|  |  |  |                   'v', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[bind-prop=v]' | 
					
						
							|  |  |  |                 ] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse bound properties via {{...}} and not report them as attributes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div prop="{{v}}">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundElementPropertyAst, | 
					
						
							|  |  |  |                   PropertyBindingType.Property, | 
					
						
							|  |  |  |                   'prop', | 
					
						
							|  |  |  |                   '{{ v }}', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[prop={{v}}]' | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('events', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse bound events with a target', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div (window:event)="v">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundEventAst, | 
					
						
							|  |  |  |                   'event', | 
					
						
							|  |  |  |                   'window', | 
					
						
							|  |  |  |                   'v', | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[(window:event)=v]' | 
					
						
							|  |  |  |                 ] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse bound events via (...) and not report them as attributes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div (event)="v">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [BoundEventAst, 'event', null, 'v', 'TestComp > div:nth-child(0)[(event)=v]'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should camel case event names', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div (some-event)="v">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundEventAst, | 
					
						
							|  |  |  |                   'someEvent', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'v', | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[(some-event)=v]' | 
					
						
							|  |  |  |                 ] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse bound events via on- and not report them as attributes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div on-event="v">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [BoundEventAst, 'event', null, 'v', 'TestComp > div:nth-child(0)[on-event=v]'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('bindon', () => { | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |         it('should parse bound events and properties via [(...)] and not report them as attributes', | 
					
						
							|  |  |  |            () => { | 
					
						
							|  |  |  |              expect(humanizeTemplateAsts(parse('<div [(prop)]="v">', []))) | 
					
						
							|  |  |  |                  .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                    [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                    [ | 
					
						
							|  |  |  |                      BoundElementPropertyAst, | 
					
						
							|  |  |  |                      PropertyBindingType.Property, | 
					
						
							|  |  |  |                      'prop', | 
					
						
							|  |  |  |                      'v', | 
					
						
							|  |  |  |                      null, | 
					
						
							|  |  |  |                      'TestComp > div:nth-child(0)[[(prop)]=v]' | 
					
						
							|  |  |  |                    ], | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                    [ | 
					
						
							|  |  |  |                      BoundEventAst, | 
					
						
							|  |  |  |                      'prop', | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                      null, | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                      'v = $event', | 
					
						
							|  |  |  |                      'TestComp > div:nth-child(0)[[(prop)]=v]' | 
					
						
							|  |  |  |                    ] | 
					
						
							|  |  |  |                  ]); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse bound events and properties via bindon- and not report them as attributes', | 
					
						
							|  |  |  |            () => { | 
					
						
							|  |  |  |              expect(humanizeTemplateAsts(parse('<div bindon-prop="v">', []))) | 
					
						
							|  |  |  |                  .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                    [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                    [ | 
					
						
							|  |  |  |                      BoundElementPropertyAst, | 
					
						
							|  |  |  |                      PropertyBindingType.Property, | 
					
						
							|  |  |  |                      'prop', | 
					
						
							|  |  |  |                      'v', | 
					
						
							|  |  |  |                      null, | 
					
						
							|  |  |  |                      'TestComp > div:nth-child(0)[bindon-prop=v]' | 
					
						
							|  |  |  |                    ], | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                    [ | 
					
						
							|  |  |  |                      BoundEventAst, | 
					
						
							|  |  |  |                      'prop', | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                      null, | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                      'v = $event', | 
					
						
							|  |  |  |                      'TestComp > div:nth-child(0)[bindon-prop=v]' | 
					
						
							|  |  |  |                    ] | 
					
						
							|  |  |  |                  ]); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       describe('directives', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |         it('should locate directives components first and ordered by the directives array in the View', | 
					
						
							|  |  |  |            () => { | 
					
						
							|  |  |  |              var dirA = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |                  {selector: '[a]', type: new CompileTypeMetadata({name: 'DirA', id: 3})}); | 
					
						
							|  |  |  |              var dirB = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |                  {selector: '[b]', type: new CompileTypeMetadata({name: 'DirB', id: 2})}); | 
					
						
							|  |  |  |              var dirC = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |                  {selector: '[c]', type: new CompileTypeMetadata({name: 'DirC', id: 1})}); | 
					
						
							|  |  |  |              var comp = CompileDirectiveMetadata.create({ | 
					
						
							|  |  |  |                selector: 'div', | 
					
						
							|  |  |  |                isComponent: true, | 
					
						
							|  |  |  |                type: new CompileTypeMetadata({name: 'ZComp'}), | 
					
						
							|  |  |  |                template: new CompileTemplateMetadata({ngContentSelectors: []}) | 
					
						
							|  |  |  |              }); | 
					
						
							|  |  |  |              expect(humanizeTemplateAsts(parse('<div a c b>', [dirA, dirB, dirC, comp]))) | 
					
						
							|  |  |  |                  .toEqual([ | 
					
						
							|  |  |  |                    [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                    [AttrAst, 'a', '', 'TestComp > div:nth-child(0)[a=]'], | 
					
						
							|  |  |  |                    [AttrAst, 'b', '', 'TestComp > div:nth-child(0)[b=]'], | 
					
						
							|  |  |  |                    [AttrAst, 'c', '', 'TestComp > div:nth-child(0)[c=]'], | 
					
						
							|  |  |  |                    [DirectiveAst, comp, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                    [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                    [DirectiveAst, dirB, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                    [DirectiveAst, dirC, 'TestComp > div:nth-child(0)'] | 
					
						
							|  |  |  |                  ]); | 
					
						
							|  |  |  |            }); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should locate directives in property bindings', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           var dirA = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |               {selector: '[a=b]', type: new CompileTypeMetadata({name: 'DirA'})}); | 
					
						
							|  |  |  |           var dirB = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |               {selector: '[b]', type: new CompileTypeMetadata({name: 'DirB'})}); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |           expect(humanizeTemplateAsts(parse('<div [a]="b">', [dirA, dirB]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                   BoundElementPropertyAst, | 
					
						
							|  |  |  |                   PropertyBindingType.Property, | 
					
						
							|  |  |  |                   'a', | 
					
						
							|  |  |  |                   'b', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[[a]=b]' | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should locate directives in variable bindings', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           var dirA = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |               {selector: '[a=b]', exportAs: 'b', type: new CompileTypeMetadata({name: 'DirA'})}); | 
					
						
							|  |  |  |           var dirB = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |               {selector: '[b]', type: new CompileTypeMetadata({name: 'DirB'})}); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |           expect(humanizeTemplateAsts(parse('<div #a="b">', [dirA, dirB]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [VariableAst, 'a', 'b', 'TestComp > div:nth-child(0)[#a=b]'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should parse directive host properties', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           var dirA = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |             selector: 'div', | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |             type: new CompileTypeMetadata({name: 'DirA'}), | 
					
						
							|  |  |  |             host: {'[a]': 'expr'} | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |           }); | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div></div>', [dirA]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [ | 
					
						
							|  |  |  |                   BoundElementPropertyAst, | 
					
						
							|  |  |  |                   PropertyBindingType.Property, | 
					
						
							|  |  |  |                   'a', | 
					
						
							|  |  |  |                   'expr', | 
					
						
							|  |  |  |                   null, | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)' | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse directive host listeners', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           var dirA = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |             selector: 'div', | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |             type: new CompileTypeMetadata({name: 'DirA'}), | 
					
						
							|  |  |  |             host: {'(a)': 'expr'} | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |           }); | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div></div>', [dirA]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [BoundEventAst, 'a', null, 'expr', 'TestComp > div:nth-child(0)'] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse directive properties', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           var dirA = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |             selector: 'div', | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |             type: new CompileTypeMetadata({name: 'DirA'}), | 
					
						
							|  |  |  |             properties: ['aProp'] | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |           }); | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div [a-prop]="expr"></div>', [dirA]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [ | 
					
						
							|  |  |  |                   BoundDirectivePropertyAst, | 
					
						
							|  |  |  |                   'aProp', | 
					
						
							|  |  |  |                   'expr', | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[[a-prop]=expr]' | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse renamed directive properties', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           var dirA = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |             selector: 'div', | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |             type: new CompileTypeMetadata({name: 'DirA'}), | 
					
						
							|  |  |  |             properties: ['b:a'] | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |           }); | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div [a]="expr"></div>', [dirA]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [BoundDirectivePropertyAst, 'b', 'expr', 'TestComp > div:nth-child(0)[[a]=expr]'] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse literal directive properties', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           var dirA = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |               {selector: 'div', type: new CompileTypeMetadata({name: 'DirA'}), properties: ['a']}); | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |           expect(humanizeTemplateAsts(parse('<div a="literal"></div>', [dirA]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [AttrAst, 'a', 'literal', 'TestComp > div:nth-child(0)[a=literal]'], | 
					
						
							|  |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [ | 
					
						
							|  |  |  |                   BoundDirectivePropertyAst, | 
					
						
							|  |  |  |                   'a', | 
					
						
							|  |  |  |                   '"literal"', | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[a=literal]' | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |         it('should favor explicit bound properties over literal properties', () => { | 
					
						
							|  |  |  |           var dirA = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |               {selector: 'div', type: new CompileTypeMetadata({name: 'DirA'}), properties: ['a']}); | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div a="literal" [a]="\'literal2\'"></div>', [dirA]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							|  |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [AttrAst, 'a', 'literal', 'TestComp > div:nth-child(0)[a=literal]'], | 
					
						
							|  |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [ | 
					
						
							|  |  |  |                   BoundDirectivePropertyAst, | 
					
						
							|  |  |  |                   'a', | 
					
						
							|  |  |  |                   '"literal2"', | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[[a]=\'literal2\']' | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |         it('should support optional directive properties', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           var dirA = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |               {selector: 'div', type: new CompileTypeMetadata({name: 'DirA'}), properties: ['a']}); | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |           expect(humanizeTemplateAsts(parse('<div></div>', [dirA]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |       describe('variables', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse variables via #... and not report them as attributes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div #a>', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							|  |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [VariableAst, 'a', '', 'TestComp > div:nth-child(0)[#a=]'] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse variables via var-... and not report them as attributes', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div var-a>', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							|  |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [VariableAst, 'a', '', 'TestComp > div:nth-child(0)[var-a=]'] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should camel case variables', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div var-some-a>', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							|  |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [VariableAst, 'someA', '', 'TestComp > div:nth-child(0)[var-some-a=]'] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |         it('should assign variables with empty value to the element', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           expect(humanizeTemplateAsts(parse('<div #a></div>', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							|  |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [VariableAst, 'a', '', 'TestComp > div:nth-child(0)[#a=]'] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should assign variables to directives via exportAs', () => { | 
					
						
							|  |  |  |           var dirA = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |               {selector: '[a]', type: new CompileTypeMetadata({name: 'DirA'}), exportAs: 'dirA'}); | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div #a="dirA"></div>', [dirA]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							|  |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [VariableAst, 'a', 'dirA', 'TestComp > div:nth-child(0)[#a=dirA]'] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should report variables with values that dont match a directive as errors', () => { | 
					
						
							|  |  |  |           expect(() => parse('<div #a="dirA"></div>', [])).toThrowError(`Template parse errors:
 | 
					
						
							|  |  |  | There is no directive with "exportAs" set to "dirA" at TestComp > div:nth-child(0)[#a=dirA]`);
 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should allow variables with values that dont match a directive on embedded template elements', | 
					
						
							|  |  |  |            () => { | 
					
						
							|  |  |  |              expect(humanizeTemplateAsts(parse('<template #a="b"></template>', []))) | 
					
						
							|  |  |  |                  .toEqual([ | 
					
						
							|  |  |  |                    [EmbeddedTemplateAst, 'TestComp > template:nth-child(0)'], | 
					
						
							|  |  |  |                    [VariableAst, 'a', 'b', 'TestComp > template:nth-child(0)[#a=b]'] | 
					
						
							|  |  |  |                  ]); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should assign variables with empty value to components', () => { | 
					
						
							|  |  |  |           var dirA = CompileDirectiveMetadata.create({ | 
					
						
							|  |  |  |             selector: '[a]', | 
					
						
							|  |  |  |             isComponent: true, | 
					
						
							|  |  |  |             type: new CompileTypeMetadata({name: 'DirA'}), | 
					
						
							|  |  |  |             exportAs: 'dirA', template: new CompileTemplateMetadata({ngContentSelectors: []}) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div #a></div>', [dirA]))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							|  |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [VariableAst, 'a', '', 'TestComp > div:nth-child(0)[#a=]'], | 
					
						
							|  |  |  |                 [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [VariableAst, 'a', '', 'TestComp > div:nth-child(0)[#a=]'] | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       describe('explicit templates', () => { | 
					
						
							|  |  |  |         it('should create embedded templates for <template> elements', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<template></template>', []))) | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |               .toEqual([[EmbeddedTemplateAst, 'TestComp > template:nth-child(0)']]); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('inline templates', () => { | 
					
						
							|  |  |  |         it('should wrap the element into an EmbeddedTemplateAST', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div template>', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [EmbeddedTemplateAst, 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse bound properties', () => { | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |           expect(humanizeTemplateAsts(parse('<div template="ngIf test">', [ngIf]))) | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [EmbeddedTemplateAst, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [DirectiveAst, ngIf, 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                 [ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                   BoundDirectivePropertyAst, | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                   'ngIf', | 
					
						
							|  |  |  |                   'test', | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[template=ngIf test]' | 
					
						
							|  |  |  |                 ], | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse variables via #...', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div template="ngIf #a=b">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [EmbeddedTemplateAst, 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                 [VariableAst, 'a', 'b', 'TestComp > div:nth-child(0)[template=ngIf #a=b]'], | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse variables via var ...', () => { | 
					
						
							|  |  |  |           expect(humanizeTemplateAsts(parse('<div template="ngIf var a=b">', []))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [EmbeddedTemplateAst, 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                 [VariableAst, 'a', 'b', 'TestComp > div:nth-child(0)[template=ngIf var a=b]'], | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         describe('directives', () => { | 
					
						
							|  |  |  |           it('should locate directives in property bindings', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |             var dirA = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |               selector: '[a=b]', | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |               type: new CompileTypeMetadata({name: 'DirA'}), | 
					
						
							|  |  |  |               properties: ['a'] | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |             var dirB = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |                 {selector: '[b]', type: new CompileTypeMetadata({name: 'DirB'})}); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |             expect(humanizeTemplateAsts(parse('<div template="a b" b>', [dirA, dirB]))) | 
					
						
							|  |  |  |                 .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                   [EmbeddedTemplateAst, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                   [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                   [ | 
					
						
							|  |  |  |                     BoundDirectivePropertyAst, | 
					
						
							|  |  |  |                     'a', | 
					
						
							|  |  |  |                     'b', | 
					
						
							|  |  |  |                     'TestComp > div:nth-child(0)[template=a b]' | 
					
						
							|  |  |  |                   ], | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                   [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                   [AttrAst, 'b', '', 'TestComp > div:nth-child(0)[b=]'], | 
					
						
							|  |  |  |                   [DirectiveAst, dirB, 'TestComp > div:nth-child(0)'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                 ]); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           it('should locate directives in variable bindings', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |             var dirA = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |                 {selector: '[a=b]', type: new CompileTypeMetadata({name: 'DirA'})}); | 
					
						
							|  |  |  |             var dirB = CompileDirectiveMetadata.create( | 
					
						
							|  |  |  |                 {selector: '[b]', type: new CompileTypeMetadata({name: 'DirB'})}); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |             expect(humanizeTemplateAsts(parse('<div template="#a=b" b>', [dirA, dirB]))) | 
					
						
							|  |  |  |                 .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                   [EmbeddedTemplateAst, 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                   [VariableAst, 'a', 'b', 'TestComp > div:nth-child(0)[template=#a=b]'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                   [DirectiveAst, dirA, 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                   [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                   [AttrAst, 'b', '', 'TestComp > div:nth-child(0)[b=]'], | 
					
						
							|  |  |  |                   [DirectiveAst, dirB, 'TestComp > div:nth-child(0)'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |                 ]); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should work with *... and use the attribute name as property binding name', () => { | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |           expect(humanizeTemplateAsts(parse('<div *ng-if="test">', [ngIf]))) | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |                 [EmbeddedTemplateAst, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [DirectiveAst, ngIf, 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                 [ | 
					
						
							|  |  |  |                   BoundDirectivePropertyAst, | 
					
						
							|  |  |  |                   'ngIf', | 
					
						
							|  |  |  |                   'test', | 
					
						
							|  |  |  |                   'TestComp > div:nth-child(0)[*ng-if=test]' | 
					
						
							|  |  |  |                 ], | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |                 [ElementAst, 'div', 'TestComp > div:nth-child(0)'] | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |     describe('content projection', () => { | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  |       function createComp(selector: string, ngContentSelectors: string[]): | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           CompileDirectiveMetadata { | 
					
						
							|  |  |  |         return CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |           selector: selector, | 
					
						
							|  |  |  |           isComponent: true, | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           type: new CompileTypeMetadata({name: 'SomeComp'}), | 
					
						
							|  |  |  |           template: new CompileTemplateMetadata({ngContentSelectors: ngContentSelectors}) | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |         }) | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('project text nodes', () => { | 
					
						
							|  |  |  |         it('should project text nodes with wildcard selector', () => { | 
					
						
							|  |  |  |           expect(humanizeContentProjection(parse('<div>hello</div>', [createComp('div', ['*'])]))) | 
					
						
							|  |  |  |               .toEqual([['div', null], ['#text(hello)', 0]]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('project elements', () => { | 
					
						
							|  |  |  |         it('should project elements with wildcard selector', () => { | 
					
						
							|  |  |  |           expect(humanizeContentProjection( | 
					
						
							|  |  |  |                      parse('<div><span></span></div>', [createComp('div', ['*'])]))) | 
					
						
							|  |  |  |               .toEqual([['div', null], ['span', 0]]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should project elements with css selector', () => { | 
					
						
							|  |  |  |           expect(humanizeContentProjection( | 
					
						
							|  |  |  |                      parse('<div><a x></a><b></b></div>', [createComp('div', ['a[x]'])]))) | 
					
						
							|  |  |  |               .toEqual([['div', null], ['a', 0], ['b', null]]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('embedded templates', () => { | 
					
						
							|  |  |  |         it('should project embedded templates with wildcard selector', () => { | 
					
						
							|  |  |  |           expect(humanizeContentProjection( | 
					
						
							|  |  |  |                      parse('<div><template></template></div>', [createComp('div', ['*'])]))) | 
					
						
							|  |  |  |               .toEqual([['div', null], ['template', 0]]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should project embedded templates with css selector', () => { | 
					
						
							|  |  |  |           expect(humanizeContentProjection( | 
					
						
							|  |  |  |                      parse('<div><template x></template><template></template></div>', | 
					
						
							|  |  |  |                            [createComp('div', ['template[x]'])]))) | 
					
						
							|  |  |  |               .toEqual([['div', null], ['template', 0], ['template', null]]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('ng-content', () => { | 
					
						
							|  |  |  |         it('should project ng-content with wildcard selector', () => { | 
					
						
							|  |  |  |           expect(humanizeContentProjection( | 
					
						
							|  |  |  |                      parse('<div><ng-content></ng-content></div>', [createComp('div', ['*'])]))) | 
					
						
							|  |  |  |               .toEqual([['div', null], ['ng-content', 0]]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should project ng-content with css selector', () => { | 
					
						
							|  |  |  |           expect(humanizeContentProjection( | 
					
						
							|  |  |  |                      parse('<div><ng-content x></ng-content><ng-content></ng-content></div>', | 
					
						
							|  |  |  |                            [createComp('div', ['ng-content[x]'])]))) | 
					
						
							|  |  |  |               .toEqual([['div', null], ['ng-content', 0], ['ng-content', null]]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should project into the first matching ng-content', () => { | 
					
						
							|  |  |  |         expect(humanizeContentProjection( | 
					
						
							|  |  |  |                    parse('<div>hello<b></b><a></a></div>', [createComp('div', ['a', 'b', '*'])]))) | 
					
						
							|  |  |  |             .toEqual([['div', null], ['#text(hello)', 2], ['b', 1], ['a', 0]]); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should only project direct child nodes', () => { | 
					
						
							|  |  |  |         expect(humanizeContentProjection( | 
					
						
							|  |  |  |                    parse('<div><span><a></a></span><a></a></div>', [createComp('div', ['a'])]))) | 
					
						
							|  |  |  |             .toEqual([['div', null], ['span', null], ['a', null], ['a', 0]]); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should project nodes of nested components', () => { | 
					
						
							|  |  |  |         expect(humanizeContentProjection( | 
					
						
							|  |  |  |                    parse('<a><b>hello</b></a>', [createComp('a', ['*']), createComp('b', ['*'])]))) | 
					
						
							|  |  |  |             .toEqual([['a', null], ['b', 0], ['#text(hello)', 0]]); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |       it('should project children of components with ng-non-bindable', () => { | 
					
						
							|  |  |  |         expect(humanizeContentProjection(parse('<div ng-non-bindable>{{hello}}<span></span></div>', | 
					
						
							|  |  |  |                                                [createComp('div', ['*'])]))) | 
					
						
							|  |  |  |             .toEqual([['div', null], ['#text({{hello}})', 0], ['span', 0]]); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     describe('splitClasses', () => { | 
					
						
							|  |  |  |       it('should keep an empty class', () => { expect(splitClasses('a')).toEqual(['a']); }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should split 2 classes', () => { expect(splitClasses('a b')).toEqual(['a', 'b']); }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should trim classes', () => { expect(splitClasses(' a  b ')).toEqual(['a', 'b']); }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     describe('error cases', () => { | 
					
						
							|  |  |  |       it('should throw on invalid property names', () => { | 
					
						
							|  |  |  |         expect(() => parse('<div [invalid-prop]></div>', [])).toThrowError(`Template parse errors:
 | 
					
						
							|  |  |  | Can't bind to 'invalidProp' since it isn't a known native property in TestComp > div:nth-child(0)[[invalid-prop]=]`);
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should report errors in expressions', () => { | 
					
						
							| 
									
										
										
										
											2015-09-10 15:25:36 -07:00
										 |  |  |         expect(() => parse('<div [prop]="a b"></div>', [])).toThrowErrorWith(`Template parse errors:
 | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  | Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp > div:nth-child(0)[[prop]=a b]`);
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not throw on invalid property names if the property is used by a directive', | 
					
						
							|  |  |  |          () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |            var dirA = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |              selector: 'div', | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |              type: new CompileTypeMetadata({name: 'DirA'}), | 
					
						
							|  |  |  |              properties: ['invalidProp'] | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |            }); | 
					
						
							|  |  |  |            expect(() => parse('<div [invalid-prop]></div>', [dirA])).not.toThrow(); | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not allow more than 1 component per element', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |         var dirA = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |           selector: 'div', | 
					
						
							|  |  |  |           isComponent: true, | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           type: new CompileTypeMetadata({name: 'DirA'}), | 
					
						
							|  |  |  |           template: new CompileTemplateMetadata({ngContentSelectors: []}) | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |         var dirB = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |           selector: 'div', | 
					
						
							|  |  |  |           isComponent: true, | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           type: new CompileTypeMetadata({name: 'DirB'}), | 
					
						
							|  |  |  |           template: new CompileTemplateMetadata({ngContentSelectors: []}) | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |         expect(() => parse('<div>', [dirB, dirA])).toThrowError(`Template parse errors:
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  | More than one component: DirB,DirA in TestComp > div:nth-child(0)`);
 | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not allow components or element nor event bindings on explicit embedded templates', | 
					
						
							|  |  |  |          () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |            var dirA = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |              selector: '[a]', | 
					
						
							|  |  |  |              isComponent: true, | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |              type: new CompileTypeMetadata({name: 'DirA'}), | 
					
						
							|  |  |  |              template: new CompileTemplateMetadata({ngContentSelectors: []}) | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |            }); | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |            expect(() => parse('<template [a]="b" (e)="f"></template>', [dirA])) | 
					
						
							|  |  |  |                .toThrowError(`Template parse errors:
 | 
					
						
							|  |  |  | Components on an embedded template: DirA in TestComp > template:nth-child(0) | 
					
						
							|  |  |  | Property binding a not used by any directive on an embedded template in TestComp > template:nth-child(0)[[a]=b] | 
					
						
							|  |  |  | Event binding e on an embedded template in TestComp > template:nth-child(0)[(e)=f]`);
 | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not allow components or element bindings on inline embedded templates', () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |         var dirA = CompileDirectiveMetadata.create({ | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |           selector: '[a]', | 
					
						
							|  |  |  |           isComponent: true, | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |           type: new CompileTypeMetadata({name: 'DirA'}), | 
					
						
							|  |  |  |           template: new CompileTemplateMetadata({ngContentSelectors: []}) | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |         expect(() => parse('<div *a="b">', [dirA])).toThrowError(`Template parse errors:
 | 
					
						
							|  |  |  | Components on an embedded template: DirA in TestComp > div:nth-child(0) | 
					
						
							|  |  |  | Property binding a not used by any directive on an embedded template in TestComp > div:nth-child(0)[*a=b]`);
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     describe('ignore elements', () => { | 
					
						
							|  |  |  |       it('should ignore <script> elements but include them for source info', () => { | 
					
						
							|  |  |  |         expect(humanizeTemplateAsts(parse('<script></script>a', []))) | 
					
						
							|  |  |  |             .toEqual([[TextAst, 'a', 'TestComp > #text(a):nth-child(1)']]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ignore <style> elements but include them for source info', () => { | 
					
						
							|  |  |  |         expect(humanizeTemplateAsts(parse('<style></style>a', []))) | 
					
						
							|  |  |  |             .toEqual([[TextAst, 'a', 'TestComp > #text(a):nth-child(1)']]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ignore <link rel="stylesheet"> elements but include them for source info', () => { | 
					
						
							|  |  |  |         expect(humanizeTemplateAsts(parse('<link rel="stylesheet"></link>a', []))) | 
					
						
							|  |  |  |             .toEqual([[TextAst, 'a', 'TestComp > #text(a):nth-child(1)']]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |       it('should ignore bindings on children of elements with ng-non-bindable', () => { | 
					
						
							|  |  |  |         expect(humanizeTemplateAsts(parse('<div ng-non-bindable>{{b}}</div>', []))) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |               [AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'], | 
					
						
							|  |  |  |               [TextAst, '{{b}}', 'TestComp > div:nth-child(0) > #text({{b}}):nth-child(0)'] | 
					
						
							|  |  |  |             ]); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should keep nested children of elements with ng-non-bindable', () => { | 
					
						
							|  |  |  |         expect(humanizeTemplateAsts(parse('<div ng-non-bindable><span>{{b}}</span></div>', []))) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |               [AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'], | 
					
						
							|  |  |  |               [ElementAst, 'span', 'TestComp > div:nth-child(0) > span:nth-child(0)'], | 
					
						
							|  |  |  |               [ | 
					
						
							|  |  |  |                 TextAst, | 
					
						
							|  |  |  |                 '{{b}}', | 
					
						
							|  |  |  |                 'TestComp > div:nth-child(0) > span:nth-child(0) > #text({{b}}):nth-child(0)' | 
					
						
							|  |  |  |               ] | 
					
						
							|  |  |  |             ]); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ignore <script> elements inside of elements with ng-non-bindable but include them for source info', | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |          () => { | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |            expect(humanizeTemplateAsts(parse('<div ng-non-bindable><script></script>a</div>', []))) | 
					
						
							|  |  |  |                .toEqual([ | 
					
						
							|  |  |  |                  [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                  [AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'], | 
					
						
							|  |  |  |                  [TextAst, 'a', 'TestComp > div:nth-child(0) > #text(a):nth-child(1)'] | 
					
						
							|  |  |  |                ]); | 
					
						
							|  |  |  |          }); | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |       it('should ignore <style> elements inside of elements with ng-non-bindable but include them for source info', | 
					
						
							|  |  |  |          () => { | 
					
						
							|  |  |  |            expect(humanizeTemplateAsts(parse('<div ng-non-bindable><style></style>a</div>', []))) | 
					
						
							|  |  |  |                .toEqual([ | 
					
						
							|  |  |  |                  [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                  [AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'], | 
					
						
							|  |  |  |                  [TextAst, 'a', 'TestComp > div:nth-child(0) > #text(a):nth-child(1)'] | 
					
						
							|  |  |  |                ]); | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ignore <link rel="stylesheet"> elements inside of elements with ng-non-bindable but include them for source info', | 
					
						
							|  |  |  |          () => { | 
					
						
							|  |  |  |            expect(humanizeTemplateAsts( | 
					
						
							|  |  |  |                       parse('<div ng-non-bindable><link rel="stylesheet"></link>a</div>', []))) | 
					
						
							|  |  |  |                .toEqual([ | 
					
						
							|  |  |  |                  [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                  [AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'], | 
					
						
							|  |  |  |                  [TextAst, 'a', 'TestComp > div:nth-child(0) > #text(a):nth-child(1)'] | 
					
						
							|  |  |  |                ]); | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should convert <ng-content> elements into regular elements inside of elements with ng-non-bindable but include them for source info', | 
					
						
							|  |  |  |          () => { | 
					
						
							|  |  |  |            expect(humanizeTemplateAsts( | 
					
						
							|  |  |  |                       parse('<div ng-non-bindable><ng-content></ng-content>a</div>', []))) | 
					
						
							|  |  |  |                .toEqual([ | 
					
						
							|  |  |  |                  [ElementAst, 'div', 'TestComp > div:nth-child(0)'], | 
					
						
							|  |  |  |                  [AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'], | 
					
						
							|  |  |  |                  [ | 
					
						
							|  |  |  |                    ElementAst, | 
					
						
							|  |  |  |                    'ng-content', | 
					
						
							|  |  |  |                    'TestComp > div:nth-child(0) > ng-content:nth-child(0)' | 
					
						
							|  |  |  |                  ], | 
					
						
							|  |  |  |                  [TextAst, 'a', 'TestComp > div:nth-child(0) > #text(a):nth-child(1)'] | 
					
						
							|  |  |  |                ]); | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export function humanizeTemplateAsts(templateAsts: TemplateAst[]): any[] { | 
					
						
							|  |  |  |   var humanizer = new TemplateHumanizer(); | 
					
						
							|  |  |  |   templateVisitAll(humanizer, templateAsts); | 
					
						
							|  |  |  |   return humanizer.result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TemplateHumanizer implements TemplateAstVisitor { | 
					
						
							|  |  |  |   result: any[] = []; | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitNgContent(ast: NgContentAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |     this.result.push([NgContentAst, ast.sourceInfo]); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |     this.result.push([EmbeddedTemplateAst, ast.sourceInfo]); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     templateVisitAll(this, ast.attrs); | 
					
						
							|  |  |  |     templateVisitAll(this, ast.vars); | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |     templateVisitAll(this, ast.directives); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     templateVisitAll(this, ast.children); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitElement(ast: ElementAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  |     this.result.push([ElementAst, ast.name, ast.sourceInfo]); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     templateVisitAll(this, ast.attrs); | 
					
						
							|  |  |  |     templateVisitAll(this, ast.properties); | 
					
						
							|  |  |  |     templateVisitAll(this, ast.events); | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |     templateVisitAll(this, ast.exportAsVars); | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |     templateVisitAll(this, ast.directives); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     templateVisitAll(this, ast.children); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitVariable(ast: VariableAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     this.result.push([VariableAst, ast.name, ast.value, ast.sourceInfo]); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitEvent(ast: BoundEventAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |     this.result.push([ | 
					
						
							|  |  |  |       BoundEventAst, | 
					
						
							|  |  |  |       ast.name, | 
					
						
							|  |  |  |       ast.target, | 
					
						
							|  |  |  |       expressionUnparser.unparse(ast.handler), | 
					
						
							|  |  |  |       ast.sourceInfo | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitElementProperty(ast: BoundElementPropertyAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |     this.result.push([ | 
					
						
							|  |  |  |       BoundElementPropertyAst, | 
					
						
							|  |  |  |       ast.type, | 
					
						
							|  |  |  |       ast.name, | 
					
						
							|  |  |  |       expressionUnparser.unparse(ast.value), | 
					
						
							|  |  |  |       ast.unit, | 
					
						
							|  |  |  |       ast.sourceInfo | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitAttr(ast: AttrAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     this.result.push([AttrAst, ast.name, ast.value, ast.sourceInfo]); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitBoundText(ast: BoundTextAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     this.result.push([BoundTextAst, expressionUnparser.unparse(ast.value), ast.sourceInfo]); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitText(ast: TextAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     this.result.push([TextAst, ast.value, ast.sourceInfo]); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitDirective(ast: DirectiveAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |     this.result.push([DirectiveAst, ast.directive, ast.sourceInfo]); | 
					
						
							|  |  |  |     templateVisitAll(this, ast.properties); | 
					
						
							|  |  |  |     templateVisitAll(this, ast.hostProperties); | 
					
						
							|  |  |  |     templateVisitAll(this, ast.hostEvents); | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |     templateVisitAll(this, ast.exportAsVars); | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-09-01 16:24:23 -07:00
										 |  |  |   visitDirectiveProperty(ast: BoundDirectivePropertyAst, context: any): any { | 
					
						
							| 
									
										
										
										
											2015-08-27 16:29:02 -07:00
										 |  |  |     this.result.push([ | 
					
						
							|  |  |  |       BoundDirectivePropertyAst, | 
					
						
							|  |  |  |       ast.directiveName, | 
					
						
							|  |  |  |       expressionUnparser.unparse(ast.value), | 
					
						
							|  |  |  |       ast.sourceInfo | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-11 13:37:05 -07:00
										 |  |  | function humanizeContentProjection(templateAsts: TemplateAst[]): any[] { | 
					
						
							|  |  |  |   var humanizer = new TemplateContentProjectionHumanizer(); | 
					
						
							|  |  |  |   templateVisitAll(humanizer, templateAsts); | 
					
						
							|  |  |  |   return humanizer.result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TemplateContentProjectionHumanizer implements TemplateAstVisitor { | 
					
						
							|  |  |  |   result: any[] = []; | 
					
						
							|  |  |  |   visitNgContent(ast: NgContentAst, context: any): any { | 
					
						
							|  |  |  |     this.result.push(['ng-content', ast.ngContentIndex]); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any { | 
					
						
							|  |  |  |     this.result.push(['template', ast.ngContentIndex]); | 
					
						
							|  |  |  |     templateVisitAll(this, ast.children); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   visitElement(ast: ElementAst, context: any): any { | 
					
						
							|  |  |  |     this.result.push([ast.name, ast.ngContentIndex]); | 
					
						
							|  |  |  |     templateVisitAll(this, ast.children); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   visitVariable(ast: VariableAst, context: any): any { return null; } | 
					
						
							|  |  |  |   visitEvent(ast: BoundEventAst, context: any): any { return null; } | 
					
						
							|  |  |  |   visitElementProperty(ast: BoundElementPropertyAst, context: any): any { return null; } | 
					
						
							|  |  |  |   visitAttr(ast: AttrAst, context: any): any { return null; } | 
					
						
							|  |  |  |   visitBoundText(ast: BoundTextAst, context: any): any { | 
					
						
							|  |  |  |     this.result.push([`#text(${expressionUnparser.unparse(ast.value)})`, ast.ngContentIndex]); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   visitText(ast: TextAst, context: any): any { | 
					
						
							|  |  |  |     this.result.push([`#text(${ast.value})`, ast.ngContentIndex]); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   visitDirective(ast: DirectiveAst, context: any): any { return null; } | 
					
						
							|  |  |  |   visitDirectiveProperty(ast: BoundDirectivePropertyAst, context: any): any { return null; } | 
					
						
							|  |  |  | } |