',
[createComp('div', ['*'])])))
.toEqual([['div', null], ['#text({{hello}})', 0], ['span', 0]]);
});
});
describe('splitClasses', () => {
it('should keep an empty class', () => { expect(splitClasses('a')).toEqual(['a']); });
it('should split 2 classes', () => { expect(splitClasses('a b')).toEqual(['a', 'b']); });
it('should trim classes', () => { expect(splitClasses(' a b ')).toEqual(['a', 'b']); });
});
describe('error cases', () => {
it('should throw on invalid property names', () => {
expect(() => parse('', [])).toThrowError(`Template parse errors:
Can't bind to 'invalidProp' since it isn't a known native property in TestComp > div:nth-child(0)[[invalid-prop]=]`);
});
it('should report errors in expressions', () => {
expect(() => parse('', [])).toThrowErrorWith(`Template parse errors:
Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp > div:nth-child(0)[[prop]=a b]`);
});
it('should not throw on invalid property names if the property is used by a directive',
() => {
var dirA = CompileDirectiveMetadata.create({
selector: 'div',
type: new CompileTypeMetadata({name: 'DirA'}),
inputs: ['invalidProp']
});
expect(() => parse('', [dirA])).not.toThrow();
});
it('should not allow more than 1 component per element', () => {
var dirA = CompileDirectiveMetadata.create({
selector: 'div',
isComponent: true,
type: new CompileTypeMetadata({name: 'DirA'}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
});
var dirB = CompileDirectiveMetadata.create({
selector: 'div',
isComponent: true,
type: new CompileTypeMetadata({name: 'DirB'}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
});
expect(() => parse('
', [dirB, dirA])).toThrowError(`Template parse errors:
More than one component: DirB,DirA in TestComp > div:nth-child(0)`);
});
it('should not allow components or element bindings nor dom events on explicit embedded templates',
() => {
var dirA = CompileDirectiveMetadata.create({
selector: '[a]',
isComponent: true,
type: new CompileTypeMetadata({name: 'DirA'}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
});
expect(() => parse('', [dirA]))
.toThrowError(`Template parse errors:
Event binding e not emitted by any directive on an embedded template in TestComp > template:nth-child(0)
Components on an embedded template: DirA in TestComp > template:nth-child(0)
Property binding a not used by any directive on an embedded template in TestComp > template:nth-child(0)[[a]=b]`);
});
it('should not allow components or element bindings on inline embedded templates', () => {
var dirA = CompileDirectiveMetadata.create({
selector: '[a]',
isComponent: true,
type: new CompileTypeMetadata({name: 'DirA'}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
});
expect(() => parse('
', [dirA])).toThrowError(`Template parse errors:
Components on an embedded template: DirA in TestComp > div:nth-child(0)
Property binding a not used by any directive on an embedded template in TestComp > div:nth-child(0)[*a=b]`);
});
});
describe('ignore elements', () => {
it('should ignore a', [])))
.toEqual([[TextAst, 'a', 'TestComp > #text(a):nth-child(1)']]);
});
it('should ignore a', [])))
.toEqual([[TextAst, 'a', 'TestComp > #text(a):nth-child(1)']]);
});
describe('', () => {
it('should keep elements if they have an absolute non package: url',
() => {
expect(humanizeTemplateAsts(
parse('a', [])))
.toEqual([
[ElementAst, 'link', 'TestComp > link:nth-child(0)'],
[
AttrAst,
'href',
'http://someurl',
'TestComp > link:nth-child(0)[href=http://someurl]'
],
[AttrAst, 'rel', 'stylesheet', 'TestComp > link:nth-child(0)[rel=stylesheet]'],
[TextAst, 'a', 'TestComp > #text(a):nth-child(1)']
]);
});
it('should keep elements if they have no uri', () => {
expect(humanizeTemplateAsts(parse('a', [])))
.toEqual([
[ElementAst, 'link', 'TestComp > link:nth-child(0)'],
[AttrAst, 'rel', 'stylesheet', 'TestComp > link:nth-child(0)[rel=stylesheet]'],
[TextAst, 'a', 'TestComp > #text(a):nth-child(1)']
]);
});
it('should ignore elements if they have a relative uri', () => {
expect(
humanizeTemplateAsts(parse('a', [])))
.toEqual([[TextAst, 'a', 'TestComp > #text(a):nth-child(1)']]);
});
it('should ignore elements if they have a package: uri', () => {
expect(humanizeTemplateAsts(
parse('a', [])))
.toEqual([[TextAst, 'a', 'TestComp > #text(a):nth-child(1)']]);
});
});
it('should ignore bindings on children of elements with ng-non-bindable', () => {
expect(humanizeTemplateAsts(parse('
{{b}}
', [])))
.toEqual([
[ElementAst, 'div', 'TestComp > div:nth-child(0)'],
[AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'],
[TextAst, '{{b}}', 'TestComp > div:nth-child(0) > #text({{b}}):nth-child(0)']
]);
});
it('should keep nested children of elements with ng-non-bindable', () => {
expect(humanizeTemplateAsts(parse('
', [])))
.toEqual([
[ElementAst, 'div', 'TestComp > div:nth-child(0)'],
[AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'],
[TextAst, 'a', 'TestComp > div:nth-child(0) > #text(a):nth-child(1)']
]);
});
it('should ignore elements inside of elements with ng-non-bindable but include them for source info',
() => {
expect(humanizeTemplateAsts(
parse('
a
', [])))
.toEqual([
[ElementAst, 'div', 'TestComp > div:nth-child(0)'],
[AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'],
[TextAst, 'a', 'TestComp > div:nth-child(0) > #text(a):nth-child(1)']
]);
});
it('should convert elements into regular elements inside of elements with ng-non-bindable but include them for source info',
() => {
expect(humanizeTemplateAsts(
parse('