Skip to content

Commit 2bc0d3f

Browse files
authored
Merge pull request #95 from gnom7/tests
ISSUE-90: Better handling of synchronous (sequential) requests
2 parents f17b0ee + c550962 commit 2bc0d3f

File tree

2 files changed

+74
-10
lines changed

2 files changed

+74
-10
lines changed

src/lib/components/ng-http-loader.component.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,23 @@ export class NgHttpLoaderComponent implements OnDestroy, OnInit {
4545
public entryComponent: any = null;
4646

4747
constructor(private pendingInterceptorService: PendingInterceptorService, private spinnerVisibilityService: SpinnerVisibilityService) {
48+
}
49+
50+
ngOnInit(): void {
51+
this.nullifySpinnerIfEntryComponentIsDefined();
52+
this.initFilters();
53+
this.initializeSubscription();
54+
}
55+
56+
ngOnDestroy(): void {
57+
this.subscriptions.unsubscribe();
58+
}
59+
60+
private initializeSubscription() {
4861
const [showSpinner, hideSpinner] = partition((h: boolean) => h)(this.pendingInterceptorService.pendingRequestsStatus$);
4962

5063
this.subscriptions = merge(
51-
merge(showSpinner, hideSpinner).pipe(
64+
this.pendingInterceptorService.pendingRequestsStatus$.pipe(
5265
switchMap(() => showSpinner.pipe(debounce(() => timer(this.debounceDelay))))
5366
),
5467
showSpinner.pipe(
@@ -60,15 +73,6 @@ export class NgHttpLoaderComponent implements OnDestroy, OnInit {
6073
.subscribe(h => this.handleSpinnerVisibility(h));
6174
}
6275

63-
ngOnInit(): void {
64-
this.nullifySpinnerIfEntryComponentIsDefined();
65-
this.initFilters();
66-
}
67-
68-
ngOnDestroy(): void {
69-
this.subscriptions.unsubscribe();
70-
}
71-
7276
private nullifySpinnerIfEntryComponentIsDefined(): void {
7377
if (null != this.entryComponent) {
7478
this.spinner = null;

src/test/components/ng-http-loader.component.spec.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ describe('NgHttpLoaderComponent', () => {
3333
beforeEach(() => {
3434
fixture = TestBed.createComponent(NgHttpLoaderComponent);
3535
component = fixture.componentInstance;
36+
component.ngOnInit();
3637
});
3738

3839
it('should create the ng-http-loader component', () => {
@@ -281,6 +282,7 @@ describe('NgHttpLoaderComponent', () => {
281282

282283
const newFixture = TestBed.createComponent(NgHttpLoaderComponent);
283284
const newComponent = newFixture.componentInstance;
285+
newComponent.ngOnInit();
284286

285287
tick();
286288
expect(newComponent.isSpinnerVisible).toBeTruthy();
@@ -336,6 +338,64 @@ describe('NgHttpLoaderComponent', () => {
336338
}
337339
)));
338340

341+
it('should correctly handle the debounce delay for HTTP sequential requests finished before spinner should be shown', fakeAsync(inject(
342+
[HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
343+
component.debounceDelay = 5000;
344+
http.get('/fake').subscribe();
345+
346+
// the first HTTP request is pending for 1 second now
347+
tick(1000);
348+
expect(component.isSpinnerVisible).toBeFalsy();
349+
350+
// the first HTTP request is over
351+
httpMock.expectOne('/fake').flush({});
352+
tick(1000);
353+
354+
http.get('/fake2').subscribe();
355+
356+
// the second HTTP request is pending for 1 second now
357+
tick(1000);
358+
expect(component.isSpinnerVisible).toBeFalsy();
359+
360+
// the second HTTP request is over
361+
httpMock.expectOne('/fake2').flush({});
362+
tick();
363+
expect(component.isSpinnerVisible).toBeFalsy();
364+
365+
// the spinner shouldn't be shown after debounceDelay terminated
366+
tick(2000);
367+
expect(component.isSpinnerVisible).toBeFalsy();
368+
}
369+
)));
370+
371+
it('should correctly handle the debounce delay for HTTP parallel requests finished before spinner should be shown', fakeAsync(inject(
372+
[HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
373+
component.debounceDelay = 5000;
374+
http.get('/fake').subscribe();
375+
http.get('/fake2').subscribe();
376+
377+
// both HTTP requests are pending for 1s now
378+
tick(1000);
379+
expect(component.isSpinnerVisible).toBeFalsy();
380+
381+
// the first HTTP request is over
382+
httpMock.expectOne('/fake').flush({});
383+
384+
// the second HTTP request is pending for 2s now
385+
tick(1000);
386+
expect(component.isSpinnerVisible).toBeFalsy();
387+
388+
// the second HTTP request is over
389+
httpMock.expectOne('/fake2').flush({});
390+
tick();
391+
expect(component.isSpinnerVisible).toBeFalsy();
392+
393+
// the spinner shouldn't be shown after debounceDelay terminated
394+
tick(3000);
395+
expect(component.isSpinnerVisible).toBeFalsy();
396+
}
397+
)));
398+
339399
it('should correctly handle the debounce delay for multiple HTTP requests', fakeAsync(inject(
340400
[HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
341401
component.debounceDelay = 2000;

0 commit comments

Comments
 (0)