import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib'; import {Parser, Lexer} from 'angular2/src/core/change_detection/change_detection'; import {TemplateParser, splitClasses} from 'angular2/src/compiler/template_parser'; import {HtmlParser} from 'angular2/src/compiler/html_parser'; import {DirectiveMetadata, ComponentMetadata, TypeMeta} from 'angular2/src/compiler/api'; import { templateVisitAll, TemplateAstVisitor, TemplateAst, NgContentAst, EmbeddedTemplateAst, ElementAst, VariableAst, BoundEventAst, BoundPropertyAst, AttrAst, BoundTextAst, TextAst } from 'angular2/src/compiler/template_ast'; import {Unparser} from '../core/change_detection/parser/unparser'; var expressionUnparser = new Unparser(); export function main() { describe('TemplateParser', () => { var domParser: HtmlParser; var parser: TemplateParser; beforeEach(() => { domParser = new HtmlParser(); parser = new TemplateParser(new Parser(new Lexer())); }); function parse(template: string, directives: DirectiveMetadata[]): TemplateAst[] { return parser.parse(domParser.parse(template, 'TestComp'), directives); } 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('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [AttrAst, 'a', 'b', 'TestComp > div:nth-child(0)[a=b]'] ]); }); }); it('should parse ngContent', () => { var parsed = parse('', []); expect(humanizeTemplateAsts(parsed)) .toEqual([[NgContentAst, 'a', 'TestComp > ng-content:nth-child(0)']]); }); it('should parse bound text nodes', () => { expect(humanizeTemplateAsts(parse('{{a}}', []))) .toEqual([[BoundTextAst, '{{ a }}', 'TestComp > #text({{a}}):nth-child(0)']]); }); describe('property, event and variable bindings', () => { it('should parse bound properties via [...] and not report them as attributes', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [BoundPropertyAst, 'prop', 'v', 'TestComp > div:nth-child(0)[[prop]=v]'] ]); }); it('should camel case bound properties', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [BoundPropertyAst, 'someProp', 'v', 'TestComp > div:nth-child(0)[[some-prop]=v]'] ]); }); it('should parse bound properties via bind- and not report them as attributes', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [BoundPropertyAst, 'prop', 'v', 'TestComp > div:nth-child(0)[bind-prop=v]'] ]); }); it('should parse bound properties via {{...}} and not report them as attributes', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [BoundPropertyAst, 'prop', '{{ v }}', 'TestComp > div:nth-child(0)[prop={{v}}]'] ]); }); it('should parse bound events via (...) and not report them as attributes', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [BoundEventAst, 'event', 'v', 'TestComp > div:nth-child(0)[(event)=v]'] ]); }); it('should camel case event names', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [BoundEventAst, 'someEvent', 'v', 'TestComp > div:nth-child(0)[(some-event)=v]'] ]); }); it('should parse bound events via on- and not report them as attributes', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [BoundEventAst, 'event', 'v', 'TestComp > div:nth-child(0)[on-event=v]'] ]); }); it('should parse bound events and properties via [(...)] and not report them as attributes', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [BoundPropertyAst, 'prop', 'v', 'TestComp > div:nth-child(0)[[(prop)]=v]'], [ BoundEventAst, 'prop', '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('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [BoundPropertyAst, 'prop', 'v', 'TestComp > div:nth-child(0)[bindon-prop=v]'], [ BoundEventAst, 'prop', 'v = $event', 'TestComp > div:nth-child(0)[bindon-prop=v]' ] ]); }); it('should parse variables via #... and not report them as attributes', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [VariableAst, 'a', 'b', 'TestComp > div:nth-child(0)[#a=b]'] ]); }); it('should parse variables via var-... and not report them as attributes', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [VariableAst, 'a', 'b', 'TestComp > div:nth-child(0)[var-a=b]'] ]); }); it('should camel case variables', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [VariableAst, 'someA', 'b', 'TestComp > div:nth-child(0)[var-some-a=b]'] ]); }); it('should use $implicit as variable name if none was specified', () => { expect(humanizeTemplateAsts(parse('
', []))) .toEqual([ [ElementAst, [], 'TestComp > div:nth-child(0)'], [VariableAst, 'a', '$implicit', 'TestComp > div:nth-child(0)[var-a=]'] ]); }); }); describe('directives', () => { it('should locate directives ordered by typeName and components first', () => { var dirA = new DirectiveMetadata({selector: '[a=b]', type: new TypeMeta({typeName: 'DirA'})}); var dirB = new DirectiveMetadata({selector: '[a]', type: new TypeMeta({typeName: 'DirB'})}); var comp = new ComponentMetadata({selector: 'div', type: new TypeMeta({typeName: 'ZComp'})}); expect(humanizeTemplateAsts(parse('
', [dirB, dirA, comp]))) .toEqual([ [ElementAst, [comp, dirA, dirB], 'TestComp > div:nth-child(0)'], [AttrAst, 'a', 'b', 'TestComp > div:nth-child(0)[a=b]'] ]); }); it('should locate directives in property bindings', () => { var dirA = new DirectiveMetadata({selector: '[a=b]', type: new TypeMeta({typeName: 'DirA'})}); var dirB = new DirectiveMetadata({selector: '[b]', type: new TypeMeta({typeName: 'DirB'})}); expect(humanizeTemplateAsts(parse('
', [dirA, dirB]))) .toEqual([ [ElementAst, [dirA], 'TestComp > div:nth-child(0)'], [BoundPropertyAst, 'a', 'b', 'TestComp > div:nth-child(0)[[a]=b]'] ]); }); it('should locate directives in variable bindings', () => { var dirA = new DirectiveMetadata({selector: '[a=b]', type: new TypeMeta({typeName: 'DirA'})}); var dirB = new DirectiveMetadata({selector: '[b]', type: new TypeMeta({typeName: 'DirB'})}); expect(humanizeTemplateAsts(parse('
', [dirA, dirB]))) .toEqual([ [ElementAst, [dirA], 'TestComp > div:nth-child(0)'], [VariableAst, 'a', 'b', 'TestComp > div:nth-child(0)[#a=b]'] ]); }); }); describe('explicit templates', () => { it('should create embedded templates for