', [
createComp('div', ['*'])
]))).toEqual([['div', null], ['#text({{hello}})', 0], ['span', 0]]);
});
it('should match the element when there is an inline template', () => {
expect(humanizeContentProjection(parse('
',
[createComp('div', ['a', 'b']), ngIf])))
.toEqual([
['div', null],
['template', 1],
['a', null],
]);
});
});
it('should support other directives before the component', () => {
expect(humanizeContentProjection(parse('
hello
', [
createDir('div'), createComp('div', ['*'])
]))).toEqual([['div', null], ['#text(hello)', 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 report when ng-content has non WS content', () => {
expect(() => parse('content', []))
.toThrowError(
`Template parse errors:\n` +
` element cannot have content. ("[ERROR ->]content"): TestComp@0:0`);
});
it('should treat *attr on a template element as valid', () => {
expect(() => parse('', [])).not.toThrowError();
expect(() => parse('', [])).not.toThrowError();
});
it('should treat template attribute on a template element as valid', () => {
expect(() => parse('', [])).not.toThrowError();
expect(() => parse('', [])).not.toThrowError();
});
it('should report when multiple *attrs are used on the same element', () => {
expect(() => parse('
', [])).toThrowError(`Template parse errors:
Can't have multiple template bindings on one element. Use only one attribute named 'template' or prefixed with * ("
]*ngFor>"): TestComp@0:11`);
});
it('should report when mix of template and *attrs are used on the same element', () => {
expect(() => parse('', []))
.toThrowError(`Template parse errors:
Can't have multiple template bindings on one element. Use only one attribute named 'template' or prefixed with * ("]*ngFor>"): TestComp@0:22`);
});
it('should report invalid property names', () => {
expect(() => parse('', [])).toThrowError(`Template parse errors:
Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("
][invalidProp]>
"): TestComp@0:5`);
});
it('should report invalid host property names', () => {
const dirA =
CompileDirectiveMetadata
.create({
selector: 'div',
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'[invalidProp]': 'someProp'}
})
.toSummary();
expect(() => parse('', [dirA])).toThrowError(`Template parse errors:
Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("[ERROR ->]"): TestComp@0:0, Directive DirA`);
});
it('should report errors in expressions', () => {
expect(() => parse('', [])).toThrowError(`Template parse errors:
Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("
][prop]="a b">
"): TestComp@0:5`);
});
it('should not throw on invalid property names if the property is used by a directive',
() => {
const dirA =
CompileDirectiveMetadata
.create({
selector: 'div',
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['invalidProp']
})
.toSummary();
expect(() => parse('', [dirA])).not.toThrow();
});
it('should not allow more than 1 component per element', () => {
const dirA =
CompileDirectiveMetadata
.create({
selector: 'div',
isComponent: true,
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
})
.toSummary();
const dirB =
CompileDirectiveMetadata
.create({
selector: 'div',
isComponent: true,
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirB'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
})
.toSummary();
expect(() => parse('
', [dirB, dirA]))
.toThrowError(
`Template parse errors:\n` +
`More than one component matched on this element.\n` +
`Make sure that only one component's selector can match a given element.\n` +
`Conflicting components: DirB,DirA ("[ERROR ->]
"): TestComp@0:0`);
});
it('should not allow components or element bindings nor dom events on explicit embedded templates',
() => {
const dirA =
CompileDirectiveMetadata
.create({
selector: '[a]',
isComponent: true,
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
})
.toSummary();
expect(() => parse('', [dirA]))
.toThrowError(`Template parse errors:
Event binding e not emitted by any directive on an embedded template. Make sure that the event name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("](e)="f">"): TestComp@0:18
Components on an embedded template: DirA ("[ERROR ->]"): TestComp@0:0
Property binding a not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("[ERROR ->]"): TestComp@0:0`);
expect(() => parse('', [dirA]))
.toThrowError(`Template parse errors:
Event binding e not emitted by any directive on an embedded template. Make sure that the event name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("](e)="f">"): TestComp@0:21
Components on an embedded template: DirA ("[ERROR ->]"): TestComp@0:0
Property binding a not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("[ERROR ->]"): TestComp@0:0`);
});
it('should not allow components or element bindings on inline embedded templates', () => {
const dirA =
CompileDirectiveMetadata
.create({
selector: '[a]',
isComponent: true,
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
})
.toSummary();
expect(() => parse('', [dirA])).toThrowError(`Template parse errors:
Components on an embedded template: DirA ("[ERROR ->]"): TestComp@0:0
Property binding a not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("[ERROR ->]"): TestComp@0:0`);
});
});
describe('ignore elements', () => {
it('should ignore a', []))).toEqual([[TextAst, 'a']]);
});
it('should ignore a', []))).toEqual([[TextAst, 'a']]);
});
describe('', () => {
it('should keep elements if they have an absolute non package: url',
() => {
expect(humanizeTplAst(parse('a', [])))
.toEqual([
[ElementAst, 'link'], [AttrAst, 'rel', 'stylesheet'],
[AttrAst, 'href', 'http://someurl'], [TextAst, 'a']
]);
});
it('should keep elements if they have no uri', () => {
expect(humanizeTplAst(parse('a', [
]))).toEqual([[ElementAst, 'link'], [AttrAst, 'rel', 'stylesheet'], [TextAst, 'a']]);
expect(humanizeTplAst(parse('a', [
]))).toEqual([[ElementAst, 'link'], [AttrAst, 'REL', 'stylesheet'], [TextAst, 'a']]);
});
it('should ignore elements if they have a relative uri', () => {
expect(humanizeTplAst(parse('a', [
]))).toEqual([[TextAst, 'a']]);
expect(humanizeTplAst(parse('a', [
]))).toEqual([[TextAst, 'a']]);
});
it('should ignore elements if they have a package: uri', () => {
expect(humanizeTplAst(parse('a', [
]))).toEqual([[TextAst, 'a']]);
});
});
it('should ignore bindings on children of elements with ngNonBindable', () => {
expect(humanizeTplAst(parse('
{{b}}
', [
]))).toEqual([[ElementAst, 'div'], [AttrAst, 'ngNonBindable', ''], [TextAst, '{{b}}']]);
});
it('should keep nested children of elements with ngNonBindable', () => {
expect(humanizeTplAst(parse('
', [
]))).toEqual([[ElementAst, 'div'], [AttrAst, 'ngNonBindable', ''], [TextAst, 'a']]);
});
it('should ignore elements inside of elements with ngNonBindable',
() => {
expect(humanizeTplAst(parse('
a
', [
]))).toEqual([[ElementAst, 'div'], [AttrAst, 'ngNonBindable', ''], [TextAst, 'a']]);
});
it('should convert elements into regular elements inside of elements with ngNonBindable',
() => {
expect(humanizeTplAst(parse('