diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index a7b38e60e..b5228f3cc 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -8,7 +8,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { NavigationEnd, Router } from '@angular/router'; -import { OSFConfigService } from '@core/services/osf-config.service'; +import { ENVIRONMENT } from '@core/provider/environment.provider'; import { GetCurrentUser, UserState } from '@core/store/user'; import { UserEmailsState } from '@core/store/user-emails'; @@ -22,7 +22,6 @@ import { GoogleTagManagerService } from 'angular-google-tag-manager'; describe('Component: App', () => { let routerEvents$: Subject; let gtmServiceMock: jest.Mocked; - let osfConfigServiceMock: OSFConfigService; let fixture: ComponentFixture; beforeEach(async () => { @@ -48,16 +47,9 @@ describe('Component: App', () => { events: routerEvents$.asObservable(), }, }, - { - provide: OSFConfigService, - useValue: { - has: jest.fn(), - }, - }, ], }).compileComponents(); - osfConfigServiceMock = TestBed.inject(OSFConfigService); fixture = TestBed.createComponent(AppComponent); }); @@ -81,7 +73,6 @@ describe('Component: App', () => { describe('Google Tag Manager', () => { it('should push GTM tag on NavigationEnd with google tag id', () => { - jest.spyOn(osfConfigServiceMock, 'has').mockReturnValue(true); fixture.detectChanges(); const event = new NavigationEnd(1, '/previous', '/current'); @@ -93,8 +84,9 @@ describe('Component: App', () => { }); }); - it('should not push GTM tag on NavigationEnd with google tag id', () => { - jest.spyOn(osfConfigServiceMock, 'has').mockReturnValue(false); + it('should not push GTM tag on NavigationEnd without google tag id', () => { + const environment = TestBed.inject(ENVIRONMENT); + environment.googleTagManagerId = ''; fixture.detectChanges(); const event = new NavigationEnd(1, '/previous', '/current'); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a40f124f0..0ab42a96a 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -10,7 +10,7 @@ import { ChangeDetectionStrategy, Component, DestroyRef, effect, inject, OnInit import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { NavigationEnd, Router, RouterOutlet } from '@angular/router'; -import { OSFConfigService } from '@core/services/osf-config.service'; +import { ENVIRONMENT } from '@core/provider/environment.provider'; import { GetCurrentUser } from '@core/store/user'; import { GetEmails, UserEmailsSelectors } from '@core/store/user-emails'; import { ConfirmEmailComponent } from '@shared/components'; @@ -34,7 +34,7 @@ export class AppComponent implements OnInit { private readonly dialogService = inject(DialogService); private readonly router = inject(Router); private readonly translateService = inject(TranslateService); - private readonly osfConfigService = inject(OSFConfigService); + private readonly environment = inject(ENVIRONMENT); private readonly actions = createDispatchMap({ getCurrentUser: GetCurrentUser, getEmails: GetEmails }); @@ -52,7 +52,7 @@ export class AppComponent implements OnInit { this.actions.getCurrentUser(); this.actions.getEmails(); - if (this.osfConfigService.has('googleTagManagerId')) { + if (this.environment.googleTagManagerId) { this.router.events .pipe( filter((event) => event instanceof NavigationEnd), diff --git a/src/app/app.config.ts b/src/app/app.config.ts index 0e57923b1..b456a9341 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -7,21 +7,14 @@ import { ConfirmationService, MessageService } from 'primeng/api'; import { providePrimeNG } from 'primeng/config'; import { provideHttpClient, withInterceptors } from '@angular/common/http'; -import { - ApplicationConfig, - ErrorHandler, - importProvidersFrom, - PLATFORM_ID, - provideZoneChangeDetection, -} from '@angular/core'; +import { ApplicationConfig, ErrorHandler, importProvidersFrom, provideZoneChangeDetection } from '@angular/core'; import { provideAnimations } from '@angular/platform-browser/animations'; import { provideRouter, withInMemoryScrolling } from '@angular/router'; import { STATES } from '@core/constants'; -import { APPLICATION_INITIALIZATION_PROVIDER } from '@core/factory/application.initialization.factory'; -import { SENTRY_PROVIDER } from '@core/factory/sentry.factory'; -import { WINDOW, windowFactory } from '@core/factory/window.factory'; import { provideTranslation } from '@core/helpers'; +import { APPLICATION_INITIALIZATION_PROVIDER } from '@core/provider/application.initialization.provider'; +import { SENTRY_PROVIDER } from '@core/provider/sentry.provider'; import { authInterceptor, errorInterceptor, viewOnlyInterceptor } from './core/interceptors'; import CustomPreset from './core/theme/custom-preset'; @@ -53,20 +46,6 @@ export const appConfig: ApplicationConfig = { }, }), provideHttpClient(withInterceptors([authInterceptor, viewOnlyInterceptor, errorInterceptor])), - importProvidersFrom(TranslateModule.forRoot(provideTranslation())), - ConfirmationService, - MessageService, - - APPLICATION_INITIALIZATION_PROVIDER, - { - provide: ErrorHandler, - useFactory: () => Sentry.createErrorHandler({ showDialog: false }), - }, - { - provide: WINDOW, - useFactory: windowFactory, - deps: [PLATFORM_ID], - }, provideRouter(routes, withInMemoryScrolling({ scrollPositionRestoration: 'top', anchorScrolling: 'enabled' })), provideStore(STATES, withNgxsReduxDevtoolsPlugin({ disabled: false })), provideZoneChangeDetection({ eventCoalescing: true }), diff --git a/src/app/core/factory/environment.factory.ts b/src/app/core/factory/environment.factory.ts deleted file mode 100644 index d16cfa292..000000000 --- a/src/app/core/factory/environment.factory.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { inject, InjectionToken } from '@angular/core'; - -import { ENVIRONMENT_DO_NO_USE } from '@core/constants/environment.token'; -import { EnvironmentModel } from '@osf/shared/models/environment.model'; - -export const ENVIRONMENT = new InjectionToken('EnvironmentProxy', { - providedIn: 'root', - factory: () => { - const environment = inject(ENVIRONMENT_DO_NO_USE); - - return new Proxy( - { ...environment }, - { - get: (target, prop: keyof EnvironmentModel) => target[prop], - set: (target: EnvironmentModel, prop: K, value: EnvironmentModel[K]) => { - target[prop] = value; - return true; - }, - } - ); - }, -}); diff --git a/src/app/core/factory/window.factory.spec.ts b/src/app/core/factory/window.factory.spec.ts deleted file mode 100644 index 0211cf905..000000000 --- a/src/app/core/factory/window.factory.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -// src/app/window.spec.ts -import { isPlatformBrowser } from '@angular/common'; - -import { windowFactory } from './window.factory'; - -jest.mock('@angular/common', () => ({ - isPlatformBrowser: jest.fn(), -})); - -describe('windowFactory', () => { - const mockWindow = globalThis.window; - - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should return window object if platform is browser', () => { - (isPlatformBrowser as jest.Mock).mockReturnValue(true); - - const result = windowFactory('browser'); - expect(isPlatformBrowser).toHaveBeenCalledWith('browser'); - expect(result).toBe(mockWindow); - }); - - it('should return empty object if platform is not browser', () => { - (isPlatformBrowser as jest.Mock).mockReturnValue(false); - - const result = windowFactory('server'); - expect(isPlatformBrowser).toHaveBeenCalledWith('server'); - expect(result).toEqual({}); - }); -}); diff --git a/src/app/core/factory/window.factory.ts b/src/app/core/factory/window.factory.ts deleted file mode 100644 index 395524e44..000000000 --- a/src/app/core/factory/window.factory.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { isPlatformBrowser } from '@angular/common'; -import { InjectionToken } from '@angular/core'; - -export const WINDOW = new InjectionToken('Global Window Object'); - -/** - * A factory function to provide the global `window` object in Angular. - * - * This is useful for making Angular applications **Universal-compatible** (i.e., supporting server-side rendering). - * It conditionally returns the real `window` only when the code is running in the **browser**, not on the server. - * - * @param platformId - The Angular platform ID token (injected by Angular) that helps detect the execution environment. - * @returns The actual `window` object if running in the browser, otherwise a mock object `{}` for SSR environments. - * - * @see https://angular.io/api/core/PLATFORM_ID - * @see https://angular.io/guide/universal - */ -export function windowFactory(platformId: string): Window | object { - // Check if we're running in the browser (vs server-side) - if (isPlatformBrowser(platformId)) { - return window; - } - - // Return an empty object as a safe fallback during server-side rendering - return {}; -} diff --git a/src/app/core/factory/application.initialization.factory.spec.ts b/src/app/core/provider/application.initialization.provider.spec.ts similarity index 96% rename from src/app/core/factory/application.initialization.factory.spec.ts rename to src/app/core/provider/application.initialization.provider.spec.ts index 7ecf1defa..12b73f067 100644 --- a/src/app/core/factory/application.initialization.factory.spec.ts +++ b/src/app/core/provider/application.initialization.provider.spec.ts @@ -4,8 +4,8 @@ import { TestBed } from '@angular/core/testing'; import { OSFConfigService } from '@core/services/osf-config.service'; -import { initializeApplication } from './application.initialization.factory'; -import { ENVIRONMENT } from './environment.factory'; +import { initializeApplication } from './application.initialization.provider'; +import { ENVIRONMENT } from './environment.provider'; import * as Sentry from '@sentry/angular'; import { OSFTestingModule } from '@testing/osf.testing.module'; @@ -16,7 +16,7 @@ jest.mock('@sentry/angular', () => ({ createErrorHandler: jest.fn(() => 'mockErrorHandler'), })); -describe('factory: sentry', () => { +describe('Provider: sentry', () => { let osfConfigServiceMock: OSFConfigService; let googleTagManagerConfigurationMock: GoogleTagManagerConfiguration; let httpMock: HttpTestingController; diff --git a/src/app/core/factory/application.initialization.factory.ts b/src/app/core/provider/application.initialization.provider.ts similarity index 97% rename from src/app/core/factory/application.initialization.factory.ts rename to src/app/core/provider/application.initialization.provider.ts index 6890b8dd5..db22ec5bc 100644 --- a/src/app/core/factory/application.initialization.factory.ts +++ b/src/app/core/provider/application.initialization.provider.ts @@ -2,7 +2,7 @@ import { inject, provideAppInitializer } from '@angular/core'; import { OSFConfigService } from '@core/services/osf-config.service'; -import { ENVIRONMENT } from './environment.factory'; +import { ENVIRONMENT } from './environment.provider'; import * as Sentry from '@sentry/angular'; import { GoogleTagManagerConfiguration } from 'angular-google-tag-manager'; diff --git a/src/app/core/factory/environment.factory.spec.ts b/src/app/core/provider/environment.provider.spec.ts similarity index 95% rename from src/app/core/factory/environment.factory.spec.ts rename to src/app/core/provider/environment.provider.spec.ts index 4f143e6b6..9548e0b07 100644 --- a/src/app/core/factory/environment.factory.spec.ts +++ b/src/app/core/provider/environment.provider.spec.ts @@ -2,11 +2,11 @@ import { TestBed } from '@angular/core/testing'; import { EnvironmentModel } from '@osf/shared/models/environment.model'; -import { ENVIRONMENT } from './environment.factory'; +import { ENVIRONMENT } from './environment.provider'; import { OSFTestingModule } from '@testing/osf.testing.module'; -describe('Factory: Environment', () => { +describe('Provider: Environment', () => { let environment: EnvironmentModel; beforeEach(async () => { diff --git a/src/app/core/provider/environment.provider.ts b/src/app/core/provider/environment.provider.ts new file mode 100644 index 000000000..bfc7ad4dc --- /dev/null +++ b/src/app/core/provider/environment.provider.ts @@ -0,0 +1,45 @@ +import { inject, InjectionToken } from '@angular/core'; + +import { ENVIRONMENT_DO_NO_USE } from '@core/constants/environment.token'; +import { EnvironmentModel } from '@osf/shared/models/environment.model'; + +/** + * `ENVIRONMENT` is an Angular `InjectionToken` that provides a **runtime-mutable proxy** + * over the application's static environment configuration. + * + * This factory wraps the base environment config (`ENVIRONMENT_DO_NO_USE`) in a `Proxy` + * so values can be accessed and overridden at runtime while preserving type safety + * based on the `EnvironmentModel` interface. + * + * ## Key Features: + * - Provides type-safe access to environment variables (e.g. `apiDomainUrl`, `recaptchaSiteKey`) + * - Supports **runtime modification** of values (e.g. `environment.featureFlag = true`) + * - Works seamlessly with Angular dependency injection + * + * @example + * ```ts + * const env = inject(ENVIRONMENT); + * console.log(env.apiDomainUrl); + * env.apiDomainUrl = 'https://dev.example.com'; // Override at runtime + * ``` + * + * @see EnvironmentModel for a complete list of available keys. + * @see ENVIRONMENT_DO_NO_USE for the static base config (not modifiable). + */ +export const ENVIRONMENT = new InjectionToken('EnvironmentProxy', { + providedIn: 'root', + factory: () => { + const environment = inject(ENVIRONMENT_DO_NO_USE); + + return new Proxy( + { ...environment }, + { + get: (target, prop: keyof EnvironmentModel) => target[prop], + set: (target: EnvironmentModel, prop: K, value: EnvironmentModel[K]) => { + target[prop] = value; + return true; + }, + } + ); + }, +}); diff --git a/src/app/core/factory/sentry.factory.spec.ts b/src/app/core/provider/sentry.provider.spec.ts similarity index 80% rename from src/app/core/factory/sentry.factory.spec.ts rename to src/app/core/provider/sentry.provider.spec.ts index f3af9aa6f..82e18573d 100644 --- a/src/app/core/factory/sentry.factory.spec.ts +++ b/src/app/core/provider/sentry.provider.spec.ts @@ -1,10 +1,10 @@ import { TestBed } from '@angular/core/testing'; -import { SENTRY_PROVIDER, SENTRY_TOKEN } from './sentry.factory'; +import { SENTRY_PROVIDER, SENTRY_TOKEN } from './sentry.provider'; import * as Sentry from '@sentry/angular'; -describe('Factory: Sentry', () => { +describe('Provider: Sentry', () => { beforeEach(() => { TestBed.configureTestingModule({ providers: [SENTRY_PROVIDER], diff --git a/src/app/core/factory/sentry.factory.ts b/src/app/core/provider/sentry.provider.ts similarity index 100% rename from src/app/core/factory/sentry.factory.ts rename to src/app/core/provider/sentry.provider.ts diff --git a/src/app/core/provider/window.provider.spec.ts b/src/app/core/provider/window.provider.spec.ts new file mode 100644 index 000000000..7f45aef72 --- /dev/null +++ b/src/app/core/provider/window.provider.spec.ts @@ -0,0 +1,35 @@ +import { CommonModule } from '@angular/common'; +import { PLATFORM_ID } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; + +import { WINDOW } from './window.provider'; + +describe('Provider: WINDOW', () => { + describe('when running in the browser', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [CommonModule], + providers: [{ provide: PLATFORM_ID, useValue: 'browser' }], + }); + }); + + it('should return the real window object', () => { + const result = TestBed.inject(WINDOW); + expect(result).toBe(window); + }); + }); + + describe('when running on the server', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [CommonModule], + providers: [{ provide: PLATFORM_ID, useValue: 'server' }], + }); + }); + + it('should return an empty object instead of window', () => { + const result = TestBed.inject(WINDOW); + expect(result).toEqual({}); + }); + }); +}); diff --git a/src/app/core/provider/window.provider.ts b/src/app/core/provider/window.provider.ts new file mode 100644 index 000000000..64ab411a4 --- /dev/null +++ b/src/app/core/provider/window.provider.ts @@ -0,0 +1,22 @@ +import { isPlatformBrowser } from '@angular/common'; +import { inject, InjectionToken, PLATFORM_ID } from '@angular/core'; + +/** + * `WINDOW` is an Angular InjectionToken that provides access to the global `window` object, + * but only when running in the browser (never on the server). + * + * This makes Angular Universal (SSR) safe by returning a mock object `{}` during server-side rendering. + * + * @example + * ```ts + * const win = inject(WINDOW); + * win.localStorage.getItem('token'); + * ``` + */ +export const WINDOW = new InjectionToken('Global Window Object', { + providedIn: 'root', + factory: () => { + const platformId = inject(PLATFORM_ID); + return isPlatformBrowser(platformId) ? window : {}; + }, +}); diff --git a/src/app/core/services/help-scout.service.spec.ts b/src/app/core/services/help-scout.service.spec.ts index 8f7603aea..454a98fff 100644 --- a/src/app/core/services/help-scout.service.spec.ts +++ b/src/app/core/services/help-scout.service.spec.ts @@ -3,7 +3,7 @@ import { Store } from '@ngxs/store'; import { signal } from '@angular/core'; import { TestBed } from '@angular/core/testing'; -import { WINDOW } from '@core/factory/window.factory'; +import { WINDOW } from '@core/provider/window.provider'; import { UserSelectors } from '@core/store/user/user.selectors'; import { HelpScoutService } from './help-scout.service'; diff --git a/src/app/core/services/help-scout.service.ts b/src/app/core/services/help-scout.service.ts index 7f33b002b..e8a00b71b 100644 --- a/src/app/core/services/help-scout.service.ts +++ b/src/app/core/services/help-scout.service.ts @@ -2,7 +2,7 @@ import { Store } from '@ngxs/store'; import { effect, inject, Injectable } from '@angular/core'; -import { WINDOW } from '@core/factory/window.factory'; +import { WINDOW } from '@core/provider/window.provider'; import { UserSelectors } from '@osf/core/store/user'; /** diff --git a/src/app/core/services/osf-config.service.spec.ts b/src/app/core/services/osf-config.service.spec.ts index 878135c7e..2c899ab48 100644 --- a/src/app/core/services/osf-config.service.spec.ts +++ b/src/app/core/services/osf-config.service.spec.ts @@ -1,8 +1,8 @@ import { HttpTestingController } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ENVIRONMENT } from '@core/factory/environment.factory'; import { ConfigModel } from '@core/models/config.model'; +import { ENVIRONMENT } from '@core/provider/environment.provider'; import { EnvironmentModel } from '@osf/shared/models/environment.model'; import { OSFConfigService } from './osf-config.service'; diff --git a/src/app/core/services/osf-config.service.ts b/src/app/core/services/osf-config.service.ts index 2ee395d2c..6d23156f3 100644 --- a/src/app/core/services/osf-config.service.ts +++ b/src/app/core/services/osf-config.service.ts @@ -3,8 +3,8 @@ import { catchError, lastValueFrom, of, shareReplay } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { inject, Injectable } from '@angular/core'; -import { ENVIRONMENT } from '@core/factory/environment.factory'; import { ConfigModel } from '@core/models/config.model'; +import { ENVIRONMENT } from '@core/provider/environment.provider'; /** * Service for loading and accessing configuration values @@ -24,6 +24,9 @@ export class OSFConfigService { */ private http: HttpClient = inject(HttpClient); + /** + * Injected instance of the application environment configuration. + * */ private environment = inject(ENVIRONMENT); /** diff --git a/src/app/features/collections/components/collections-discover/collections-discover.component.spec.ts b/src/app/features/collections/components/collections-discover/collections-discover.component.spec.ts index 5b497b230..e89538d36 100644 --- a/src/app/features/collections/components/collections-discover/collections-discover.component.spec.ts +++ b/src/app/features/collections/components/collections-discover/collections-discover.component.spec.ts @@ -12,7 +12,7 @@ import { provideHttpClientTesting } from '@angular/common/http/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ActivatedRoute } from '@angular/router'; -import { SENTRY_TOKEN } from '@core/factory/sentry.factory'; +import { SENTRY_TOKEN } from '@core/provider/sentry.provider'; import { CollectionsMainContentComponent } from '@osf/features/collections/components'; import { CollectionsSearchResultCardComponent } from '@osf/features/collections/components/collections-search-result-card/collections-search-result-card.component'; import { LoadingSpinnerComponent, SearchInputComponent } from '@shared/components'; diff --git a/src/app/features/collections/services/collections-query-sync.service.ts b/src/app/features/collections/services/collections-query-sync.service.ts index af92b2e50..0b8431671 100644 --- a/src/app/features/collections/services/collections-query-sync.service.ts +++ b/src/app/features/collections/services/collections-query-sync.service.ts @@ -4,7 +4,7 @@ import { effect, inject, Injectable, signal } from '@angular/core'; import { toSignal } from '@angular/core/rxjs-interop'; import { ActivatedRoute, Router } from '@angular/router'; -import { SENTRY_TOKEN } from '@core/factory/sentry.factory'; +import { SENTRY_TOKEN } from '@core/provider/sentry.provider'; import { collectionsSortOptions } from '@osf/features/collections/constants'; import { queryParamsKeys } from '@osf/features/collections/constants/query-params-keys.const'; import { CollectionQueryParams } from '@osf/features/collections/models'; diff --git a/src/app/features/files/pages/files/files.component.spec.ts b/src/app/features/files/pages/files/files.component.spec.ts index 4a6c370a9..eb171f2ec 100644 --- a/src/app/features/files/pages/files/files.component.spec.ts +++ b/src/app/features/files/pages/files/files.component.spec.ts @@ -13,7 +13,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; -import { SENTRY_TOKEN } from '@core/factory/sentry.factory'; +import { SENTRY_TOKEN } from '@core/provider/sentry.provider'; import { FilesTreeComponent, FormSelectComponent, diff --git a/src/app/features/registry/pages/registration-recent-activity/registration-recent-activity.component.ts b/src/app/features/registry/pages/registration-recent-activity/registration-recent-activity.component.ts index 390f2ff8a..888819ede 100644 --- a/src/app/features/registry/pages/registration-recent-activity/registration-recent-activity.component.ts +++ b/src/app/features/registry/pages/registration-recent-activity/registration-recent-activity.component.ts @@ -9,7 +9,7 @@ import { DatePipe } from '@angular/common'; import { ChangeDetectionStrategy, Component, computed, inject, OnDestroy, signal } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { ENVIRONMENT } from '@core/factory/environment.factory'; +import { ENVIRONMENT } from '@core/provider/environment.provider'; import { CustomPaginatorComponent } from '@shared/components'; import { ACTIVITY_LOGS_DEFAULT_PAGE_SIZE } from '@shared/constants/activity-logs'; import { diff --git a/src/app/shared/components/addons/storage-item-selector/google-file-picker/google-file-picker.component.spec.ts b/src/app/shared/components/addons/storage-item-selector/google-file-picker/google-file-picker.component.spec.ts index 578a1f54f..c8a7b597f 100644 --- a/src/app/shared/components/addons/storage-item-selector/google-file-picker/google-file-picker.component.spec.ts +++ b/src/app/shared/components/addons/storage-item-selector/google-file-picker/google-file-picker.component.spec.ts @@ -4,8 +4,7 @@ import { Observable, of, throwError } from 'rxjs'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { SENTRY_TOKEN } from '@core/factory/sentry.factory'; -import { OSFConfigService } from '@core/services/osf-config.service'; +import { SENTRY_TOKEN } from '@core/provider/sentry.provider'; import { GoogleFilePickerDownloadService } from './service/google-file-picker.download.service'; import { GoogleFilePickerComponent } from './google-file-picker.component'; @@ -25,17 +24,6 @@ describe('Component: Google File Picker', () => { }), }; - const OSFConfigServiceProvider = { - provide: OSFConfigService, - useValue: { - get: (key: string) => { - if (key === 'googleFilePickerApiKey') return 'test-api-key'; - if (key === 'googleFilePickerAppId') return 'test-app-id'; - return null; - }, - }, - }; - let sentrySpy: any; let throwLoadScriptError = false; @@ -123,7 +111,6 @@ describe('Component: Google File Picker', () => { provide: Store, useValue: storeMock, }, - OSFConfigServiceProvider, ], }).compileComponents(); @@ -245,7 +232,6 @@ describe('Component: Google File Picker', () => { provide: Store, useValue: storeMock, }, - OSFConfigServiceProvider, ], }).compileComponents(); diff --git a/src/app/shared/components/addons/storage-item-selector/google-file-picker/google-file-picker.component.ts b/src/app/shared/components/addons/storage-item-selector/google-file-picker/google-file-picker.component.ts index ac2272200..c014114ed 100644 --- a/src/app/shared/components/addons/storage-item-selector/google-file-picker/google-file-picker.component.ts +++ b/src/app/shared/components/addons/storage-item-selector/google-file-picker/google-file-picker.component.ts @@ -6,8 +6,8 @@ import { Button } from 'primeng/button'; import { ChangeDetectionStrategy, Component, inject, input, OnInit, signal } from '@angular/core'; -import { SENTRY_TOKEN } from '@core/factory/sentry.factory'; -import { OSFConfigService } from '@core/services/osf-config.service'; +import { ENVIRONMENT } from '@core/provider/environment.provider'; +import { SENTRY_TOKEN } from '@core/provider/sentry.provider'; import { StorageItemModel } from '@osf/shared/models'; import { GoogleFileDataModel } from '@osf/shared/models/files/google-file.data.model'; import { GoogleFilePickerModel } from '@osf/shared/models/files/google-file.picker.model'; @@ -26,7 +26,7 @@ import { GoogleFilePickerDownloadService } from './service/google-file-picker.do }) export class GoogleFilePickerComponent implements OnInit { private readonly Sentry = inject(SENTRY_TOKEN); - private configService = inject(OSFConfigService); + private readonly environmnet = inject(ENVIRONMENT); readonly #translateService = inject(TranslateService); readonly #googlePicker = inject(GoogleFilePickerDownloadService); @@ -39,8 +39,8 @@ export class GoogleFilePickerComponent implements OnInit { public accessToken = signal(null); public visible = signal(false); public isGFPDisabled = signal(true); - private readonly apiKey = this.configService.get('googleFilePickerApiKey'); - private readonly appId = this.configService.get('googleFilePickerAppId'); + private readonly apiKey = this.environmnet.googleFilePickerApiKey; + private readonly appId = this.environmnet.googleFilePickerAppId; private readonly store = inject(Store); private parentId = ''; diff --git a/src/app/shared/services/datacite/datacite.service.spec.ts b/src/app/shared/services/datacite/datacite.service.spec.ts index ae824b150..a4813551e 100644 --- a/src/app/shared/services/datacite/datacite.service.spec.ts +++ b/src/app/shared/services/datacite/datacite.service.spec.ts @@ -4,7 +4,7 @@ import { provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ENVIRONMENT } from '@core/factory/environment.factory'; +import { ENVIRONMENT } from '@core/provider/environment.provider'; import { Identifier } from '@shared/models'; import { DataciteEvent } from '@shared/models/datacite/datacite-event.enum'; diff --git a/src/app/shared/services/datacite/datacite.service.ts b/src/app/shared/services/datacite/datacite.service.ts index aaef45c46..e94ae938e 100644 --- a/src/app/shared/services/datacite/datacite.service.ts +++ b/src/app/shared/services/datacite/datacite.service.ts @@ -3,7 +3,7 @@ import { EMPTY, filter, map, Observable, of, switchMap, take } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { inject, Injectable } from '@angular/core'; -import { ENVIRONMENT } from '@core/factory/environment.factory'; +import { ENVIRONMENT } from '@core/provider/environment.provider'; import { Identifier } from '@shared/models'; import { DataciteEvent } from '@shared/models/datacite/datacite-event.enum'; import { IdentifiersJsonApiResponse } from '@shared/models/identifiers/identifier-json-api.model'; diff --git a/src/testing/mocks/environment.token.mock.ts b/src/testing/mocks/environment.token.mock.ts index 027cb8f90..fe239bd87 100644 --- a/src/testing/mocks/environment.token.mock.ts +++ b/src/testing/mocks/environment.token.mock.ts @@ -25,5 +25,8 @@ export const EnvironmentTokenMock = { useValue: { production: false, apiDomainUrl: 'http://localhost:8000', + googleFilePickerApiKey: 'test-api-key', + googleFilePickerAppId: 'test-app-id', + googleTagManagerId: 'test-goolge-tag-manager-id', }, }; diff --git a/src/testing/osf.testing.module.ts b/src/testing/osf.testing.module.ts index c7412daf6..8687591d1 100644 --- a/src/testing/osf.testing.module.ts +++ b/src/testing/osf.testing.module.ts @@ -8,7 +8,7 @@ import { BrowserModule } from '@angular/platform-browser'; import { NoopAnimationsModule, provideNoopAnimations } from '@angular/platform-browser/animations'; import { provideRouter } from '@angular/router'; -import { WINDOW, windowFactory } from '@core/factory/window.factory'; +import { WINDOW, windowFactory } from '@core/provider/window.provider'; import { DynamicDialogRefMock } from './mocks/dynamic-dialog-ref.mock'; import { EnvironmentTokenMock } from './mocks/environment.token.mock';