From 6b1daad71822b86a4e977ac34aba95633d122893 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 16:22:20 +0000 Subject: [PATCH 1/2] test(auth): add comprehensive unit tests for AuthService Cover register, login, getCurrentUser, and logout methods including success paths, error handling, localStorage interactions, and signal state. Co-authored-by: thivernale --- src/app/auth/services/auth.service.spec.ts | 294 ++++++++++++++++++++- 1 file changed, 292 insertions(+), 2 deletions(-) diff --git a/src/app/auth/services/auth.service.spec.ts b/src/app/auth/services/auth.service.spec.ts index f1251ca..fc553cd 100644 --- a/src/app/auth/services/auth.service.spec.ts +++ b/src/app/auth/services/auth.service.spec.ts @@ -1,16 +1,306 @@ +import { provideHttpClient } from '@angular/common/http'; +import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; - +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { environment } from '../../../environments/environment'; +import { User, UserResponse } from '../types/user.interface'; import { AuthService } from './auth.service'; +const mockUser: User = { + email: 'test@example.com', + token: 'mock-token-123', + username: 'testuser', +}; + +const mockUserResponse: UserResponse = { user: mockUser }; + describe('AuthService', () => { let service: AuthService; + let httpTesting: HttpTestingController; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [ + provideHttpClient(), + provideHttpClientTesting(), + ], + }); service = TestBed.inject(AuthService); + httpTesting = TestBed.inject(HttpTestingController); + localStorage.clear(); + }); + + afterEach(() => { + httpTesting.verify(); + localStorage.clear(); + vi.restoreAllMocks(); }); it('should be created', () => { expect(service).toBeTruthy(); }); + + it('should initialize currentUserSignal as undefined', () => { + expect(service.currentUserSignal()).toBeUndefined(); + }); + + describe('register()', () => { + const registerModel = { email: 'test@example.com', password: 'password123', username: 'testuser' }; + + it('should POST to the correct URL', () => { + service.register(registerModel).subscribe(); + + const req = httpTesting.expectOne(`${environment.authUrl}/api/users`); + expect(req.request.method).toBe('POST'); + req.flush(mockUserResponse); + }); + + it('should send the user in the request body', () => { + service.register(registerModel).subscribe(); + + const req = httpTesting.expectOne(`${environment.authUrl}/api/users`); + expect(req.request.body).toEqual({ user: registerModel }); + req.flush(mockUserResponse); + }); + + it('should set Content-Type header', () => { + service.register(registerModel).subscribe(); + + const req = httpTesting.expectOne(`${environment.authUrl}/api/users`); + expect(req.request.headers.get('Content-Type')).toBe('application/json; charset=utf-8'); + req.flush(mockUserResponse); + }); + + it('should store token in localStorage on success', () => { + service.register(registerModel).subscribe(); + + const req = httpTesting.expectOne(`${environment.authUrl}/api/users`); + req.flush(mockUserResponse); + + expect(localStorage.getItem('token')).toBe(mockUser.token); + }); + + it('should set currentUserSignal on success', () => { + service.register(registerModel).subscribe(); + + const req = httpTesting.expectOne(`${environment.authUrl}/api/users`); + req.flush(mockUserResponse); + + expect(service.currentUserSignal()).toEqual(mockUser); + }); + + it('should emit the user on success', () => { + let emittedUser: User | undefined; + service.register(registerModel).subscribe(user => (emittedUser = user)); + + const req = httpTesting.expectOne(`${environment.authUrl}/api/users`); + req.flush(mockUserResponse); + + expect(emittedUser).toEqual(mockUser); + }); + + it('should throw formatted error on HTTP error', () => { + const errorResponse = { errors: { email: ['is already taken'] } }; + let thrownError: Error | undefined; + + service.register(registerModel).subscribe({ + error: (err: Error) => (thrownError = err), + }); + + const req = httpTesting.expectOne(`${environment.authUrl}/api/users`); + req.flush(errorResponse, { status: 422, statusText: 'Unprocessable Entity' }); + + expect(thrownError).toBeInstanceOf(Error); + expect(thrownError!.message).toContain('