Unit tests

This commit is contained in:
Bastian Wagner
2026-03-09 10:54:50 +01:00
parent ac2117b64b
commit b3fd7fbf03
4 changed files with 58 additions and 19 deletions

View File

@@ -1,5 +1,11 @@
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { SseController } from './sse.controller'; 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', () => { describe('SseController', () => {
let controller: SseController; let controller: SseController;
@@ -7,6 +13,16 @@ describe('SseController', () => {
beforeEach(async () => { beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({ const module: TestingModule = await Test.createTestingModule({
controllers: [SseController], 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(); }).compile();
controller = module.get<SseController>(SseController); controller = module.get<SseController>(SseController);
@@ -15,4 +31,36 @@ describe('SseController', () => {
it('should be defined', () => { it('should be defined', () => {
expect(controller).toBeDefined(); 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 {}

View File

@@ -2,17 +2,13 @@ import { Controller, Get, Param, Query, Req, Sse, UnauthorizedException, UseGuar
import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface'; import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface';
import { SseTicketService } from './sse-ticket.service'; import { SseTicketService } from './sse-ticket.service';
import { AuthGuard } from 'src/core/guards/auth.guard'; import { AuthGuard } from 'src/core/guards/auth.guard';
import { Observable, interval, map } from 'rxjs'; import { Observable } 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 { SseService } from './sse.service'; import { SseService } from './sse.service';
@Controller('sse') @Controller('sse')
export class SseController { export class SseController {
constructor(private ticketService: SseTicketService, private sseService: SseService, private userService: UserService) {} constructor(private ticketService: SseTicketService, private sseService: SseService) {}
@UseGuards(AuthGuard) @UseGuards(AuthGuard)
@Get('ticket') @Get('ticket')
@@ -24,15 +20,9 @@ export class SseController {
async sse(@Query('ticket') ticket: string): Promise<Observable<any>> { async sse(@Query('ticket') ticket: string): Promise<Observable<any>> {
const userId = this.ticketService.getUserIdToTicket(ticket); const userId = this.ticketService.getUserIdToTicket(ticket);
if (!userId) throw new UnauthorizedException('Invalid/expired ticket'); if (!userId) throw new UnauthorizedException('Invalid/expired ticket');
const user = await this.getUserToId(userId);
if (!userId) throw new UnauthorizedException('Invalid/expired ticket'); if (!userId) throw new UnauthorizedException('Invalid/expired ticket');
return this.sseService.register(userId); return this.sseService.register(userId);
} }
private async getUserToId(userId: string): Promise<User> {
const user = await this.userService.getUserById(userId);
return Promise.resolve(user);
}
} }

View File

@@ -5,13 +5,12 @@ import { SseTicketService } from './sse-ticket.service';
import { AuthModule } from 'src/modules/auth/auth.module'; import { AuthModule } from 'src/modules/auth/auth.module';
import { SharedServiceModule } from 'src/shared/service/shared.service.module'; import { SharedServiceModule } from 'src/shared/service/shared.service.module';
import { MailModule } from 'src/modules/mail/mail.module'; import { MailModule } from 'src/modules/mail/mail.module';
import { UserService } from 'src/modules/user/user.service';
import { SseService } from './sse.service'; import { SseService } from './sse.service';
@Module({ @Module({
controllers: [SseController], controllers: [SseController],
imports: [DatabaseModule, AuthModule, SharedServiceModule, MailModule], imports: [DatabaseModule, AuthModule, SharedServiceModule, MailModule],
providers: [SseTicketService, UserService, SseService], providers: [SseTicketService, SseService],
exports: [SseService] exports: [SseService]
}) })
export class SseModule {} export class SseModule {}

View File

@@ -431,12 +431,15 @@ export class ApiService {
private async setupKeyFeed() { private async setupKeyFeed() {
const ticket = await this.getSSETicket(); const ticket = await this.getSSETicket();
console.log(ticket)
const sseSource = new EventSource('api/sse/key?ticket=' + ticket); const sseSource = new EventSource('api/sse/key?ticket=' + ticket);
sseSource.addEventListener('message', (e: MessageEvent<string>) => { sseSource.addEventListener('message', (e: MessageEvent<string>) => {
console.log(e.data) try {
this.keys.next(JSON.parse(e.data)) 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) => { sseSource.addEventListener('error', (error) => {
console.error(error) console.error(error)
@@ -448,7 +451,6 @@ export class ApiService {
this.http.get<{ ticket: string }>('api/sse/ticket').subscribe({ this.http.get<{ ticket: string }>('api/sse/ticket').subscribe({
next: (ticket) => { next: (ticket) => {
return resolve(ticket.ticket) return resolve(ticket.ticket)
} }
}) })
}) })