fix(ivy): ensure multi providers in ModuleWithProviders are not duplicated (#34914)
The current logic pulls multiproviders up to the parent module's provider list. The result is that the multi provider being defined both in the imported ModuleWithProviders and the parent and getting an extra item in the multi provided array of values. This PR fixes that problem by not pulling providers in ModuleWithProviders up to the parent module. PR Close #34914
This commit is contained in:
parent
b608fa55f0
commit
4a5467bac6
|
@ -345,13 +345,19 @@ describe('TestBed', () => {
|
|||
describe('multi providers', () => {
|
||||
const multiToken = new InjectionToken<string[]>('multiToken');
|
||||
const singleToken = new InjectionToken<string>('singleToken');
|
||||
const multiTokenToOverrideAtModuleLevel =
|
||||
new InjectionToken<string[]>('moduleLevelMultiOverride');
|
||||
@NgModule({providers: [{provide: multiToken, useValue: 'valueFromModule', multi: true}]})
|
||||
class MyModule {
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
{provide: singleToken, useValue: 't1'},
|
||||
{provide: singleToken, useValue: 't1'}, {
|
||||
provide: multiTokenToOverrideAtModuleLevel,
|
||||
useValue: 'multiTokenToOverrideAtModuleLevelOriginal',
|
||||
multi: true
|
||||
},
|
||||
{provide: multiToken, useValue: 'valueFromModule2', multi: true},
|
||||
{provide: multiToken, useValue: 'secondValueFromModule2', multi: true}
|
||||
]
|
||||
|
@ -361,14 +367,23 @@ describe('TestBed', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MyModule, MyModule2],
|
||||
imports: [
|
||||
MyModule, {
|
||||
ngModule: MyModule2,
|
||||
providers:
|
||||
[{provide: multiTokenToOverrideAtModuleLevel, useValue: 'override', multi: true}]
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('is preserved when other provider is overridden', () => {
|
||||
TestBed.overrideProvider(singleToken, {useValue: ''});
|
||||
const value = TestBed.inject(multiToken);
|
||||
expect(value.length).toEqual(3);
|
||||
expect(TestBed.inject(multiToken).length).toEqual(3);
|
||||
expect(TestBed.inject(multiTokenToOverrideAtModuleLevel).length).toEqual(2);
|
||||
expect(TestBed.inject(multiTokenToOverrideAtModuleLevel)).toEqual([
|
||||
'multiTokenToOverrideAtModuleLevelOriginal', 'override'
|
||||
]);
|
||||
});
|
||||
|
||||
it('overridden with an array', () => {
|
||||
|
|
|
@ -394,15 +394,8 @@ export class R3TestBedCompiler {
|
|||
|
||||
const injectorDef: any = (moduleType as any)[NG_INJ_DEF];
|
||||
if (this.providerOverridesByToken.size > 0) {
|
||||
// Extract the list of providers from ModuleWithProviders, so we can define the final list of
|
||||
// providers that might have overrides.
|
||||
// Note: second `flatten` operation is needed to convert an array of providers
|
||||
// (e.g. `[[], []]`) into one flat list, also eliminating empty arrays.
|
||||
const providersFromModules = flatten(flatten(
|
||||
injectorDef.imports, (imported: NgModuleType<any>| ModuleWithProviders<any>) =>
|
||||
isModuleWithProviders(imported) ? imported.providers : []));
|
||||
const providers = [
|
||||
...providersFromModules, ...injectorDef.providers,
|
||||
...injectorDef.providers,
|
||||
...(this.providerOverridesByModule.get(moduleType as InjectorType<any>) || [])
|
||||
];
|
||||
if (this.hasProviderOverrides(providers)) {
|
||||
|
|
Loading…
Reference in New Issue