| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							| 
									
										
										
										
											2020-05-19 12:08:49 -07:00
										 |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import {ParseSourceSpan} from '../../src/parse_util'; | 
					
						
							|  |  |  | import * as t from '../../src/render3/r3_ast'; | 
					
						
							|  |  |  | import {parseR3 as parse} from './view/util'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class R3AstSourceSpans implements t.Visitor<void> { | 
					
						
							|  |  |  |   result: any[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   visitElement(element: t.Element) { | 
					
						
							|  |  |  |     this.result.push([ | 
					
						
							|  |  |  |       'Element', humanizeSpan(element.sourceSpan), humanizeSpan(element.startSourceSpan), | 
					
						
							|  |  |  |       humanizeSpan(element.endSourceSpan) | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |     this.visitAll([ | 
					
						
							|  |  |  |       element.attributes, | 
					
						
							|  |  |  |       element.inputs, | 
					
						
							|  |  |  |       element.outputs, | 
					
						
							|  |  |  |       element.references, | 
					
						
							|  |  |  |       element.children, | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   visitTemplate(template: t.Template) { | 
					
						
							|  |  |  |     this.result.push([ | 
					
						
							|  |  |  |       'Template', humanizeSpan(template.sourceSpan), humanizeSpan(template.startSourceSpan), | 
					
						
							|  |  |  |       humanizeSpan(template.endSourceSpan) | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |     this.visitAll([ | 
					
						
							|  |  |  |       template.attributes, | 
					
						
							|  |  |  |       template.inputs, | 
					
						
							|  |  |  |       template.outputs, | 
					
						
							|  |  |  |       template.templateAttrs, | 
					
						
							|  |  |  |       template.references, | 
					
						
							|  |  |  |       template.variables, | 
					
						
							|  |  |  |       template.children, | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   visitContent(content: t.Content) { | 
					
						
							|  |  |  |     this.result.push(['Content', humanizeSpan(content.sourceSpan)]); | 
					
						
							|  |  |  |     t.visitAll(this, content.attributes); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   visitVariable(variable: t.Variable) { | 
					
						
							| 
									
										
										
										
											2020-09-23 16:28:36 -07:00
										 |  |  |     this.result.push([ | 
					
						
							|  |  |  |       'Variable', | 
					
						
							|  |  |  |       humanizeSpan(variable.sourceSpan), | 
					
						
							|  |  |  |       humanizeSpan(variable.keySpan), | 
					
						
							|  |  |  |       humanizeSpan(variable.valueSpan), | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   visitReference(reference: t.Reference) { | 
					
						
							| 
									
										
										
										
											2020-11-09 13:35:48 -08:00
										 |  |  |     this.result.push([ | 
					
						
							|  |  |  |       'Reference', humanizeSpan(reference.sourceSpan), humanizeSpan(reference.keySpan), | 
					
						
							|  |  |  |       humanizeSpan(reference.valueSpan) | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   visitTextAttribute(attribute: t.TextAttribute) { | 
					
						
							| 
									
										
										
										
											2020-11-09 10:25:25 -08:00
										 |  |  |     this.result.push([ | 
					
						
							|  |  |  |       'TextAttribute', humanizeSpan(attribute.sourceSpan), humanizeSpan(attribute.keySpan), | 
					
						
							|  |  |  |       humanizeSpan(attribute.valueSpan) | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   visitBoundAttribute(attribute: t.BoundAttribute) { | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |     this.result.push([ | 
					
						
							|  |  |  |       'BoundAttribute', humanizeSpan(attribute.sourceSpan), humanizeSpan(attribute.keySpan), | 
					
						
							|  |  |  |       humanizeSpan(attribute.valueSpan) | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   visitBoundEvent(event: t.BoundEvent) { | 
					
						
							| 
									
										
										
										
											2020-11-09 09:16:19 -08:00
										 |  |  |     this.result.push([ | 
					
						
							|  |  |  |       'BoundEvent', humanizeSpan(event.sourceSpan), humanizeSpan(event.keySpan), | 
					
						
							|  |  |  |       humanizeSpan(event.handlerSpan) | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |   visitText(text: t.Text) { | 
					
						
							|  |  |  |     this.result.push(['Text', humanizeSpan(text.sourceSpan)]); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   visitBoundText(text: t.BoundText) { | 
					
						
							|  |  |  |     this.result.push(['BoundText', humanizeSpan(text.sourceSpan)]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |   visitIcu(icu: t.Icu) { | 
					
						
							| 
									
										
										
										
											2020-10-01 00:17:21 +02:00
										 |  |  |     this.result.push(['Icu', humanizeSpan(icu.sourceSpan)]); | 
					
						
							|  |  |  |     for (const key of Object.keys(icu.vars)) { | 
					
						
							|  |  |  |       this.result.push(['Icu:Var', humanizeSpan(icu.vars[key].sourceSpan)]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (const key of Object.keys(icu.placeholders)) { | 
					
						
							|  |  |  |       this.result.push(['Icu:Placeholder', humanizeSpan(icu.placeholders[key].sourceSpan)]); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |   private visitAll(nodes: t.Node[][]) { | 
					
						
							|  |  |  |     nodes.forEach(node => t.visitAll(this, node)); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  | function humanizeSpan(span: ParseSourceSpan|null|undefined): string { | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |   if (span === null || span === undefined) { | 
					
						
							|  |  |  |     return `<empty>`; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |   return span.toString(); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function expectFromHtml(html: string) { | 
					
						
							|  |  |  |   const res = parse(html); | 
					
						
							|  |  |  |   return expectFromR3Nodes(res.nodes); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function expectFromR3Nodes(nodes: t.Node[]) { | 
					
						
							|  |  |  |   const humanizer = new R3AstSourceSpans(); | 
					
						
							|  |  |  |   t.visitAll(humanizer, nodes); | 
					
						
							|  |  |  |   return expect(humanizer.result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe('R3 AST source spans', () => { | 
					
						
							|  |  |  |   describe('nodes without binding', () => { | 
					
						
							|  |  |  |     it('is correct for text nodes', () => { | 
					
						
							|  |  |  |       expectFromHtml('a').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Text', 'a'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for elements with attributes', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div a="b"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div a="b"></div>', '<div a="b">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 10:25:25 -08:00
										 |  |  |         ['TextAttribute', 'a="b"', 'a', 'b'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for elements with attributes without value', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div a></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div a></div>', '<div a>', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 10:25:25 -08:00
										 |  |  |         ['TextAttribute', 'a', 'a', '<empty>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('bound text nodes', () => { | 
					
						
							|  |  |  |     it('is correct for bound text nodes', () => { | 
					
						
							|  |  |  |       expectFromHtml('{{a}}').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['BoundText', '{{a}}'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('bound attributes', () => { | 
					
						
							|  |  |  |     it('is correct for bound properties', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div [someProp]="v"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div [someProp]="v"></div>', '<div [someProp]="v">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |         ['BoundAttribute', '[someProp]="v"', 'someProp', 'v'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for bound properties without value', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div [someProp]></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div [someProp]></div>', '<div [someProp]>', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |         ['BoundAttribute', '[someProp]', 'someProp', '<empty>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for bound properties via bind- ', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div bind-prop="v"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div bind-prop="v"></div>', '<div bind-prop="v">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |         ['BoundAttribute', 'bind-prop="v"', 'prop', 'v'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for bound properties via {{...}}', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div prop="{{v}}"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div prop="{{v}}"></div>', '<div prop="{{v}}">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |         ['BoundAttribute', 'prop="{{v}}"', 'prop', '{{v}}'], | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for bound properties via data-', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div data-prop="{{v}}"></div>').toEqual([ | 
					
						
							|  |  |  |         ['Element', '<div data-prop="{{v}}"></div>', '<div data-prop="{{v}}">', '</div>'], | 
					
						
							|  |  |  |         ['BoundAttribute', 'data-prop="{{v}}"', 'prop', '{{v}}'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('templates', () => { | 
					
						
							|  |  |  |     it('is correct for * directives', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div *ngIf></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Template', '<div *ngIf></div>', '<div *ngIf>', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 10:25:25 -08:00
										 |  |  |         ['TextAttribute', 'ngIf', 'ngIf', '<empty>'], | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div *ngIf></div>', '<div *ngIf>', '</div>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for <ng-template>', () => { | 
					
						
							|  |  |  |       expectFromHtml('<ng-template></ng-template>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Template', '<ng-template></ng-template>', '<ng-template>', '</ng-template>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for reference via #...', () => { | 
					
						
							|  |  |  |       expectFromHtml('<ng-template #a></ng-template>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Template', '<ng-template #a></ng-template>', '<ng-template #a>', '</ng-template>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 13:35:48 -08:00
										 |  |  |         ['Reference', '#a', 'a', '<empty>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for reference with name', () => { | 
					
						
							|  |  |  |       expectFromHtml('<ng-template #a="b"></ng-template>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         [ | 
					
						
							|  |  |  |           'Template', '<ng-template #a="b"></ng-template>', '<ng-template #a="b">', '</ng-template>' | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2020-11-09 13:35:48 -08:00
										 |  |  |         ['Reference', '#a="b"', 'a', 'b'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for reference via ref-...', () => { | 
					
						
							|  |  |  |       expectFromHtml('<ng-template ref-a></ng-template>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Template', '<ng-template ref-a></ng-template>', '<ng-template ref-a>', '</ng-template>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 13:35:48 -08:00
										 |  |  |         ['Reference', 'ref-a', 'a', '<empty>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |     it('is correct for reference via data-ref-...', () => { | 
					
						
							|  |  |  |       expectFromHtml('<ng-template data-ref-a></ng-template>').toEqual([ | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |           'Template', '<ng-template data-ref-a></ng-template>', '<ng-template data-ref-a>', | 
					
						
							|  |  |  |           '</ng-template>' | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2020-11-09 13:35:48 -08:00
										 |  |  |         ['Reference', 'data-ref-a', 'a', '<empty>'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |     it('is correct for variables via let-...', () => { | 
					
						
							|  |  |  |       expectFromHtml('<ng-template let-a="b"></ng-template>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         [ | 
					
						
							|  |  |  |           'Template', '<ng-template let-a="b"></ng-template>', '<ng-template let-a="b">', | 
					
						
							|  |  |  |           '</ng-template>' | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2020-09-23 16:28:36 -07:00
										 |  |  |         ['Variable', 'let-a="b"', 'a', 'b'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |     it('is correct for variables via data-let-...', () => { | 
					
						
							|  |  |  |       expectFromHtml('<ng-template data-let-a="b"></ng-template>').toEqual([ | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |           'Template', '<ng-template data-let-a="b"></ng-template>', '<ng-template data-let-a="b">', | 
					
						
							|  |  |  |           '</ng-template>' | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2020-09-23 16:28:36 -07:00
										 |  |  |         ['Variable', 'data-let-a="b"', 'a', 'b'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |     it('is correct for attributes', () => { | 
					
						
							|  |  |  |       expectFromHtml('<ng-template k1="v1"></ng-template>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         [ | 
					
						
							|  |  |  |           'Template', '<ng-template k1="v1"></ng-template>', '<ng-template k1="v1">', | 
					
						
							|  |  |  |           '</ng-template>' | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2020-11-09 10:25:25 -08:00
										 |  |  |         ['TextAttribute', 'k1="v1"', 'k1', 'v1'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for bound attributes', () => { | 
					
						
							|  |  |  |       expectFromHtml('<ng-template [k1]="v1"></ng-template>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         [ | 
					
						
							|  |  |  |           'Template', '<ng-template [k1]="v1"></ng-template>', '<ng-template [k1]="v1">', | 
					
						
							|  |  |  |           '</ng-template>' | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |         ['BoundAttribute', '[k1]="v1"', 'k1', 'v1'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // TODO(joost): improve spans of nodes extracted from macrosyntax
 | 
					
						
							|  |  |  |   describe('inline templates', () => { | 
					
						
							|  |  |  |     it('is correct for attribute and bound attributes', () => { | 
					
						
							| 
									
										
										
										
											2020-02-25 12:23:03 -08:00
										 |  |  |       // Desugared form is
 | 
					
						
							|  |  |  |       // <ng-template ngFor [ngForOf]="items" let-item>
 | 
					
						
							|  |  |  |       //   <div></div>
 | 
					
						
							|  |  |  |       // </ng-template>
 | 
					
						
							|  |  |  |       expectFromHtml('<div *ngFor="let item of items"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         [ | 
					
						
							|  |  |  |           'Template', '<div *ngFor="let item of items"></div>', '<div *ngFor="let item of items">', | 
					
						
							|  |  |  |           '</div>' | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2020-11-09 10:25:25 -08:00
										 |  |  |         ['TextAttribute', 'ngFor', 'ngFor', '<empty>'], | 
					
						
							| 
									
										
										
										
											2020-09-28 21:23:34 -07:00
										 |  |  |         ['BoundAttribute', 'of items', 'of', 'items'], | 
					
						
							| 
									
										
										
										
											2020-09-23 16:28:36 -07:00
										 |  |  |         ['Variable', 'let item ', 'item', '<empty>'], | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         [ | 
					
						
							|  |  |  |           'Element', '<div *ngFor="let item of items"></div>', '<div *ngFor="let item of items">', | 
					
						
							|  |  |  |           '</div>' | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2020-02-25 12:23:03 -08:00
										 |  |  |       ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Note that this test exercises an *incorrect* usage of the ngFor
 | 
					
						
							|  |  |  |       // directive. There is a missing 'let' in the beginning of the expression
 | 
					
						
							|  |  |  |       // which causes the template to be desugared into
 | 
					
						
							|  |  |  |       // <ng-template [ngFor]="item" [ngForOf]="items">
 | 
					
						
							|  |  |  |       //   <div></div>
 | 
					
						
							|  |  |  |       // </ng-template>
 | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       expectFromHtml('<div *ngFor="item of items"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         [ | 
					
						
							|  |  |  |           'Template', '<div *ngFor="item of items"></div>', '<div *ngFor="item of items">', '</div>' | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2020-09-28 21:23:34 -07:00
										 |  |  |         ['BoundAttribute', 'ngFor="item ', 'ngFor', 'item'], | 
					
						
							|  |  |  |         ['BoundAttribute', 'of items', 'of', 'items'], | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div *ngFor="item of items"></div>', '<div *ngFor="item of items">', '</div>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       expectFromHtml('<div *ngFor="let item of items; trackBy: trackByFn"></div>').toEqual([ | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |           'Template', '<div *ngFor="let item of items; trackBy: trackByFn"></div>', | 
					
						
							|  |  |  |           '<div *ngFor="let item of items; trackBy: trackByFn">', '</div>' | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2020-11-09 10:25:25 -08:00
										 |  |  |         ['TextAttribute', 'ngFor', 'ngFor', '<empty>'], | 
					
						
							| 
									
										
										
										
											2020-09-28 21:23:34 -07:00
										 |  |  |         ['BoundAttribute', 'of items; ', 'of', 'items'], | 
					
						
							|  |  |  |         ['BoundAttribute', 'trackBy: trackByFn', 'trackBy', 'trackByFn'], | 
					
						
							| 
									
										
										
										
											2020-09-23 16:28:36 -07:00
										 |  |  |         ['Variable', 'let item ', 'item', '<empty>'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |         [ | 
					
						
							|  |  |  |           'Element', '<div *ngFor="let item of items; trackBy: trackByFn"></div>', | 
					
						
							|  |  |  |           '<div *ngFor="let item of items; trackBy: trackByFn">', '</div>' | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       ]); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for variables via let ...', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div *ngIf="let a=b"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Template', '<div *ngIf="let a=b"></div>', '<div *ngIf="let a=b">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 10:25:25 -08:00
										 |  |  |         ['TextAttribute', 'ngIf', 'ngIf', '<empty>'], | 
					
						
							| 
									
										
										
										
											2020-09-23 16:28:36 -07:00
										 |  |  |         ['Variable', 'let a=b', 'a', 'b'], | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div *ngIf="let a=b"></div>', '<div *ngIf="let a=b">', '</div>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for variables via as ...', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div *ngIf="expr as local"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Template', '<div *ngIf="expr as local"></div>', '<div *ngIf="expr as local">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-09-28 21:23:34 -07:00
										 |  |  |         ['BoundAttribute', 'ngIf="expr ', 'ngIf', 'expr'], | 
					
						
							| 
									
										
										
										
											2020-09-23 16:28:36 -07:00
										 |  |  |         ['Variable', 'ngIf="expr as local', 'local', 'ngIf'], | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div *ngIf="expr as local"></div>', '<div *ngIf="expr as local">', '</div>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('events', () => { | 
					
						
							|  |  |  |     it('is correct for event names case sensitive', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div (someEvent)="v"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div (someEvent)="v"></div>', '<div (someEvent)="v">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 09:16:19 -08:00
										 |  |  |         ['BoundEvent', '(someEvent)="v"', 'someEvent', 'v'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for bound events via on-', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div on-event="v"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div on-event="v"></div>', '<div on-event="v">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 09:16:19 -08:00
										 |  |  |         ['BoundEvent', 'on-event="v"', 'event', 'v'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |     it('is correct for bound events via data-on-', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div data-on-event="v"></div>').toEqual([ | 
					
						
							|  |  |  |         ['Element', '<div data-on-event="v"></div>', '<div data-on-event="v">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 09:16:19 -08:00
										 |  |  |         ['BoundEvent', 'data-on-event="v"', 'event', 'v'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |     it('is correct for bound events and properties via [(...)]', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div [(prop)]="v"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div [(prop)]="v"></div>', '<div [(prop)]="v">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |         ['BoundAttribute', '[(prop)]="v"', 'prop', 'v'], | 
					
						
							| 
									
										
										
										
											2020-11-09 09:16:19 -08:00
										 |  |  |         ['BoundEvent', '[(prop)]="v"', 'prop', 'v'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for bound events and properties via bindon-', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div bindon-prop="v"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div bindon-prop="v"></div>', '<div bindon-prop="v">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |         ['BoundAttribute', 'bindon-prop="v"', 'prop', 'v'], | 
					
						
							| 
									
										
										
										
											2020-11-09 09:16:19 -08:00
										 |  |  |         ['BoundEvent', 'bindon-prop="v"', 'prop', 'v'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for bound events and properties via data-bindon-', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div data-bindon-prop="v"></div>').toEqual([ | 
					
						
							|  |  |  |         ['Element', '<div data-bindon-prop="v"></div>', '<div data-bindon-prop="v">', '</div>'], | 
					
						
							|  |  |  |         ['BoundAttribute', 'data-bindon-prop="v"', 'prop', 'v'], | 
					
						
							| 
									
										
										
										
											2020-11-09 09:16:19 -08:00
										 |  |  |         ['BoundEvent', 'data-bindon-prop="v"', 'prop', 'v'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('references', () => { | 
					
						
							|  |  |  |     it('is correct for references via #...', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div #a></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div #a></div>', '<div #a>', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 13:35:48 -08:00
										 |  |  |         ['Reference', '#a', 'a', '<empty>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for references with name', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div #a="b"></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div #a="b"></div>', '<div #a="b">', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 13:35:48 -08:00
										 |  |  |         ['Reference', '#a="b"', 'a', 'b'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for references via ref-', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div ref-a></div>').toEqual([ | 
					
						
							| 
									
										
										
										
											2020-09-18 12:11:00 -07:00
										 |  |  |         ['Element', '<div ref-a></div>', '<div ref-a>', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 13:35:48 -08:00
										 |  |  |         ['Reference', 'ref-a', 'a', '<empty>'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for references via data-ref-', () => { | 
					
						
							|  |  |  |       expectFromHtml('<div ref-a></div>').toEqual([ | 
					
						
							|  |  |  |         ['Element', '<div ref-a></div>', '<div ref-a>', '</div>'], | 
					
						
							| 
									
										
										
										
											2020-11-09 13:35:48 -08:00
										 |  |  |         ['Reference', 'ref-a', 'a', '<empty>'], | 
					
						
							| 
									
										
										
										
											2020-09-17 13:01:32 -07:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-10-01 00:17:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('ICU expressions', () => { | 
					
						
							|  |  |  |     it('is correct for variables and placeholders', () => { | 
					
						
							|  |  |  |       expectFromHtml('<span i18n>{item.var, plural, other { {{item.placeholder}} items } }</span>') | 
					
						
							|  |  |  |           .toEqual([ | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |               'Element', | 
					
						
							|  |  |  |               '<span i18n>{item.var, plural, other { {{item.placeholder}} items } }</span>', | 
					
						
							|  |  |  |               '<span i18n>', '</span>' | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             ['Icu', '{item.var, plural, other { {{item.placeholder}} items } }'], | 
					
						
							|  |  |  |             ['Icu:Var', 'item.var'], | 
					
						
							|  |  |  |             ['Icu:Placeholder', '{{item.placeholder}}'], | 
					
						
							|  |  |  |           ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('is correct for nested ICUs', () => { | 
					
						
							|  |  |  |       expectFromHtml( | 
					
						
							|  |  |  |           '<span i18n>{item.var, plural, other { {{item.placeholder}} {nestedVar, plural, other { {{nestedPlaceholder}} }}} }</span>') | 
					
						
							|  |  |  |           .toEqual([ | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |               'Element', | 
					
						
							|  |  |  |               '<span i18n>{item.var, plural, other { {{item.placeholder}} {nestedVar, plural, other { {{nestedPlaceholder}} }}} }</span>', | 
					
						
							|  |  |  |               '<span i18n>', '</span>' | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |               'Icu', | 
					
						
							|  |  |  |               '{item.var, plural, other { {{item.placeholder}} {nestedVar, plural, other { {{nestedPlaceholder}} }}} }' | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             ['Icu:Var', 'nestedVar'], | 
					
						
							|  |  |  |             ['Icu:Var', 'item.var'], | 
					
						
							|  |  |  |             ['Icu:Placeholder', '{{item.placeholder}}'], | 
					
						
							|  |  |  |             ['Icu:Placeholder', '{{nestedPlaceholder}}'], | 
					
						
							|  |  |  |           ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:41:17 +02:00
										 |  |  | }); |