| 
									
										
										
										
											2016-06-23 09:47:54 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-27 17:12:25 -07:00
										 |  |  | import {beforeEach, describe, expect, it} from '../../../core/testing/testing_internal'; | 
					
						
							| 
									
										
										
										
											2016-08-01 12:19:09 -07:00
										 |  |  | import * as html from '../../src/ml_parser/ast'; | 
					
						
							|  |  |  | import {HtmlParser, ParseTreeResult, TreeError} from '../../src/ml_parser/html_parser'; | 
					
						
							|  |  |  | import {TokenType} from '../../src/ml_parser/lexer'; | 
					
						
							| 
									
										
										
										
											2016-07-21 11:41:25 -07:00
										 |  |  | import {ParseError} from '../../src/parse_util'; | 
					
						
							| 
									
										
										
										
											2016-06-09 14:53:03 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  | import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn} from './ast_spec_utils'; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export function main() { | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |   describe('HtmlParser', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let parser: HtmlParser; | 
					
						
							| 
									
										
										
										
											2016-06-22 17:25:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 14:31:35 -07:00
										 |  |  |     beforeEach(() => { parser = new HtmlParser(); }); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |     describe('parse', () => { | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |       describe('text nodes', () => { | 
					
						
							|  |  |  |         it('should parse root level text nodes', () => { | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('a', 'TestComp'))).toEqual([[html.Text, 'a', 0]]); | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse text nodes inside regular elements', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<div>a</div>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'div', 0], [html.Text, 'a', 1] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |         it('should parse text nodes inside template elements', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<template>a</template>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'template', 0], [html.Text, 'a', 1] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse CDATA', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<![CDATA[text]]>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Text, 'text', 0] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |       describe('elements', () => { | 
					
						
							|  |  |  |         it('should parse root level elements', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<div></div>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'div', 0] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse elements inside of regular elements', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<div><span></span></div>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'div', 0], [html.Element, 'span', 1] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should parse elements inside of template elements', () => { | 
					
						
							|  |  |  |           expect(humanizeDom(parser.parse('<template><span></span></template>', 'TestComp'))) | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |               .toEqual([[html.Element, 'template', 0], [html.Element, 'span', 1]]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should support void elements', () => { | 
					
						
							|  |  |  |           expect(humanizeDom(parser.parse('<link rel="author license" href="/about">', 'TestComp'))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |                 [html.Element, 'link', 0], | 
					
						
							|  |  |  |                 [html.Attribute, 'rel', 'author license'], | 
					
						
							|  |  |  |                 [html.Attribute, 'href', '/about'], | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 18:06:03 +01:00
										 |  |  |         it('should not error on void elements from HTML5 spec', | 
					
						
							|  |  |  |            () => {  // http://www.w3.org/TR/html-markup/syntax.html#syntax-elements without:
 | 
					
						
							|  |  |  |              // <base> - it can be present in head only
 | 
					
						
							|  |  |  |              // <meta> - it can be present in head only
 | 
					
						
							|  |  |  |              // <command> - obsolete
 | 
					
						
							|  |  |  |              // <keygen> - obsolete
 | 
					
						
							|  |  |  |              ['<map><area></map>', '<div><br></div>', '<colgroup><col></colgroup>', | 
					
						
							|  |  |  |               '<div><embed></div>', '<div><hr></div>', '<div><img></div>', '<div><input></div>', | 
					
						
							|  |  |  |               '<object><param>/<object>', '<audio><source></audio>', '<audio><track></audio>', | 
					
						
							|  |  |  |               '<p><wbr></p>', | 
					
						
							|  |  |  |              ].forEach((html) => { expect(parser.parse(html, 'TestComp').errors).toEqual([]); }); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-01 13:01:05 -08:00
										 |  |  |         it('should close void elements on text nodes', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<p>before<br>after</p>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'p', 0], | 
					
						
							|  |  |  |             [html.Text, 'before', 1], | 
					
						
							|  |  |  |             [html.Element, 'br', 1], | 
					
						
							|  |  |  |             [html.Text, 'after', 1], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-12-01 13:01:05 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         it('should support optional end tags', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<div><p>1<p>2</div>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'div', 0], | 
					
						
							|  |  |  |             [html.Element, 'p', 1], | 
					
						
							|  |  |  |             [html.Text, '1', 2], | 
					
						
							|  |  |  |             [html.Element, 'p', 1], | 
					
						
							|  |  |  |             [html.Text, '2', 2], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should support nested elements', () => { | 
					
						
							|  |  |  |           expect(humanizeDom(parser.parse('<ul><li><ul><li></li></ul></li></ul>', 'TestComp'))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |                 [html.Element, 'ul', 0], | 
					
						
							|  |  |  |                 [html.Element, 'li', 1], | 
					
						
							|  |  |  |                 [html.Element, 'ul', 2], | 
					
						
							|  |  |  |                 [html.Element, 'li', 3], | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should add the requiredParent', () => { | 
					
						
							| 
									
										
										
										
											2015-11-20 13:13:48 -08:00
										 |  |  |           expect( | 
					
						
							|  |  |  |               humanizeDom(parser.parse( | 
					
						
							|  |  |  |                   '<table><thead><tr head></tr></thead><tr noparent></tr><tbody><tr body></tr></tbody><tfoot><tr foot></tr></tfoot></table>', | 
					
						
							|  |  |  |                   'TestComp'))) | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |                 [html.Element, 'table', 0], | 
					
						
							|  |  |  |                 [html.Element, 'thead', 1], | 
					
						
							|  |  |  |                 [html.Element, 'tr', 2], | 
					
						
							|  |  |  |                 [html.Attribute, 'head', ''], | 
					
						
							|  |  |  |                 [html.Element, 'tbody', 1], | 
					
						
							|  |  |  |                 [html.Element, 'tr', 2], | 
					
						
							|  |  |  |                 [html.Attribute, 'noparent', ''], | 
					
						
							|  |  |  |                 [html.Element, 'tbody', 1], | 
					
						
							|  |  |  |                 [html.Element, 'tr', 2], | 
					
						
							|  |  |  |                 [html.Attribute, 'body', ''], | 
					
						
							|  |  |  |                 [html.Element, 'tfoot', 1], | 
					
						
							|  |  |  |                 [html.Element, 'tr', 2], | 
					
						
							|  |  |  |                 [html.Attribute, 'foot', ''], | 
					
						
							| 
									
										
										
										
											2016-06-15 09:37:33 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should append the required parent considering ng-container', () => { | 
					
						
							|  |  |  |           expect(humanizeDom(parser.parse( | 
					
						
							|  |  |  |                      '<table><ng-container><tr></tr></ng-container></table>', 'TestComp'))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |                 [html.Element, 'table', 0], | 
					
						
							|  |  |  |                 [html.Element, 'tbody', 1], | 
					
						
							|  |  |  |                 [html.Element, 'ng-container', 2], | 
					
						
							|  |  |  |                 [html.Element, 'tr', 3], | 
					
						
							| 
									
										
										
										
											2016-06-15 09:37:33 -07:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should special case ng-container when adding a required parent', () => { | 
					
						
							|  |  |  |           expect(humanizeDom(parser.parse( | 
					
						
							|  |  |  |                      '<table><thead><ng-container><tr></tr></ng-container></thead></table>', | 
					
						
							|  |  |  |                      'TestComp'))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |                 [html.Element, 'table', 0], | 
					
						
							|  |  |  |                 [html.Element, 'thead', 1], | 
					
						
							|  |  |  |                 [html.Element, 'ng-container', 2], | 
					
						
							|  |  |  |                 [html.Element, 'tr', 3], | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 09:41:01 -08:00
										 |  |  |         it('should not add the requiredParent when the parent is a template', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<template><tr></tr></template>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'template', 0], | 
					
						
							|  |  |  |             [html.Element, 'tr', 1], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-12-07 09:41:01 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-15 09:45:19 -07:00
										 |  |  |         // https://github.com/angular/angular/issues/5967
 | 
					
						
							|  |  |  |         it('should not add the requiredParent to a template root element', () => { | 
					
						
							|  |  |  |           expect(humanizeDom(parser.parse('<tr></tr>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'tr', 0], | 
					
						
							| 
									
										
										
										
											2016-06-15 09:45:19 -07:00
										 |  |  |           ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         it('should support explicit mamespace', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<myns:div></myns:div>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, ':myns:div', 0] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should support implicit mamespace', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<svg></svg>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, ':svg:svg', 0] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should propagate the namespace', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<myns:div><p></p></myns:div>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, ':myns:div', 0], | 
					
						
							|  |  |  |             [html.Element, ':myns:p', 1], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-23 16:02:19 -08:00
										 |  |  |         it('should match closing tags case sensitive', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const errors = parser.parse('<DiV><P></p></dIv>', 'TestComp').errors; | 
					
						
							| 
									
										
										
										
											2015-11-23 16:02:19 -08:00
										 |  |  |           expect(errors.length).toEqual(2); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeErrors(errors)).toEqual([ | 
					
						
							|  |  |  |             ['p', 'Unexpected closing tag "p"', '0:8'], | 
					
						
							|  |  |  |             ['dIv', 'Unexpected closing tag "dIv"', '0:12'], | 
					
						
							|  |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-12-03 16:10:20 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should support self closing void elements', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<input />', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'input', 0] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-12-03 16:10:20 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should support self closing foreign elements', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<math />', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, ':math:math', 0] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-12-03 16:10:20 -08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-12-05 00:15:18 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should ignore LF immediately after textarea, pre and listing', () => { | 
					
						
							|  |  |  |           expect(humanizeDom(parser.parse( | 
					
						
							|  |  |  |                      '<p>\n</p><textarea>\n</textarea><pre>\n\n</pre><listing>\n\n</listing>', | 
					
						
							|  |  |  |                      'TestComp'))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |                 [html.Element, 'p', 0], | 
					
						
							|  |  |  |                 [html.Text, '\n', 1], | 
					
						
							|  |  |  |                 [html.Element, 'textarea', 0], | 
					
						
							|  |  |  |                 [html.Element, 'pre', 0], | 
					
						
							|  |  |  |                 [html.Text, '\n', 1], | 
					
						
							|  |  |  |                 [html.Element, 'listing', 0], | 
					
						
							|  |  |  |                 [html.Text, '\n', 1], | 
					
						
							| 
									
										
										
										
											2015-12-05 00:15:18 -08:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |       describe('attributes', () => { | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         it('should parse attributes on regular elements case sensitive', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<div kEy="v" key2=v2></div>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'div', 0], | 
					
						
							|  |  |  |             [html.Attribute, 'kEy', 'v'], | 
					
						
							|  |  |  |             [html.Attribute, 'key2', 'v2'], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |         it('should parse attributes without values', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<div k></div>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'div', 0], | 
					
						
							|  |  |  |             [html.Attribute, 'k', ''], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:31:03 -08:00
										 |  |  |         it('should parse attributes on svg elements case sensitive', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<svg viewBox="0"></svg>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, ':svg:svg', 0], | 
					
						
							|  |  |  |             [html.Attribute, 'viewBox', '0'], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-10-14 18:04:38 +02:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |         it('should parse attributes on template elements', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<template k="v"></template>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'template', 0], | 
					
						
							|  |  |  |             [html.Attribute, 'k', 'v'], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-09-11 13:35:46 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-12 11:46:39 -07:00
										 |  |  |         it('should support namespace', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<svg:use xlink:href="Port" />', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, ':svg:use', 0], | 
					
						
							|  |  |  |             [html.Attribute, ':xlink:href', 'Port'], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('comments', () => { | 
					
						
							| 
									
										
										
										
											2016-03-06 20:21:20 -08:00
										 |  |  |         it('should preserve comments', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeDom(parser.parse('<!-- comment --><div></div>', 'TestComp'))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Comment, 'comment', 0], | 
					
						
							|  |  |  |             [html.Element, 'div', 0], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |       describe('expansion forms', () => { | 
					
						
							|  |  |  |         it('should parse out expansion forms', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const parsed = parser.parse( | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |               `<div>before{messages.length, plural, =0 {You have <b>no</b> messages} =1 {One {{message}}}}after</div>`, | 
					
						
							|  |  |  |               'TestComp', true); | 
					
						
							| 
									
										
										
										
											2016-04-12 11:46:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-09 14:53:03 -07:00
										 |  |  |           expect(humanizeDom(parsed)).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Element, 'div', 0], | 
					
						
							|  |  |  |             [html.Text, 'before', 1], | 
					
						
							|  |  |  |             [html.Expansion, 'messages.length', 'plural', 1], | 
					
						
							|  |  |  |             [html.ExpansionCase, '=0', 2], | 
					
						
							|  |  |  |             [html.ExpansionCase, '=1', 2], | 
					
						
							|  |  |  |             [html.Text, 'after', 1], | 
					
						
							| 
									
										
										
										
											2016-06-09 14:53:03 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const cases = (<any>parsed.rootNodes[0]).children[1].cases; | 
					
						
							| 
									
										
										
										
											2016-04-12 11:46:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |           expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([ | 
					
						
							|  |  |  |             [html.Text, 'You have ', 0], | 
					
						
							|  |  |  |             [html.Element, 'b', 0], | 
					
						
							|  |  |  |             [html.Text, 'no', 1], | 
					
						
							|  |  |  |             [html.Text, ' messages', 0], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2016-04-12 11:46:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |           expect(humanizeDom(new ParseTreeResult(cases[1].expression, [ | 
					
						
							|  |  |  |           ]))).toEqual([[html.Text, 'One {{message}}', 0]]); | 
					
						
							| 
									
										
										
										
											2016-04-12 11:46:39 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         it('should parse out nested expansion forms', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const parsed = parser.parse( | 
					
						
							| 
									
										
										
										
											2016-11-04 15:10:19 -07:00
										 |  |  |               `{messages.length, plural, =0 { {p.gender, select, male {m}} }}`, 'TestComp', true); | 
					
						
							| 
									
										
										
										
											2016-06-09 14:53:03 -07:00
										 |  |  |           expect(humanizeDom(parsed)).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Expansion, 'messages.length', 'plural', 0], | 
					
						
							|  |  |  |             [html.ExpansionCase, '=0', 1], | 
					
						
							| 
									
										
										
										
											2016-06-09 14:53:03 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2016-04-13 16:01:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const firstCase = (<any>parsed.rootNodes[0]).cases[0]; | 
					
						
							| 
									
										
										
										
											2016-04-13 16:01:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |           expect(humanizeDom(new ParseTreeResult(firstCase.expression, []))).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-11-04 15:10:19 -07:00
										 |  |  |             [html.Expansion, 'p.gender', 'select', 0], | 
					
						
							|  |  |  |             [html.ExpansionCase, 'male', 1], | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [html.Text, ' ', 0], | 
					
						
							| 
									
										
										
										
											2016-06-09 14:53:03 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2016-04-13 16:01:25 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         it('should error when expansion form is not closed', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const p = parser.parse(`{messages.length, plural, =0 {one}`, 'TestComp', true); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeErrors(p.errors)).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [null, 'Invalid ICU message. Missing \'}\'.', '0:34'] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2016-04-12 11:46:39 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         it('should error when expansion case is not closed', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const p = parser.parse(`{messages.length, plural, =0 {one`, 'TestComp', true); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeErrors(p.errors)).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [null, 'Invalid ICU message. Missing \'}\'.', '0:29'] | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2016-04-12 11:46:39 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         it('should error when invalid html in the case', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const p = parser.parse(`{messages.length, plural, =0 {<b/>}`, 'TestComp', true); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeErrors(p.errors)).toEqual([ | 
					
						
							|  |  |  |             ['b', 'Only void and foreign elements can be self closed "b"', '0:30'] | 
					
						
							|  |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2016-04-12 11:46:39 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |       describe('source spans', () => { | 
					
						
							|  |  |  |         it('should store the location', () => { | 
					
						
							|  |  |  |           expect(humanizeDomSourceSpans(parser.parse( | 
					
						
							|  |  |  |                      '<div [prop]="v1" (e)="do()" attr="v2" noValue>\na\n</div>', 'TestComp'))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |                 [html.Element, 'div', 0, '<div [prop]="v1" (e)="do()" attr="v2" noValue>'], | 
					
						
							|  |  |  |                 [html.Attribute, '[prop]', 'v1', '[prop]="v1"'], | 
					
						
							|  |  |  |                 [html.Attribute, '(e)', 'do()', '(e)="do()"'], | 
					
						
							|  |  |  |                 [html.Attribute, 'attr', 'v2', 'attr="v2"'], | 
					
						
							|  |  |  |                 [html.Attribute, 'noValue', '', 'noValue'], | 
					
						
							|  |  |  |                 [html.Text, '\na\n', 1, '\na\n'], | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-03-23 13:43:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should set the start and end source spans', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const node = <html.Element>parser.parse('<div>a</div>', 'TestComp').rootNodes[0]; | 
					
						
							| 
									
										
										
										
											2016-03-23 13:43:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |           expect(node.startSourceSpan.start.offset).toEqual(0); | 
					
						
							|  |  |  |           expect(node.startSourceSpan.end.offset).toEqual(5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(node.endSourceSpan.start.offset).toEqual(6); | 
					
						
							|  |  |  |           expect(node.endSourceSpan.end.offset).toEqual(12); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should support expansion form', () => { | 
					
						
							|  |  |  |           expect(humanizeDomSourceSpans( | 
					
						
							|  |  |  |                      parser.parse('<div>{count, plural, =0 {msg}}</div>', 'TestComp', true))) | 
					
						
							|  |  |  |               .toEqual([ | 
					
						
							|  |  |  |                 [html.Element, 'div', 0, '<div>'], | 
					
						
							|  |  |  |                 [html.Expansion, 'count', 'plural', 1, '{count, plural, =0 {msg}}'], | 
					
						
							|  |  |  |                 [html.ExpansionCase, '=0', 2, '=0 {msg}'], | 
					
						
							|  |  |  |               ]); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-10-07 13:53:29 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should not report a value span for an attribute without a value', () => { | 
					
						
							|  |  |  |           const ast = parser.parse('<div bar></div>', 'TestComp'); | 
					
						
							|  |  |  |           expect((ast.rootNodes[0] as html.Element).attrs[0].valueSpan).toBeUndefined(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should report a value span for an attibute with a value', () => { | 
					
						
							|  |  |  |           const ast = parser.parse('<div bar="12"></div>', 'TestComp'); | 
					
						
							|  |  |  |           const attr = (ast.rootNodes[0] as html.Element).attrs[0]; | 
					
						
							|  |  |  |           expect(attr.valueSpan.start.offset).toEqual(9); | 
					
						
							|  |  |  |           expect(attr.valueSpan.end.offset).toEqual(13); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-10 09:13:50 -07:00
										 |  |  |       describe('visitor', () => { | 
					
						
							|  |  |  |         it('should visit text nodes', () => { | 
					
						
							|  |  |  |           const result = humanizeDom(parser.parse('text', 'TestComp')); | 
					
						
							|  |  |  |           expect(result).toEqual([[html.Text, 'text', 0]]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should visit element nodes', () => { | 
					
						
							|  |  |  |           const result = humanizeDom(parser.parse('<div></div>', 'TestComp')); | 
					
						
							|  |  |  |           expect(result).toEqual([[html.Element, 'div', 0]]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should visit attribute nodes', () => { | 
					
						
							|  |  |  |           const result = humanizeDom(parser.parse('<div id="foo"></div>', 'TestComp')); | 
					
						
							|  |  |  |           expect(result).toContain([html.Attribute, 'id', 'foo']); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should visit all nodes', () => { | 
					
						
							|  |  |  |           const result = | 
					
						
							|  |  |  |               parser.parse('<div id="foo"><span id="bar">a</span><span>b</span></div>', 'TestComp'); | 
					
						
							|  |  |  |           const accumulator: html.Node[] = []; | 
					
						
							|  |  |  |           const visitor = new class { | 
					
						
							|  |  |  |             visit(node: html.Node, context: any) { accumulator.push(node); } | 
					
						
							|  |  |  |             visitElement(element: html.Element, context: any): any { | 
					
						
							|  |  |  |               html.visitAll(this, element.attrs); | 
					
						
							|  |  |  |               html.visitAll(this, element.children); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             visitAttribute(attribute: html.Attribute, context: any): any {} | 
					
						
							|  |  |  |             visitText(text: html.Text, context: any): any {} | 
					
						
							|  |  |  |             visitComment(comment: html.Comment, context: any): any {} | 
					
						
							|  |  |  |             visitExpansion(expansion: html.Expansion, context: any): any { | 
					
						
							|  |  |  |               html.visitAll(this, expansion.cases); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any {} | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           html.visitAll(visitor, result.rootNodes); | 
					
						
							|  |  |  |           expect(accumulator.map(n => n.constructor)).toEqual([ | 
					
						
							|  |  |  |             html.Element, html.Attribute, html.Element, html.Attribute, html.Text, html.Element, | 
					
						
							|  |  |  |             html.Text | 
					
						
							|  |  |  |           ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should skip typed visit if visit() returns a truthy value', () => { | 
					
						
							|  |  |  |           const visitor = new class { | 
					
						
							|  |  |  |             visit(node: html.Node, context: any) { return true; } | 
					
						
							|  |  |  |             visitElement(element: html.Element, context: any): any { throw Error('Unexpected'); } | 
					
						
							|  |  |  |             visitAttribute(attribute: html.Attribute, context: any): any { | 
					
						
							|  |  |  |               throw Error('Unexpected'); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             visitText(text: html.Text, context: any): any { throw Error('Unexpected'); } | 
					
						
							|  |  |  |             visitComment(comment: html.Comment, context: any): any { throw Error('Unexpected'); } | 
					
						
							|  |  |  |             visitExpansion(expansion: html.Expansion, context: any): any { | 
					
						
							|  |  |  |               throw Error('Unexpected'); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any { | 
					
						
							|  |  |  |               throw Error('Unexpected'); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |           const result = parser.parse('<div id="foo"></div><div id="bar"></div>', 'TestComp'); | 
					
						
							|  |  |  |           const traversal = html.visitAll(visitor, result.rootNodes); | 
					
						
							|  |  |  |           expect(traversal).toEqual([true, true]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |       describe('errors', () => { | 
					
						
							|  |  |  |         it('should report unexpected closing tags', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const errors = parser.parse('<div></p></div>', 'TestComp').errors; | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |           expect(errors.length).toEqual(1); | 
					
						
							|  |  |  |           expect(humanizeErrors(errors)).toEqual([['p', 'Unexpected closing tag "p"', '0:5']]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 19:49:17 +02:00
										 |  |  |         it('should report subsequent open tags without proper close tag', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const errors = parser.parse('<div</div>', 'TestComp').errors; | 
					
						
							| 
									
										
										
										
											2016-06-03 19:49:17 +02:00
										 |  |  |           expect(errors.length).toEqual(1); | 
					
						
							|  |  |  |           expect(humanizeErrors(errors)).toEqual([['div', 'Unexpected closing tag "div"', '0:4']]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-03 15:53:44 -08:00
										 |  |  |         it('should report closing tag for void elements', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const errors = parser.parse('<input></input>', 'TestComp').errors; | 
					
						
							| 
									
										
										
										
											2015-12-02 10:11:01 -08:00
										 |  |  |           expect(errors.length).toEqual(1); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeErrors(errors)).toEqual([ | 
					
						
							|  |  |  |             ['input', 'Void elements do not have end tags "input"', '0:7'] | 
					
						
							|  |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-12-02 10:11:01 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-03 16:10:20 -08:00
										 |  |  |         it('should report self closing html element', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const errors = parser.parse('<p />', 'TestComp').errors; | 
					
						
							| 
									
										
										
										
											2015-12-03 16:10:20 -08:00
										 |  |  |           expect(errors.length).toEqual(1); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeErrors(errors)).toEqual([ | 
					
						
							|  |  |  |             ['p', 'Only void and foreign elements can be self closed "p"', '0:0'] | 
					
						
							|  |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-12-03 16:10:20 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should report self closing custom element', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const errors = parser.parse('<my-cmp />', 'TestComp').errors; | 
					
						
							| 
									
										
										
										
											2015-12-03 16:10:20 -08:00
										 |  |  |           expect(errors.length).toEqual(1); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeErrors(errors)).toEqual([ | 
					
						
							|  |  |  |             ['my-cmp', 'Only void and foreign elements can be self closed "my-cmp"', '0:0'] | 
					
						
							|  |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-12-03 16:10:20 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         it('should also report lexer errors', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |           const errors = parser.parse('<!-err--><div></p></div>', 'TestComp').errors; | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |           expect(errors.length).toEqual(2); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           expect(humanizeErrors(errors)).toEqual([ | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |             [TokenType.COMMENT_START, 'Unexpected character "e"', '0:3'], | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |             ['p', 'Unexpected closing tag "p"', '0:14'] | 
					
						
							|  |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-23 13:43:28 -07:00
										 |  |  | export function humanizeErrors(errors: ParseError[]): any[] { | 
					
						
							| 
									
										
										
										
											2016-06-22 17:25:42 -07:00
										 |  |  |   return errors.map(e => { | 
					
						
							| 
									
										
										
										
											2016-07-21 13:56:58 -07:00
										 |  |  |     if (e instanceof TreeError) { | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |       // Parser errors
 | 
					
						
							| 
									
										
										
										
											2016-06-22 17:25:42 -07:00
										 |  |  |       return [<any>e.elementName, e.msg, humanizeLineColumn(e.span.start)]; | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     // Tokenizer errors
 | 
					
						
							| 
									
										
										
										
											2016-06-22 17:25:42 -07:00
										 |  |  |     return [(<any>e).tokenType, e.msg, humanizeLineColumn(e.span.start)]; | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-04-28 17:50:03 -07:00
										 |  |  | } |