fix(ivy): ensure TestBed restores fields to the most original value (#32823)

PR Close #32823
This commit is contained in:
Andrew Scott 2019-09-23 16:15:11 -07:00 committed by Andrew Kushnir
parent a54adcaff0
commit c8be987b40
2 changed files with 34 additions and 4 deletions

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Component, Directive, ErrorHandler, Inject, Injectable, InjectionToken, Input, ModuleWithProviders, NgModule, Optional, Pipe, ɵsetClassMetadata as setClassMetadata, ɵɵdefineComponent as defineComponent, ɵɵdefineNgModule as defineNgModule, ɵɵtext as text} from '@angular/core';
import {Compiler, Component, Directive, ErrorHandler, Inject, Injectable, InjectionToken, Input, ModuleWithProviders, NgModule, Optional, Pipe, ɵ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';
@ -699,5 +699,35 @@ describe('TestBed', () => {
// no trace of the overridden providers.
expect((Module as any).ngInjectorDef.providers).toEqual([Token]);
});
it('should clean up overridden providers on components whose modules are compiled more than once',
async() => {
@Injectable()
class SomeInjectable {
id: string|undefined;
}
@Component({providers: [SomeInjectable]})
class ComponentWithProvider {
constructor(readonly injectable: SomeInjectable) {}
}
@NgModule({declarations: [ComponentWithProvider]})
class MyModule {
}
TestBed.configureTestingModule({imports: [MyModule]});
const originalResolver =
(ComponentWithProvider as any).ngComponentDef.providersResolver;
TestBed.overrideProvider(SomeInjectable, {useValue: {id: 'fake'}});
const compiler = TestBed.inject(Compiler);
await compiler.compileModuleAsync(MyModule);
compiler.compileModuleSync(MyModule);
TestBed.resetTestingModule();
expect((ComponentWithProvider as any).ngComponentDef.providersResolver)
.toEqual(originalResolver);
});
});
});

View File

@ -513,9 +513,9 @@ export class R3TestBedCompiler {
}
restoreOriginalState(): void {
for (const op of this.defCleanupOps) {
op.def[op.field] = op.original;
}
// Process cleanup ops in reverse order so the field's original value is restored correctly (in
// case there were multiple overrides for the same field).
forEachRight(this.defCleanupOps, (op: CleanupOperation) => { op.def[op.field] = op.original; });
// Restore initial component/directive/pipe defs
this.initialNgDefs.forEach(
(value: [string, PropertyDescriptor | undefined], type: Type<any>) => {