From b3fd7fbf03f8425bdd24807be8dd6e20c2ec1277 Mon Sep 17 00:00:00 2001 From: Bastian Wagner Date: Mon, 9 Mar 2026 10:54:50 +0100 Subject: [PATCH] Unit tests --- .../realtime/sse/sse.controller.spec.ts | 48 +++++++++++++++++++ .../modules/realtime/sse/sse.controller.ts | 14 +----- api/src/modules/realtime/sse/sse.module.ts | 3 +- client/src/app/shared/api.service.ts | 12 +++-- 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/api/src/modules/realtime/sse/sse.controller.spec.ts b/api/src/modules/realtime/sse/sse.controller.spec.ts index d10cbac..169c3ed 100644 --- a/api/src/modules/realtime/sse/sse.controller.spec.ts +++ b/api/src/modules/realtime/sse/sse.controller.spec.ts @@ -1,5 +1,11 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SseController } from './sse.controller'; +import { SseTicketService } from './sse-ticket.service'; +import { UserService } from 'src/modules/user/user.service'; +import { JwtService } from '@nestjs/jwt'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { AuthService } from 'src/modules/auth/auth.service'; +import { SseService } from './sse.service'; describe('SseController', () => { let controller: SseController; @@ -7,6 +13,16 @@ describe('SseController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [SseController], + imports: [ConfigModule], + providers: [ + ConfigService, + { provide: JwtService, useClass: MockJwTService }, + { provide: SseTicketService, useClass: MockSseTicketService }, + { provide: UserService, useClass: MockUserService }, + { provide: AuthService, useClass: MockAuthService }, + { provide: SseService, useClass: MockSSEService } + + ] }).compile(); controller = module.get(SseController); @@ -15,4 +31,36 @@ describe('SseController', () => { it('should be defined', () => { expect(controller).toBeDefined(); }); + + it('should generate a Ticket', () => { + const t = controller.getTicket({ user: { id: 123}} as any); + expect(controller['ticketService'].generateTicket).toHaveBeenCalled() + }); + + it('should generate a SSE stream', async () => { + await controller.sse('abc'); + expect(controller["sseService"].register).toHaveBeenCalled(); + }) }); + + +class MockSseTicketService { + generateTicket = jest.fn().mockImplementation( (id) => { + return {ticket: 'test-ticket-id'} + }); + + getUserIdToTicket = jest.fn().mockImplementation( (ticket) => { + return 99; + }) +} + +class MockSSEService { + register = jest.fn().mockImplementation( (id) => { + return new Promise(resolve => resolve(null)) + }) +} + +class MockUserService { } + +class MockJwTService {} +class MockAuthService {} \ No newline at end of file diff --git a/api/src/modules/realtime/sse/sse.controller.ts b/api/src/modules/realtime/sse/sse.controller.ts index 3b202e6..2b58de8 100644 --- a/api/src/modules/realtime/sse/sse.controller.ts +++ b/api/src/modules/realtime/sse/sse.controller.ts @@ -2,17 +2,13 @@ import { Controller, Get, Param, Query, Req, Sse, UnauthorizedException, UseGuar import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface'; import { SseTicketService } from './sse-ticket.service'; import { AuthGuard } from 'src/core/guards/auth.guard'; -import { Observable, interval, map } from 'rxjs'; -import { KeyService } from 'src/modules/key/key.service'; -import { AuthService } from 'src/modules/auth/auth.service'; -import { User } from 'src/model/entitites'; -import { UserService } from 'src/modules/user/user.service'; +import { Observable } from 'rxjs'; import { SseService } from './sse.service'; @Controller('sse') export class SseController { - constructor(private ticketService: SseTicketService, private sseService: SseService, private userService: UserService) {} + constructor(private ticketService: SseTicketService, private sseService: SseService) {} @UseGuards(AuthGuard) @Get('ticket') @@ -24,15 +20,9 @@ export class SseController { async sse(@Query('ticket') ticket: string): Promise> { const userId = this.ticketService.getUserIdToTicket(ticket); if (!userId) throw new UnauthorizedException('Invalid/expired ticket'); - const user = await this.getUserToId(userId); if (!userId) throw new UnauthorizedException('Invalid/expired ticket'); return this.sseService.register(userId); } - - private async getUserToId(userId: string): Promise { - const user = await this.userService.getUserById(userId); - return Promise.resolve(user); - } } diff --git a/api/src/modules/realtime/sse/sse.module.ts b/api/src/modules/realtime/sse/sse.module.ts index 7b5e179..47e50f1 100644 --- a/api/src/modules/realtime/sse/sse.module.ts +++ b/api/src/modules/realtime/sse/sse.module.ts @@ -5,13 +5,12 @@ import { SseTicketService } from './sse-ticket.service'; import { AuthModule } from 'src/modules/auth/auth.module'; import { SharedServiceModule } from 'src/shared/service/shared.service.module'; import { MailModule } from 'src/modules/mail/mail.module'; -import { UserService } from 'src/modules/user/user.service'; import { SseService } from './sse.service'; @Module({ controllers: [SseController], imports: [DatabaseModule, AuthModule, SharedServiceModule, MailModule], - providers: [SseTicketService, UserService, SseService], + providers: [SseTicketService, SseService], exports: [SseService] }) export class SseModule {} diff --git a/client/src/app/shared/api.service.ts b/client/src/app/shared/api.service.ts index 1c95ac2..6c3819f 100644 --- a/client/src/app/shared/api.service.ts +++ b/client/src/app/shared/api.service.ts @@ -431,12 +431,15 @@ export class ApiService { private async setupKeyFeed() { const ticket = await this.getSSETicket(); - - console.log(ticket) const sseSource = new EventSource('api/sse/key?ticket=' + ticket); sseSource.addEventListener('message', (e: MessageEvent) => { - console.log(e.data) - this.keys.next(JSON.parse(e.data)) + try { + const keys = JSON.parse(e.data) as IKey[]; + this.keys.next(keys) + } + catch { + this.toast.error('Fehler beim Empfangen der Schlüssel. Bitte später versuchen') + } }) sseSource.addEventListener('error', (error) => { console.error(error) @@ -448,7 +451,6 @@ export class ApiService { this.http.get<{ ticket: string }>('api/sse/ticket').subscribe({ next: (ticket) => { return resolve(ticket.ticket) - } }) })