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:',
+ );
+ });
+ });
+});