Files
gridpilot.gg/apps/api/src/domain/media/MediaController.test.ts
2025-12-22 15:58:20 +01:00

252 lines
8.4 KiB
TypeScript

import { Test, TestingModule } from '@nestjs/testing';
import { vi } from 'vitest';
import { MediaController } from './MediaController';
import { MediaService } from './MediaService';
import type { Response } from 'express';
import { RequestAvatarGenerationInputDTO } from './dtos/RequestAvatarGenerationInputDTO';
import { UploadMediaInputDTO } from './dtos/UploadMediaInputDTO';
import { RequestAvatarGenerationOutputDTO } from './dtos/RequestAvatarGenerationOutputDTO';
import { UploadMediaOutputDTO } from './dtos/UploadMediaOutputDTO';
import { GetMediaOutputDTO } from './dtos/GetMediaOutputDTO';
import { DeleteMediaOutputDTO } from './dtos/DeleteMediaOutputDTO';
import { GetAvatarOutputDTO } from './dtos/GetAvatarOutputDTO';
import { UpdateAvatarOutputDTO } from './dtos/UpdateAvatarOutputDTO';
import { UpdateAvatarInputDTO } from './dtos/UpdateAvatarInputDTO';
import type { MulterFile } from './types/MulterFile';
describe('MediaController', () => {
let controller: MediaController;
let service: MediaService & {
requestAvatarGeneration: ReturnType<typeof vi.fn>;
uploadMedia: ReturnType<typeof vi.fn>;
getMedia: ReturnType<typeof vi.fn>;
deleteMedia: ReturnType<typeof vi.fn>;
getAvatar: ReturnType<typeof vi.fn>;
updateAvatar: ReturnType<typeof vi.fn>;
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [MediaController],
providers: [
{
provide: MediaService,
useValue: {
requestAvatarGeneration: vi.fn(),
uploadMedia: vi.fn(),
getMedia: vi.fn(),
deleteMedia: vi.fn(),
getAvatar: vi.fn(),
updateAvatar: vi.fn(),
},
},
],
}).compile();
controller = module.get<MediaController>(MediaController);
service = module.get(MediaService) as MediaService & {
requestAvatarGeneration: ReturnType<typeof vi.fn>;
uploadMedia: ReturnType<typeof vi.fn>;
getMedia: ReturnType<typeof vi.fn>;
deleteMedia: ReturnType<typeof vi.fn>;
getAvatar: ReturnType<typeof vi.fn>;
updateAvatar: ReturnType<typeof vi.fn>;
};
});
const createMockResponse = (): Response => {
const res: Partial<Response> = {};
res.status = vi.fn().mockReturnValue(res as Response);
res.json = vi.fn().mockReturnValue(res as Response);
return res as Response;
};
describe('requestAvatarGeneration', () => {
it('should request avatar generation and return 201 on success', async () => {
const input: RequestAvatarGenerationInputDTO = {
userId: 'user-123',
facePhotoData: 'photo-data',
suitColor: 'red',
};
const dto: RequestAvatarGenerationOutputDTO = {
success: true,
requestId: 'req-123',
avatarUrls: ['https://example.com/avatar.png'],
};
service.requestAvatarGeneration.mockResolvedValue(dto);
const res = createMockResponse();
await controller.requestAvatarGeneration(input, res);
expect(service.requestAvatarGeneration).toHaveBeenCalledWith(input);
expect(res.status).toHaveBeenCalledWith(201);
expect(res.json).toHaveBeenCalledWith(dto);
});
it('should return 400 on failure', async () => {
const input: RequestAvatarGenerationInputDTO = {
userId: 'user-123',
facePhotoData: 'photo-data',
suitColor: 'red',
};
const dto: RequestAvatarGenerationOutputDTO = {
success: false,
errorMessage: 'Error',
};
service.requestAvatarGeneration.mockResolvedValue(dto);
const res = createMockResponse();
await controller.requestAvatarGeneration(input, res);
expect(service.requestAvatarGeneration).toHaveBeenCalledWith(input);
expect(res.status).toHaveBeenCalledWith(400);
expect(res.json).toHaveBeenCalledWith(dto);
});
});
describe('uploadMedia', () => {
it('should upload media and return 201 on success', async () => {
const file: MulterFile = { filename: 'file.jpg' } as MulterFile;
const input: UploadMediaInputDTO = { type: 'image' } as UploadMediaInputDTO;
const dto: UploadMediaOutputDTO = {
success: true,
mediaId: 'media-123',
url: 'https://example.com/file.jpg',
};
service.uploadMedia.mockResolvedValue(dto);
const res = createMockResponse();
await controller.uploadMedia(file, input, res);
expect(service.uploadMedia).toHaveBeenCalledWith({ ...input, file });
expect(res.status).toHaveBeenCalledWith(201);
expect(res.json).toHaveBeenCalledWith(dto);
});
it('should return 400 when upload fails', async () => {
const file: MulterFile = { filename: 'file.jpg' } as MulterFile;
const input: UploadMediaInputDTO = { type: 'image' } as UploadMediaInputDTO;
const dto: UploadMediaOutputDTO = {
success: false,
error: 'Upload failed',
};
service.uploadMedia.mockResolvedValue(dto);
const res = createMockResponse();
await controller.uploadMedia(file, input, res);
expect(service.uploadMedia).toHaveBeenCalledWith({ ...input, file });
expect(res.status).toHaveBeenCalledWith(400);
expect(res.json).toHaveBeenCalledWith(dto);
});
});
describe('getMedia', () => {
it('should return media if found', async () => {
const mediaId = 'media-123';
const dto: GetMediaOutputDTO = {
id: mediaId,
url: 'https://example.com/file.jpg',
type: 'image',
category: 'avatar',
uploadedAt: new Date(),
size: 123,
};
service.getMedia.mockResolvedValue(dto);
const res = createMockResponse();
await controller.getMedia(mediaId, res);
expect(service.getMedia).toHaveBeenCalledWith(mediaId);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.json).toHaveBeenCalledWith(dto);
});
it('should return 404 if not found', async () => {
const mediaId = 'media-123';
service.getMedia.mockResolvedValue(null);
const res = createMockResponse();
await controller.getMedia(mediaId, res);
expect(service.getMedia).toHaveBeenCalledWith(mediaId);
expect(res.status).toHaveBeenCalledWith(404);
expect(res.json).toHaveBeenCalledWith({ error: 'Media not found' });
});
});
describe('deleteMedia', () => {
it('should delete media and return result', async () => {
const mediaId = 'media-123';
const dto: DeleteMediaOutputDTO = {
success: true,
};
service.deleteMedia.mockResolvedValue(dto);
const res = createMockResponse();
await controller.deleteMedia(mediaId, res);
expect(service.deleteMedia).toHaveBeenCalledWith(mediaId);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.json).toHaveBeenCalledWith(dto);
});
});
describe('getAvatar', () => {
it('should return avatar if found', async () => {
const driverId = 'driver-123';
const dto: GetAvatarOutputDTO = {
avatarUrl: 'https://example.com/avatar.png',
};
service.getAvatar.mockResolvedValue(dto);
const res = createMockResponse();
await controller.getAvatar(driverId, res);
expect(service.getAvatar).toHaveBeenCalledWith(driverId);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.json).toHaveBeenCalledWith(dto);
});
it('should return 404 when avatar not found', async () => {
const driverId = 'driver-123';
service.getAvatar.mockResolvedValue(null);
const res = createMockResponse();
await controller.getAvatar(driverId, res);
expect(service.getAvatar).toHaveBeenCalledWith(driverId);
expect(res.status).toHaveBeenCalledWith(404);
expect(res.json).toHaveBeenCalledWith({ error: 'Avatar not found' });
});
});
describe('updateAvatar', () => {
it('should update avatar and return result', async () => {
const driverId = 'driver-123';
const input: UpdateAvatarInputDTO = { driverId: 'driver-123', avatarUrl: 'https://example.com/new-avatar.png' };
const dto: UpdateAvatarOutputDTO = {
success: true,
};
service.updateAvatar.mockResolvedValue(dto);
const res = createMockResponse();
await controller.updateAvatar(driverId, input, res);
expect(service.updateAvatar).toHaveBeenCalledWith(driverId, input);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.json).toHaveBeenCalledWith(dto);
});
});
});