refactor(core): throw more descriptive error message in case of invalid host element (#35916)

This commit replaces an assert with more descriptive error message that is thrown in case `<ng-template>` or `<ng-container>` is used as host element for a Component.

Resolves #35240.

PR Close #35916
This commit is contained in:
Andrew Kushnir
2020-03-06 11:57:29 -08:00
parent 7f93f7ef47
commit 335f3271d2
12 changed files with 95 additions and 28 deletions

View File

@ -11,7 +11,7 @@ import {ApplicationRef, Component, ComponentFactoryResolver, ComponentRef, Eleme
import {TestBed} from '@angular/core/testing';
import {ɵDomRendererFactory2 as DomRendererFactory2} from '@angular/platform-browser';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {onlyInIvy} from '@angular/private/testing';
import {ivyEnabled, onlyInIvy} from '@angular/private/testing';
import {domRendererFactory3} from '../../src/render3/interfaces/renderer';
@ -259,6 +259,65 @@ describe('component', () => {
expect(wrapperEls.length).toBe(2); // other elements are preserved
});
describe('invalid host element', () => {
it('should throw when <ng-container> is used as a host element for a Component', () => {
@Component({
selector: 'ng-container',
template: '...',
})
class Comp {
}
@Component({
selector: 'root',
template: '<ng-container></ng-container>',
})
class App {
}
TestBed.configureTestingModule({declarations: [App, Comp]});
if (ivyEnabled) {
expect(() => TestBed.createComponent(App))
.toThrowError(
/"ng-container" tags cannot be used as component hosts. Please use a different tag to activate the Comp component/);
} else {
// In VE there is no special check for the case when `<ng-container>` is used as a host
// element for a Component. VE tries to attach Component's content to a Comment node that
// represents the `<ng-container>` location and this call fails with a
// browser/environment-specific error message, so we just verify that this scenario is
// triggering an error in VE.
expect(() => TestBed.createComponent(App)).toThrow();
}
});
it('should throw when <ng-template> is used as a host element for a Component', () => {
@Component({
selector: 'ng-template',
template: '...',
})
class Comp {
}
@Component({
selector: 'root',
template: '<ng-template></ng-template>',
})
class App {
}
TestBed.configureTestingModule({declarations: [App, Comp]});
if (ivyEnabled) {
expect(() => TestBed.createComponent(App))
.toThrowError(
/"ng-template" tags cannot be used as component hosts. Please use a different tag to activate the Comp component/);
} else {
expect(() => TestBed.createComponent(App))
.toThrowError(
/Components on an embedded template: Comp \("\[ERROR ->\]<ng-template><\/ng-template>"\)/);
}
});
});
it('should use a new ngcontent attribute for child elements created w/ Renderer2', () => {
@Component({
selector: 'app-root',