diff --git a/libs/ng-mocks/src/lib/common/core.config.ts b/libs/ng-mocks/src/lib/common/core.config.ts index 59ab1b1108..828a6d50fe 100644 --- a/libs/ng-mocks/src/lib/common/core.config.ts +++ b/libs/ng-mocks/src/lib/common/core.config.ts @@ -11,11 +11,24 @@ export default { // https://github.com/ike18t/ng-mocks/issues/538 'Sanitizer', 'DomSanitizer', + + // ApplicationModule, A14 made them global at root level + 'ApplicationInitStatus', + 'ApplicationRef', + 'Compiler', + 'IterableDiffers', + 'KeyValueDiffers', ], neverMockToken: [ 'InjectionToken Set Injector scope.', // INJECTOR_SCOPE // ivy only 'InjectionToken EventManagerPlugins', // EVENT_MANAGER_PLUGINS 'InjectionToken HammerGestureConfig', // HAMMER_GESTURE_CONFIG + + // ApplicationModule, A14 made them global at root level + 'InjectionToken AppId', // APP_ID + 'InjectionToken DefaultCurrencyCode', // DEFAULT_CURRENCY_CODE + 'InjectionToken LocaleId', // LOCALE_ID + 'InjectionToken SCHEDULER_TOKEN', // SCHEDULER ], onMockInstanceRestoreNeed: 'warn', onTestBedFlushNeed: 'warn', diff --git a/tests/providedin-root/test.spec.ts b/tests/providedin-root/test.spec.ts new file mode 100644 index 0000000000..3047521462 --- /dev/null +++ b/tests/providedin-root/test.spec.ts @@ -0,0 +1,105 @@ +import { + Component, + Inject, + Injectable, + InjectionToken, + LOCALE_ID, + VERSION, +} from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; + +const TOKEN = new (InjectionToken as any)('TOKEN', { + factory: () => 'ROOT_TOKEN', + providedIn: 'root', +}); + +@((Injectable as any)({ + providedIn: 'root', +})) +class Service { + public readonly value: string = 'ROOT_SERVICE'; +} + +@Component({ + selector: 'target', + template: ':{{ service.value }}:{{ token }}:{{localeId}}:', +}) +class TargetComponent { + public constructor( + public service: Service, + @Inject(TOKEN) public token: string, + @Inject(LOCALE_ID) public localeId: string, + ) {} +} + +// tokens provided on the root level, shouldn't be mocked unless it's explicitly specified. +// @see https://github.com/ike18t/ng-mocks/issues/1932 +describe('providedIn:root', () => { + if (parseInt(VERSION.major, 10) <= 5) { + it('a5', () => { + // pending('Need Angular > 5'); + expect(true).toBeTruthy(); + }); + + return; + } + + describe('native', () => { + beforeEach(() => + TestBed.configureTestingModule({ + declarations: [TargetComponent], + }), + ); + + it('finds token the root token', () => { + const fixture = MockRender(TargetComponent); + expect(ngMocks.formatHtml(fixture)).toEqual( + ':ROOT_SERVICE:ROOT_TOKEN:en-US:', + ); + }); + }); + + describe('MockBuilder:default', () => { + beforeEach(() => MockBuilder(TargetComponent)); + + it('mocks all root provides apart from ApplicationModule:LOCALE_ID', () => { + const fixture = MockRender(TargetComponent); + expect(ngMocks.formatHtml(fixture)).toEqual( + ':::en-US:', + ); + }); + }); + + describe('MockBuilder:keep', () => { + beforeEach(() => + MockBuilder(TargetComponent) + .keep(Service) + .keep(TOKEN) + .keep(LOCALE_ID), + ); + + it('keeps all original values', () => { + const fixture = MockRender(TargetComponent); + expect(ngMocks.formatHtml(fixture)).toEqual( + ':ROOT_SERVICE:ROOT_TOKEN:en-US:', + ); + }); + }); + + describe('MockBuilder:mock', () => { + beforeEach(() => + MockBuilder(TargetComponent) + .mock(Service, { value: 'MOCK_SERVICE' }) + .mock(TOKEN, 'MOCK_TOKEN') + .mock(LOCALE_ID, 'MOCK_LOCALE_ID'), + ); + + it('mocks all values', () => { + const fixture = MockRender(TargetComponent); + expect(ngMocks.formatHtml(fixture)).toEqual( + ':MOCK_SERVICE:MOCK_TOKEN:MOCK_LOCALE_ID:', + ); + }); + }); +});