2016-06-23 12:47:54 -04:00
|
|
|
/**
|
|
|
|
* @license
|
2020-05-19 15:08:49 -04:00
|
|
|
* Copyright Google LLC All Rights Reserved.
|
2016-06-23 12:47:54 -04: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
|
|
|
|
*/
|
|
|
|
|
2016-08-01 15:19:09 -04:00
|
|
|
import * as html from '../../src/ml_parser/ast';
|
|
|
|
import {HtmlParser} from '../../src/ml_parser/html_parser';
|
2020-04-08 13:14:18 -04:00
|
|
|
import {expandNodes, ExpansionResult} from '../../src/ml_parser/icu_ast_expander';
|
2016-07-21 14:41:25 -04:00
|
|
|
import {ParseError} from '../../src/parse_util';
|
2016-06-30 17:59:23 -04:00
|
|
|
|
2016-07-21 16:56:58 -04:00
|
|
|
import {humanizeNodes} from './ast_spec_utils';
|
2016-06-17 14:38:24 -04:00
|
|
|
|
2017-12-16 17:42:55 -05:00
|
|
|
{
|
2016-06-17 14:38:24 -04:00
|
|
|
describe('Expander', () => {
|
|
|
|
function expand(template: string): ExpansionResult {
|
2016-06-24 17:31:35 -04:00
|
|
|
const htmlParser = new HtmlParser();
|
2019-02-08 17:10:19 -05:00
|
|
|
const res = htmlParser.parse(template, 'url', {tokenizeExpansionForms: true});
|
2016-06-17 14:38:24 -04:00
|
|
|
return expandNodes(res.rootNodes);
|
|
|
|
}
|
|
|
|
|
|
|
|
it('should handle the plural expansion form', () => {
|
|
|
|
const res = expand(`{messages.length, plural,=0 {zero<b>bold</b>}}`);
|
|
|
|
|
|
|
|
expect(humanizeNodes(res.nodes)).toEqual([
|
2016-07-21 16:56:58 -04:00
|
|
|
[html.Element, 'ng-container', 0],
|
|
|
|
[html.Attribute, '[ngPlural]', 'messages.length'],
|
2017-01-09 16:16:46 -05:00
|
|
|
[html.Element, 'ng-template', 1],
|
2016-07-21 16:56:58 -04:00
|
|
|
[html.Attribute, 'ngPluralCase', '=0'],
|
|
|
|
[html.Text, 'zero', 2],
|
|
|
|
[html.Element, 'b', 2],
|
|
|
|
[html.Text, 'bold', 3],
|
2016-06-17 14:38:24 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle nested expansion forms', () => {
|
2018-01-22 15:23:10 -05:00
|
|
|
const res = expand(`{messages.length, plural, =0 { {p.gender, select, male {m}} }}`);
|
2016-06-17 14:38:24 -04:00
|
|
|
|
|
|
|
expect(humanizeNodes(res.nodes)).toEqual([
|
2016-07-21 16:56:58 -04:00
|
|
|
[html.Element, 'ng-container', 0],
|
|
|
|
[html.Attribute, '[ngPlural]', 'messages.length'],
|
2017-01-09 16:16:46 -05:00
|
|
|
[html.Element, 'ng-template', 1],
|
2016-07-21 16:56:58 -04:00
|
|
|
[html.Attribute, 'ngPluralCase', '=0'],
|
|
|
|
[html.Element, 'ng-container', 2],
|
|
|
|
[html.Attribute, '[ngSwitch]', 'p.gender'],
|
2017-01-09 16:16:46 -05:00
|
|
|
[html.Element, 'ng-template', 3],
|
2018-01-22 15:23:10 -05:00
|
|
|
[html.Attribute, 'ngSwitchCase', 'male'],
|
2016-07-21 16:56:58 -04:00
|
|
|
[html.Text, 'm', 4],
|
|
|
|
[html.Text, ' ', 2],
|
2016-06-17 14:38:24 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should correctly set source code positions', () => {
|
|
|
|
const nodes = expand(`{messages.length, plural,=0 {<b>bold</b>}}`).nodes;
|
|
|
|
|
2016-07-21 16:56:58 -04:00
|
|
|
const container: html.Element = <html.Element>nodes[0];
|
2020-08-26 07:21:29 -04:00
|
|
|
expect(container.sourceSpan.start.col).toEqual(0);
|
|
|
|
expect(container.sourceSpan.end.col).toEqual(42);
|
|
|
|
expect(container.startSourceSpan.start.col).toEqual(0);
|
|
|
|
expect(container.startSourceSpan.end.col).toEqual(42);
|
2020-04-08 13:14:18 -04:00
|
|
|
expect(container.endSourceSpan!.start.col).toEqual(0);
|
|
|
|
expect(container.endSourceSpan!.end.col).toEqual(42);
|
2016-06-17 14:38:24 -04:00
|
|
|
|
|
|
|
const switchExp = container.attrs[0];
|
|
|
|
expect(switchExp.sourceSpan.start.col).toEqual(1);
|
|
|
|
expect(switchExp.sourceSpan.end.col).toEqual(16);
|
|
|
|
|
2016-07-21 16:56:58 -04:00
|
|
|
const template: html.Element = <html.Element>container.children[0];
|
2020-08-26 07:21:29 -04:00
|
|
|
expect(template.sourceSpan.start.col).toEqual(25);
|
|
|
|
expect(template.sourceSpan.end.col).toEqual(41);
|
2016-06-17 14:38:24 -04:00
|
|
|
|
|
|
|
const switchCheck = template.attrs[0];
|
|
|
|
expect(switchCheck.sourceSpan.start.col).toEqual(25);
|
|
|
|
expect(switchCheck.sourceSpan.end.col).toEqual(28);
|
|
|
|
|
2016-07-21 16:56:58 -04:00
|
|
|
const b: html.Element = <html.Element>template.children[0];
|
2020-08-26 07:21:29 -04:00
|
|
|
expect(b.sourceSpan.start.col).toEqual(29);
|
2020-04-08 13:14:18 -04:00
|
|
|
expect(b.endSourceSpan!.end.col).toEqual(40);
|
2016-06-17 14:38:24 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle other special forms', () => {
|
2016-11-04 17:52:02 -04:00
|
|
|
const res = expand(`{person.gender, select, male {m} other {default}}`);
|
2016-06-17 14:38:24 -04:00
|
|
|
|
|
|
|
expect(humanizeNodes(res.nodes)).toEqual([
|
2016-07-21 16:56:58 -04:00
|
|
|
[html.Element, 'ng-container', 0],
|
|
|
|
[html.Attribute, '[ngSwitch]', 'person.gender'],
|
2017-01-09 16:16:46 -05:00
|
|
|
[html.Element, 'ng-template', 1],
|
2016-11-04 17:52:02 -04:00
|
|
|
[html.Attribute, 'ngSwitchCase', 'male'],
|
2016-07-21 16:56:58 -04:00
|
|
|
[html.Text, 'm', 2],
|
2017-01-09 16:16:46 -05:00
|
|
|
[html.Element, 'ng-template', 1],
|
2016-11-04 17:52:02 -04:00
|
|
|
[html.Attribute, 'ngSwitchDefault', ''],
|
|
|
|
[html.Text, 'default', 2],
|
2016-06-17 14:38:24 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
2016-12-16 18:33:16 -05:00
|
|
|
it('should parse an expansion form as a tag single child', () => {
|
|
|
|
const res = expand(`<div><span>{a, b, =4 {c}}</span></div>`);
|
|
|
|
|
|
|
|
expect(humanizeNodes(res.nodes)).toEqual([
|
|
|
|
[html.Element, 'div', 0],
|
|
|
|
[html.Element, 'span', 1],
|
|
|
|
[html.Element, 'ng-container', 2],
|
|
|
|
[html.Attribute, '[ngSwitch]', 'a'],
|
2017-01-09 16:16:46 -05:00
|
|
|
[html.Element, 'ng-template', 3],
|
2016-12-16 18:33:16 -05:00
|
|
|
[html.Attribute, 'ngSwitchCase', '=4'],
|
|
|
|
[html.Text, 'c', 4],
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
2016-06-17 14:38:24 -04:00
|
|
|
describe('errors', () => {
|
|
|
|
it('should error on unknown plural cases', () => {
|
|
|
|
expect(humanizeErrors(expand('{n, plural, unknown {-}}').errors)).toEqual([
|
|
|
|
`Plural cases should be "=<number>" or one of zero, one, two, few, many, other`,
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function humanizeErrors(errors: ParseError[]): string[] {
|
|
|
|
return errors.map(error => error.msg);
|
|
|
|
}
|