Skip to content

Commit 6565aa6

Browse files
andresacg30mmaquinasemantic-release-botAndres Cabrera
authored
fix: Tta 193 add loading page to new ip check load time (#939)
* feat: TTA-193 add preload page * fix: TTA-181 change husky hint when commit message is wrong (#937) Co-authored-by: mmaquina <[email protected]> * chore(release): 1.75.21 [skip ci]nn * feat: TTA-193 add service and interceptor for spinner loading * feat: TTA-193 add spinner overlay and style it * test: TTA-193 make test * update package-lock.json version * test: add test for interceptor and service * test: TTA-193 increase code coverage * test: TTA-193 increase code coverage * fix: spinner test * fix: spinner test * fix: load spinner when route is recent Co-authored-by: mmaquina <[email protected]> Co-authored-by: mmaquina <[email protected]> Co-authored-by: semantic-release-bot <[email protected]> Co-authored-by: Andres Cabrera <andres@MSI> Co-authored-by: Nicole Garcia <nicolsss>
1 parent 8abf25b commit 6565aa6

File tree

11 files changed

+33123
-159
lines changed

11 files changed

+33123
-159
lines changed

package-lock.json

Lines changed: 32881 additions & 156 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "time-tracker",
3-
"version": "1.75.22",
3+
"version": "1.75.24",
44
"scripts": {
55
"preinstall": "npx npm-force-resolutions",
66
"ng": "ng",

src/app/app.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<router-outlet></router-outlet>
1+
<router-outlet></router-outlet>

src/app/app.module.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
33
import { ToastrModule } from 'ngx-toastr';
44
import { CommonModule, DatePipe } from '@angular/common';
55
import { BrowserModule } from '@angular/platform-browser';
6-
import { NgModule, Component } from '@angular/core';
6+
import { NgModule } from '@angular/core';
77
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
88
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
99
import { DataTablesModule } from 'angular-datatables';
@@ -14,6 +14,8 @@ import { DragDropModule } from '@angular/cdk/drag-drop';
1414
import { MatCheckboxModule } from '@angular/material/checkbox';
1515
import { MatDatepickerModule } from '@angular/material/datepicker';
1616
import { MatInputModule } from '@angular/material/input';
17+
import { MatButtonModule } from '@angular/material/button';
18+
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
1719
import { MatIconModule } from '@angular/material/icon';
1820
import { MatListModule } from '@angular/material/list';
1921
import { MatMomentDateModule } from '@angular/material-moment-adapter';
@@ -95,6 +97,8 @@ import { SearchUserComponent } from './modules/shared/components/search-user/sea
9597
import { TimeRangeCustomComponent } from './modules/reports/components/time-range-custom/time-range-custom.component';
9698
import { TimeRangeHeaderComponent } from './modules/reports/components/time-range-custom/time-range-header/time-range-header.component';
9799
import { TimeRangeOptionsComponent } from './modules/reports/components/time-range-custom/time-range-options/time-range-options.component';
100+
import { SpinnerOverlayComponent } from './modules/shared/components/spinner-overlay/spinner-overlay.component';
101+
import { SpinnerInterceptor } from './modules/shared/interceptors/spinner.interceptor';
98102

99103
const maskConfig: Partial<IConfig> = {
100104
validation: false,
@@ -154,6 +158,7 @@ const maskConfig: Partial<IConfig> = {
154158
TimeRangeCustomComponent,
155159
TimeRangeHeaderComponent,
156160
TimeRangeOptionsComponent,
161+
SpinnerOverlayComponent,
157162
],
158163
imports: [
159164
NgxMaskModule.forRoot(maskConfig),
@@ -172,6 +177,7 @@ const maskConfig: Partial<IConfig> = {
172177
DataTablesModule,
173178
AutocompleteLibModule,
174179
NgxMaterialTimepickerModule,
180+
MatProgressSpinnerModule,
175181
UiSwitchModule,
176182
DragDropModule,
177183
MatIconModule,
@@ -206,6 +212,11 @@ const maskConfig: Partial<IConfig> = {
206212
useClass: InjectTokenInterceptor,
207213
multi: true,
208214
},
215+
{
216+
provide: HTTP_INTERCEPTORS,
217+
useClass: SpinnerInterceptor,
218+
multi: true,
219+
},
209220
DatePipe,
210221
CookieService,
211222
{provide: Window, useValue: window}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@use "../../../../../styles/colors.scss" as colors;
2+
3+
:host ::ng-deep .mat-progress-spinner circle, .mat-spinner circle {
4+
stroke: colors.$warning;
5+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { SpinnerOverlayComponent } from './spinner-overlay.component';
4+
5+
describe('SpinnerOverlayComponent', () => {
6+
let component: SpinnerOverlayComponent;
7+
let fixture: ComponentFixture<SpinnerOverlayComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
declarations: [ SpinnerOverlayComponent ]
12+
})
13+
.compileComponents();
14+
15+
fixture = TestBed.createComponent(SpinnerOverlayComponent);
16+
component = fixture.componentInstance;
17+
fixture.detectChanges();
18+
});
19+
20+
it('should create', () => {
21+
expect(component).toBeTruthy();
22+
});
23+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-spinner-overlay',
5+
template: '<mat-spinner diameter="80"></mat-spinner>',
6+
styleUrls: ['./spinner-overlay.component.scss'],
7+
})
8+
9+
export class SpinnerOverlayComponent {
10+
constructor() {}
11+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
2+
3+
import { Overlay } from '@angular/cdk/overlay';
4+
import { TestBed } from '@angular/core/testing';
5+
import { SpinnerInterceptor } from './spinner.interceptor';
6+
import { HttpHandler, HttpRequest, HttpResponse, HttpEvent } from '@angular/common/http';
7+
import { Observable, of } from 'rxjs';
8+
import { SpinnerOverlayService } from '../services/spinner-overlay.service';
9+
10+
11+
describe('SpinnerInterceptorService test', () => {
12+
TestBed.configureTestingModule({
13+
providers: [
14+
SpinnerInterceptor,
15+
Overlay
16+
],
17+
});
18+
19+
class MockHttpHandler implements HttpHandler {
20+
handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
21+
return of(new HttpResponse());
22+
}
23+
}
24+
25+
let overlay: Overlay;
26+
let httpHandler: HttpHandler;
27+
let spinnerInterceptor: SpinnerInterceptor;
28+
29+
beforeEach(() => {
30+
overlay = jasmine.createSpyObj('Overlay', ['create']);
31+
httpHandler = new MockHttpHandler();
32+
spinnerInterceptor = new SpinnerInterceptor(new SpinnerOverlayService(overlay));
33+
});
34+
35+
it('should be created', () => {
36+
expect(spinnerInterceptor).toBeTruthy();
37+
});
38+
39+
it('if request is made then spinnerInterceptor is called', () => {
40+
const request = new HttpRequest('GET', '/recent');
41+
spyOn(spinnerInterceptor, 'intercept');
42+
43+
spinnerInterceptor.intercept(request, httpHandler);
44+
45+
expect(spinnerInterceptor.intercept).toHaveBeenCalledWith(request, httpHandler);
46+
47+
});
48+
49+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import {
2+
HttpEvent,
3+
HttpHandler,
4+
HttpInterceptor,
5+
HttpRequest,
6+
} from '@angular/common/http';
7+
import { Injectable } from '@angular/core';
8+
import { Observable, Subscription } from 'rxjs';
9+
import { finalize } from 'rxjs/operators';
10+
import { SpinnerOverlayService } from '../services/spinner-overlay.service';
11+
12+
@Injectable()
13+
export class SpinnerInterceptor implements HttpInterceptor {
14+
constructor(private readonly spinnerOverlayService: SpinnerOverlayService) {}
15+
16+
intercept(
17+
req: HttpRequest<any>,
18+
next: HttpHandler
19+
): Observable<HttpEvent<any>> {
20+
if(req.url.endsWith('recent')){
21+
const spinnerSubscription: Subscription = this.spinnerOverlayService.spinner$.subscribe();
22+
return next
23+
.handle(req)
24+
.pipe(finalize(() => spinnerSubscription.unsubscribe()));
25+
}else{
26+
return next.handle(req);
27+
}
28+
29+
}
30+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { TestBed } from '@angular/core/testing';
2+
import { Overlay } from '@angular/cdk/overlay';
3+
4+
import { SpinnerOverlayService } from './spinner-overlay.service';
5+
import { SpinnerInterceptor } from '../interceptors/spinner.interceptor';
6+
import { HttpEvent, HttpHandler, HttpRequest, HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
7+
import { Observable, of } from 'rxjs';
8+
import { ComponentPortal } from 'ngx-toastr';
9+
10+
11+
describe('SpinnerOverlayService test', () => {
12+
13+
class MockHttpHandler extends HttpHandler {
14+
handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
15+
return of(new HttpResponse());
16+
}
17+
}
18+
19+
let spinnerService: SpinnerOverlayService;
20+
let spinnerInterceptor: SpinnerInterceptor;
21+
let mockHttpHandler: HttpHandler;
22+
let overlayRef: any;
23+
24+
beforeEach(() => {
25+
TestBed.configureTestingModule({
26+
providers: [
27+
Overlay,
28+
SpinnerInterceptor,
29+
{
30+
provide: HTTP_INTERCEPTORS,
31+
useClass: SpinnerInterceptor,
32+
multi: true,
33+
},
34+
],
35+
});
36+
spinnerService = TestBed.inject(SpinnerOverlayService);
37+
spinnerInterceptor = TestBed.inject(SpinnerInterceptor);
38+
mockHttpHandler = new MockHttpHandler();
39+
overlayRef = spinnerService.overlayRef;
40+
});
41+
42+
it('should be created', () => {
43+
expect(spinnerService).toBeTruthy();
44+
});
45+
46+
it('if request is made then spinnerService is show', () => {
47+
const request = new HttpRequest('GET', '/recent');
48+
spyOn(spinnerService, 'show');
49+
50+
spinnerInterceptor.intercept(request, mockHttpHandler);
51+
52+
expect(spinnerService.show).toHaveBeenCalled();
53+
expect(ComponentPortal).toBeTruthy();
54+
});
55+
56+
57+
it('if hide calls detach method of overlayRef and then sets it to undefined', () => {
58+
spyOn(spinnerService, 'hide');
59+
60+
spinnerService.hide();
61+
62+
expect(spinnerService.hide).toHaveBeenCalled();
63+
expect(overlayRef).toBeUndefined();
64+
});
65+
66+
});

0 commit comments

Comments
 (0)