fix(testing): override metadata subclasses properly (#10767)

This fixes an issue where `TestBed.overrideComponent(MyComp, {})`
would remove some properties including `providers` from the component.

This was due to the override not properly dealing with getter fields
on subclasses.
This commit is contained in:
Julie Ralph 2016-08-12 17:39:33 -07:00 committed by vikerman
parent 9317056138
commit 87fe47737a
2 changed files with 46 additions and 7 deletions

View File

@ -15,6 +15,10 @@ interface SomeMetadataType {
arrayProp?: any[];
}
interface OtherMetadataType extends SomeMetadataType {
otherPlainProp?: string;
}
class SomeMetadata implements SomeMetadataType {
plainProp: string;
private _getterProp: string;
@ -28,6 +32,20 @@ class SomeMetadata implements SomeMetadataType {
}
}
class OtherMetadata extends SomeMetadata implements OtherMetadataType {
otherPlainProp: string;
constructor(options: OtherMetadataType) {
super({
plainProp: options.plainProp,
getterProp: options.getterProp,
arrayProp: options.arrayProp
});
this.otherPlainProp = options.otherPlainProp;
}
}
export function main() {
describe('metadata overrider', () => {
let overrider: MetadataOverrider;
@ -112,5 +130,23 @@ export function main() {
});
});
describe('subclasses', () => {
it('should set individual properties and keep others', () => {
const oldInstance = new OtherMetadata({
plainProp: 'somePlainProp',
getterProp: 'someGetterProp',
otherPlainProp: 'newOtherProp'
});
const newInstance = overrider.overrideMetadata(
OtherMetadata, oldInstance, {set: {plainProp: 'newPlainProp'}});
expect(newInstance).toEqual(new OtherMetadata({
plainProp: 'newPlainProp',
getterProp: 'someGetterProp',
otherPlainProp: 'newOtherProp'
}));
});
});
});
}

View File

@ -118,13 +118,16 @@ function _valueProps(obj: any): string[] {
props.push(prop);
}
});
// getters
const proto = Object.getPrototypeOf(obj);
Object.keys(proto).forEach((protoProp) => {
var desc = Object.getOwnPropertyDescriptor(proto, protoProp);
if (!protoProp.startsWith('_') && desc && 'get' in desc) {
props.push(protoProp);
}
});
let proto = obj;
while (proto = Object.getPrototypeOf(proto)) {
Object.keys(proto).forEach((protoProp) => {
var desc = Object.getOwnPropertyDescriptor(proto, protoProp);
if (!protoProp.startsWith('_') && desc && 'get' in desc) {
props.push(protoProp);
}
});
}
return props;
}