11import { Store , StoreModule } from '@ngrx/store' ;
2- import { ComponentFixture , fakeAsync , flush , inject , TestBed , tick , waitForAsync } from '@angular/core/testing' ;
3- import { ApplicationRef , CUSTOM_ELEMENTS_SCHEMA } from '@angular/core' ;
2+ import { ComponentFixture , discardPeriodicTasks , fakeAsync , flush , inject , TestBed , waitForAsync } from '@angular/core/testing' ;
3+ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core' ;
44import { CommonModule } from '@angular/common' ;
55import { ActivatedRoute , Router } from '@angular/router' ;
66import { TranslateLoader , TranslateModule } from '@ngx-translate/core' ;
@@ -31,7 +31,7 @@ import { Angulartics2DSpace } from './statistics/angulartics/dspace-provider';
3131import { storeModuleConfig } from './app.reducer' ;
3232import { LocaleService } from './core/locale/locale.service' ;
3333import { authReducer } from './core/auth/auth.reducer' ;
34- import { provideMockStore } from '@ngrx/store/testing' ;
34+ import { MockStore , provideMockStore } from '@ngrx/store/testing' ;
3535import { ThemeService } from './shared/theme-support/theme.service' ;
3636import { getMockThemeService } from './shared/mocks/theme-service.mock' ;
3737import { BreadcrumbsService } from './breadcrumbs/breadcrumbs.service' ;
@@ -42,7 +42,7 @@ let comp: AppComponent;
4242let fixture : ComponentFixture < AppComponent > ;
4343const menuService = new MenuServiceStub ( ) ;
4444const initialState = {
45- core : { auth : { loading : false } }
45+ core : { auth : { loading : false , blocking : false } }
4646} ;
4747
4848export function getMockLocaleService ( ) : LocaleService {
@@ -129,20 +129,22 @@ describe('App component', () => {
129129
130130 } ) ;
131131
132- describe ( 'removeSsrOverlayWhenStable' , ( ) => {
133- // The inline bootstrap script in src/index.html injects window.__dspaceRemoveSsrOverlay
134- // and AppComponent must call it exactly once when ApplicationRef.isStable first emits true.
135- let appRef : ApplicationRef ;
136- let isStable$ : BehaviorSubject < boolean > ;
132+ describe ( 'removeSsrOverlayWhenContentVisible' , ( ) => {
133+ // The inline bootstrap script in src/index.html injects window.__dspaceRemoveSsrOverlay.
134+ // AppComponent should remove it once both auth blocking and theme loading are false.
135+ let mockStore : MockStore ;
136+ let themeLoading$ : BehaviorSubject < boolean > ;
137+ let themeService : ThemeService ;
137138 let originalRaF : typeof window . requestAnimationFrame ;
138139
139140 beforeEach ( ( ) => {
140- appRef = TestBed . inject ( ApplicationRef ) ;
141- isStable$ = new BehaviorSubject < boolean > ( false ) ;
142- // Patch isStable to our controllable subject for this test only
143- Object . defineProperty ( appRef , 'isStable' , { value : isStable$ . asObservable ( ) } ) ;
141+ mockStore = TestBed . inject ( MockStore ) ;
142+ themeService = TestBed . inject ( ThemeService ) ;
143+ themeLoading$ = new BehaviorSubject < boolean > ( true ) ;
144+ ( themeService as any ) . isThemeLoading$ = themeLoading$ . asObservable ( ) ;
145+ mockStore . setState ( { core : { auth : { loading : false , blocking : true } } } ) ;
144146
145- // Force rAF to a synchronous shim so we can flush() through the chain deterministically .
147+ // Force rAF to a synchronous shim so assertions are deterministic .
146148 originalRaF = window . requestAnimationFrame ;
147149 ( window as any ) . requestAnimationFrame = ( cb : FrameRequestCallback ) => {
148150 cb ( 0 ) ;
@@ -155,21 +157,22 @@ describe('App component', () => {
155157 delete ( window as any ) . __dspaceRemoveSsrOverlay ;
156158 } ) ;
157159
158- it ( 'removes the overlay once isStable emits true ' , fakeAsync ( ( ) => {
160+ it ( 'removes the overlay once auth is unblocked and theme loading is finished ' , fakeAsync ( ( ) => {
159161 const spy = jasmine . createSpy ( '__dspaceRemoveSsrOverlay' ) ;
160162 window . __dspaceRemoveSsrOverlay = spy ;
161163
162- // Re-construct so the constructor-time subscription picks up our patched isStable + global.
164+ // Re-construct so constructor-time subscription picks up our patched streams + global.
163165 const f = TestBed . createComponent ( AppComponent ) ;
164166 f . detectChanges ( ) ;
165167
166168 expect ( spy ) . not . toHaveBeenCalled ( ) ;
167169
168- isStable$ . next ( true ) ;
169- tick ( 50 ) ; // matches the 50ms pad after rAF in removeSsrOverlayWhenStable
170+ mockStore . setState ( { core : { auth : { loading : false , blocking : false } } } ) ;
171+ themeLoading$ . next ( false ) ;
170172 flush ( ) ;
171173
172174 expect ( spy ) . toHaveBeenCalledTimes ( 1 ) ;
175+ discardPeriodicTasks ( ) ;
173176 } ) ) ;
174177
175178 it ( 'is a no-op when the global is not injected (e.g. CSR-only route, SSR skipped)' , fakeAsync ( ( ) => {
@@ -179,11 +182,12 @@ describe('App component', () => {
179182 const f = TestBed . createComponent ( AppComponent ) ;
180183 expect ( ( ) => f . detectChanges ( ) ) . not . toThrow ( ) ;
181184
182- isStable$ . next ( true ) ;
183- tick ( 50 ) ;
185+ mockStore . setState ( { core : { auth : { loading : false , blocking : false } } } ) ;
186+ themeLoading$ . next ( false ) ;
184187 flush ( ) ;
185188
186189 expect ( window . __dspaceRemoveSsrOverlay ) . toBeUndefined ( ) ;
190+ discardPeriodicTasks ( ) ;
187191 } ) ) ;
188192 } ) ;
189193} ) ;
0 commit comments