Skip to content

Commit 194fd19

Browse files
committed
fix(loader): updated loader logic to avoid issue with can deactivate
1 parent 014e8f7 commit 194fd19

2 files changed

Lines changed: 66 additions & 10 deletions

File tree

src/app/app.component.spec.ts

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ import { Subject } from 'rxjs';
66

77
import { ComponentFixture, TestBed } from '@angular/core/testing';
88
import { By } from '@angular/platform-browser';
9-
import { NavigationEnd, Router } from '@angular/router';
9+
import {
10+
NavigationCancel,
11+
NavigationEnd,
12+
NavigationError,
13+
NavigationStart,
14+
ResolveStart,
15+
Router,
16+
} from '@angular/router';
1017

1118
import { CookieConsentBannerComponent } from '@core/components/osf-banners/cookie-consent-banner/cookie-consent-banner.component';
1219
import { ENVIRONMENT } from '@core/provider/environment.provider';
@@ -18,17 +25,20 @@ import { TranslateServiceMock } from '../testing/mocks/translate.service.mock';
1825
import { FullScreenLoaderComponent } from './shared/components/full-screen-loader/full-screen-loader.component';
1926
import { ToastComponent } from './shared/components/toast/toast.component';
2027
import { CustomDialogService } from './shared/services/custom-dialog.service';
28+
import { LoaderService } from './shared/services/loader.service';
2129
import { AppComponent } from './app.component';
2230

2331
import { OSFTestingModule } from '@testing/osf.testing.module';
2432
import { CustomDialogServiceMockBuilder } from '@testing/providers/custom-dialog-provider.mock';
33+
import { LoaderServiceMock } from '@testing/providers/loader-service.mock';
2534
import { GoogleTagManagerService } from 'angular-google-tag-manager';
2635

2736
describe('Component: App', () => {
2837
let routerEvents$: Subject<any>;
2938
let gtmServiceMock: jest.Mocked<GoogleTagManagerService>;
3039
let fixture: ComponentFixture<AppComponent>;
3140
let mockCustomDialogService: ReturnType<CustomDialogServiceMockBuilder['build']>;
41+
let loaderServiceMock: LoaderServiceMock;
3242

3343
beforeEach(async () => {
3444
mockCustomDialogService = CustomDialogServiceMockBuilder.create().build();
@@ -37,6 +47,7 @@ describe('Component: App', () => {
3747
gtmServiceMock = {
3848
pushTag: jest.fn(),
3949
} as any;
50+
loaderServiceMock = new LoaderServiceMock();
4051

4152
await TestBed.configureTestingModule({
4253
imports: [
@@ -47,6 +58,7 @@ describe('Component: App', () => {
4758
providers: [
4859
provideStore([UserState, UserEmailsState]),
4960
MockProvider(CustomDialogService, mockCustomDialogService),
61+
MockProvider(LoaderService, loaderServiceMock),
5062
TranslateServiceMock,
5163
{ provide: GoogleTagManagerService, useValue: gtmServiceMock },
5264
{
@@ -103,4 +115,55 @@ describe('Component: App', () => {
103115
expect(gtmServiceMock.pushTag).not.toHaveBeenCalled();
104116
});
105117
});
118+
119+
describe('Loader routing behavior', () => {
120+
it('should not show loader on NavigationStart', () => {
121+
fixture.detectChanges();
122+
123+
routerEvents$.next(new NavigationStart(1, '/next'));
124+
125+
expect(loaderServiceMock.show).not.toHaveBeenCalled();
126+
});
127+
128+
it('should show loader on ResolveStart', () => {
129+
fixture.detectChanges();
130+
131+
routerEvents$.next(new ResolveStart(1, '/next', '/next', {} as any));
132+
133+
expect(loaderServiceMock.show).toHaveBeenCalled();
134+
});
135+
136+
it('should hide loader on NavigationEnd after delay', () => {
137+
jest.useFakeTimers();
138+
fixture.detectChanges();
139+
140+
routerEvents$.next(new NavigationEnd(1, '/previous', '/current'));
141+
jest.advanceTimersByTime(500);
142+
143+
expect(loaderServiceMock.hide).toHaveBeenCalled();
144+
jest.useRealTimers();
145+
});
146+
147+
it('should hide loader on NavigationCancel after delay', () => {
148+
jest.useFakeTimers();
149+
fixture.detectChanges();
150+
151+
routerEvents$.next(new NavigationCancel(1, '/current', 'cancelled'));
152+
jest.advanceTimersByTime(500);
153+
154+
expect(loaderServiceMock.hide).toHaveBeenCalled();
155+
jest.useRealTimers();
156+
});
157+
158+
it('should hide loader on NavigationError after delay', () => {
159+
jest.useFakeTimers();
160+
fixture.detectChanges();
161+
162+
routerEvents$.next(new NavigationError(1, '/current', new Error('test')));
163+
jest.advanceTimersByTime(500);
164+
165+
expect(loaderServiceMock.hide).toHaveBeenCalled();
166+
jest.useRealTimers();
167+
});
168+
});
106169
});

src/app/app.component.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,7 @@ import { switchMap, timer } from 'rxjs';
55
import { isPlatformBrowser } from '@angular/common';
66
import { ChangeDetectionStrategy, Component, DestroyRef, effect, inject, OnInit, PLATFORM_ID } from '@angular/core';
77
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
8-
import {
9-
NavigationCancel,
10-
NavigationEnd,
11-
NavigationError,
12-
NavigationStart,
13-
Router,
14-
RouterOutlet,
15-
} from '@angular/router';
8+
import { NavigationCancel, NavigationEnd, NavigationError, ResolveStart, Router, RouterOutlet } from '@angular/router';
169

1710
import { ENVIRONMENT } from '@core/provider/environment.provider';
1811
import { GetCurrentUser } from '@core/store/user';
@@ -65,7 +58,7 @@ export class AppComponent implements OnInit {
6558

6659
if (this.isBrowser) {
6760
this.router.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
68-
if (event instanceof NavigationStart) {
61+
if (event instanceof ResolveStart) {
6962
this.loaderService.show();
7063
} else if (
7164
event instanceof NavigationEnd ||

0 commit comments

Comments
 (0)