diff --git a/src/app/pages/profile/profile.component.spec.ts b/src/app/pages/profile/profile.component.spec.ts index 8f879141..38def172 100644 --- a/src/app/pages/profile/profile.component.spec.ts +++ b/src/app/pages/profile/profile.component.spec.ts @@ -38,6 +38,8 @@ class AlertServiceMock { class AuthServiceMock { logout() { } + refreshToken() { } + showRenewTokenDialog() { } } class ConfirmationServiceMock { @@ -125,6 +127,49 @@ describe('ProfileComponent', () => { expect(mySpy).toHaveBeenCalled(); }); + it('should call refreshToken and set token in localStorage', () => { + spyOn(authService, 'refreshToken').and.returnValue(of({ access_token: 'new_access_token' })); + + component.renewToken(); + + expect(authService.refreshToken).toHaveBeenCalled(); + expect(localStorage.getItem('token')).toEqual('new_access_token'); + }); + + it('should handle error when renewing token', () => { + spyOn(authService, 'refreshToken').and.returnValue(throwError('error')); + spyOn(console, 'error'); + + component.renewToken(); + + expect(authService.refreshToken).toHaveBeenCalled(); + expect(console.error).toHaveBeenCalledWith('Failed to refresh token:', 'error'); + }); + it('should show renew token dialog', () => { + const confirmSpy = spyOn(confirmationService, 'confirm').and.callFake((params: any) => { + params.accept(); + params.reject(); + + // Return a mock ConfirmationService instance + return {} as ConfirmationService; + }); + const renewTokenSpy = spyOn(component, 'renewToken'); + const logoutSpy = spyOn(authService, 'logout'); + + component.showRenewTokenDialog(); + + expect(confirmSpy).toHaveBeenCalledWith({ + message: 'Deseja se manter logado?', + header: 'Confirmação', + key: 'myDialog', + icon: 'pi pi-exclamation-triangle', + accept: jasmine.any(Function), + reject: jasmine.any(Function), + }); + expect(renewTokenSpy).toHaveBeenCalled(); + expect(logoutSpy).toHaveBeenCalled(); + }); + it('should call navigatorEdit when editUser is clicked', () => { spyOn(component, 'navigatorEdit').and.callThrough(); const navigateSpy = spyOn(router, 'navigate'); diff --git a/src/app/pages/profile/profile.component.ts b/src/app/pages/profile/profile.component.ts index f147e0a5..520a564e 100644 --- a/src/app/pages/profile/profile.component.ts +++ b/src/app/pages/profile/profile.component.ts @@ -7,6 +7,7 @@ import { AlertService } from 'src/app/services/alert.service'; import { ConfirmationService, MessageService } from 'primeng/api'; import { AuthService } from 'src/app/services/auth.service'; import { HttpErrorResponse } from '@angular/common/http'; +import { take, timer } from 'rxjs'; type ErrorResponseType = HttpErrorResponse; @@ -32,6 +33,11 @@ export class ProfileComponent { ngOnInit(): void { this.setUserIdFromToken(localStorage.getItem('token') as string); this.getUser(); + timer(15 * 60 * 1000) + .pipe(take(1)) + .subscribe(() => { + this.showRenewTokenDialog(); + }); } setUserIdFromToken(token: string) { @@ -91,6 +97,35 @@ export class ProfileComponent { }); } + showRenewTokenDialog() { + this.confirmationService.confirm({ + message: 'Deseja se manter logado?', + header: 'Confirmação', + key: 'myDialog', + icon: 'pi pi-exclamation-triangle', + accept: () => { + this.renewToken(); + }, + reject: () => { + this.authService.logout(); + }, + }); + } + + renewToken() { + this.authService.refreshToken().subscribe({ + next: (response) => { + if (response?.access_token) { + localStorage.setItem('token', response.access_token); + } + }, + error: (error: ErrorResponseType) => { + console.error('Failed to refresh token:', error); + this.authService.logout(); + } + }); + } + navigatorEdit(): void { this.router.navigate([`/editUser/${this.user.id}`]); } diff --git a/src/app/services/auth.service.spec.ts b/src/app/services/auth.service.spec.ts index f5736b2e..29599618 100644 --- a/src/app/services/auth.service.spec.ts +++ b/src/app/services/auth.service.spec.ts @@ -118,6 +118,18 @@ describe('AuthService', () => { req.flush(userResponse); }); + it('should refresh token', () => { + const dummyResponse = { access_token: 'dummyToken' }; + + service.refreshToken().subscribe(res => { + expect(res).toEqual(dummyResponse); + }); + + const req = httpMock.expectOne(`${service.usersAPIURL}/auth/refresh`); + expect(req.request.method).toBe('POST'); + req.flush(dummyResponse); + }); + it('should logout', () => { localStorage.setItem('token', 'testtoken'); service.logout(); diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts index c91004b4..55269e4b 100644 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -45,7 +45,11 @@ export class AuthService { const token = localStorage.getItem('token'); return !!token; } - + + refreshToken(): Observable { + return this.http.post(`${this.usersAPIURL}/auth/refresh`, null); + } + logout(): void { localStorage.removeItem('token'); this.router.navigate(['/login']);