refactor(ivy): check metadata presence before compiling Type in R3TestBed (#34204)

Prior to this commit, there was no check in R3TestBed to verify that metadata is resolved using a given Type. That leads to some cryptic error messages (when TestBed tries to compile a Type without having metadata) in case TestBed override functions receive unexpected Types (for example a Directive is used in `TestBed.overrideComponent` call). This commit adds the necessary checks to verify metadata presence before TestBed tries to (re)compile a Type.

PR Close #34204
This commit is contained in:
Andrew Kushnir
2019-12-02 21:51:19 -08:00
committed by Miško Hevery
parent 41ea3c214a
commit 668692598b
2 changed files with 49 additions and 10 deletions

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Compiler, Component, Directive, ErrorHandler, Inject, Injectable, InjectionToken, Injector, Input, ModuleWithProviders, NgModule, Optional, Pipe, ViewChild, ɵsetClassMetadata as setClassMetadata, ɵɵdefineComponent as defineComponent, ɵɵdefineNgModule as defineNgModule, ɵɵtext as text} from '@angular/core';
import {Compiler, Component, Directive, ErrorHandler, Inject, Injectable, InjectionToken, Injector, Input, ModuleWithProviders, NgModule, Optional, Pipe, Type, ViewChild, ɵsetClassMetadata as setClassMetadata, ɵɵdefineComponent as defineComponent, ɵɵdefineNgModule as defineNgModule, ɵɵtext as text} from '@angular/core';
import {TestBed, getTestBed} from '@angular/core/testing/src/test_bed';
import {By} from '@angular/platform-browser';
import {expect} from '@angular/platform-browser/testing/src/matchers';
@ -715,6 +715,36 @@ describe('TestBed', () => {
expect(fixture.nativeElement.innerHTML).toEqual('<outer><inner>Inner</inner></outer>');
});
onlyInIvy('Ivy-specific errors').describe('checking types before compiling them', () => {
@Directive({
selector: 'my-dir',
})
class MyDir {
}
@NgModule()
class MyModule {
}
// [decorator, type, overrideFn]
const cases: [string, Type<any>, string][] = [
['Component', MyDir, 'overrideComponent'],
['NgModule', MyDir, 'overrideModule'],
['Pipe', MyModule, 'overridePipe'],
['Directive', MyModule, 'overrideDirective'],
];
cases.forEach(([decorator, type, overrideFn]) => {
it(`should throw an error in case invalid type is used in ${overrideFn} function`, () => {
TestBed.configureTestingModule({declarations: [MyDir]});
expect(() => {
(TestBed as any)[overrideFn](type, {});
TestBed.createComponent(type);
}).toThrowError(new RegExp(`class doesn't have @${decorator} decorator`, 'g'));
});
});
});
onlyInIvy('TestBed should handle AOT pre-compiled Components')
.describe('AOT pre-compiled components', () => {
/**