diff --git a/packages/core/src/render3/metadata.ts b/packages/core/src/render3/metadata.ts
index bfa8e65a64..053d742845 100644
--- a/packages/core/src/render3/metadata.ts
+++ b/packages/core/src/render3/metadata.ts
@@ -28,7 +28,7 @@ export function setClassMetadata(
propDecorators: {[field: string]: any} | null): void {
const clazz = type as TypeWithMetadata;
if (decorators !== null) {
- if (clazz.decorators !== undefined) {
+ if (clazz.hasOwnProperty('decorators') && clazz.decorators !== undefined) {
clazz.decorators.push(...decorators);
} else {
clazz.decorators = decorators;
diff --git a/packages/core/test/test_bed_spec.ts b/packages/core/test/test_bed_spec.ts
index 0492ecd2c0..2b055bc58d 100644
--- a/packages/core/test/test_bed_spec.ts
+++ b/packages/core/test/test_bed_spec.ts
@@ -48,8 +48,21 @@ export class SimpleCmp {
export class WithRefsCmp {
}
+@Component({selector: 'inherited-cmp', template: 'inherited'})
+export class InheritedCmp extends SimpleCmp {
+}
+
+@Component({
+ selector: 'simple-app',
+ template: `
+ -
+ `
+})
+export class SimpleApp {
+}
+
@NgModule({
- declarations: [HelloWorld, SimpleCmp, WithRefsCmp],
+ declarations: [HelloWorld, SimpleCmp, WithRefsCmp, InheritedCmp, SimpleApp],
imports: [GreetingModule],
providers: [
{provide: NAME, useValue: 'World!'},
@@ -174,6 +187,13 @@ describe('TestBed', () => {
expect(hello.nativeElement).toHaveText('Hello injected World !');
});
+ it('should resolve components that are extended by other components', () => {
+ // SimpleApp uses SimpleCmp in its template, which is extended by InheritedCmp
+ const simpleApp = TestBed.createComponent(SimpleApp);
+ simpleApp.detectChanges();
+ expect(simpleApp.nativeElement).toHaveText('simple - inherited');
+ });
+
onlyInIvy('patched ng defs should be removed after resetting TestingModule')
.it('make sure we restore ng defs to their initial states', () => {
@Pipe({name: 'somePipe', pure: true})
diff --git a/packages/core/testing/src/resolvers.ts b/packages/core/testing/src/resolvers.ts
index 2a15dd7bc5..bacbe78273 100644
--- a/packages/core/testing/src/resolvers.ts
+++ b/packages/core/testing/src/resolvers.ts
@@ -37,7 +37,9 @@ abstract class OverrideResolver implements Resolver {
}
getAnnotation(type: Type): T|null {
- return reflection.annotations(type).find(a => a instanceof this.type) || null;
+ // We should always return the last match from filter(), or we may return superclass data by
+ // mistake.
+ return reflection.annotations(type).filter(a => a instanceof this.type).pop() || null;
}
resolve(type: Type): T|null {