website refactor
This commit is contained in:
@@ -9,7 +9,7 @@ describe('Default avatar assets (HTTP)', () => {
|
||||
const originalEnv = { ...process.env };
|
||||
|
||||
let module: TestingModule | undefined;
|
||||
let app: any;
|
||||
let app: import("@nestjs/common").INestApplication;
|
||||
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
|
||||
@@ -35,6 +35,8 @@ describe('MediaController', () => {
|
||||
deleteMedia: ReturnType<typeof vi.fn>;
|
||||
getAvatar: ReturnType<typeof vi.fn>;
|
||||
updateAvatar: ReturnType<typeof vi.fn>;
|
||||
getUploadedMedia: ReturnType<typeof vi.fn>;
|
||||
resolveMediaReference: ReturnType<typeof vi.fn>;
|
||||
};
|
||||
let generationService: MediaGenerationService & {
|
||||
generateDriverAvatar: ReturnType<typeof vi.fn>;
|
||||
@@ -57,6 +59,8 @@ describe('MediaController', () => {
|
||||
deleteMedia: vi.fn(),
|
||||
getAvatar: vi.fn(),
|
||||
updateAvatar: vi.fn(),
|
||||
getUploadedMedia: vi.fn(),
|
||||
resolveMediaReference: vi.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -97,8 +101,8 @@ describe('MediaController', () => {
|
||||
}).compile();
|
||||
|
||||
controller = module.get<MediaController>(MediaController);
|
||||
service = module.get(MediaService) as any;
|
||||
generationService = module.get(MediaGenerationService) as any;
|
||||
service = module.get(MediaService) as never;
|
||||
generationService = module.get(MediaGenerationService) as never;
|
||||
});
|
||||
|
||||
const createMockResponse = (): Response => {
|
||||
@@ -375,6 +379,7 @@ describe('MediaController', () => {
|
||||
};
|
||||
const mockService = {
|
||||
getMedia: vi.fn().mockResolvedValue({ id: mediaId }),
|
||||
getUploadedMedia: vi.fn().mockResolvedValue({ bytes: pngBuffer, contentType: 'image/png' }),
|
||||
};
|
||||
|
||||
const module = await Test.createTestingModule({
|
||||
@@ -409,8 +414,7 @@ describe('MediaController', () => {
|
||||
await testController.getUploadedMedia(mediaId, res);
|
||||
|
||||
expect(mockService.getMedia).toHaveBeenCalledWith(mediaId);
|
||||
expect(mockStorage.getBytes).toHaveBeenCalledWith('uploaded/media-123');
|
||||
expect(mockStorage.getMetadata).toHaveBeenCalledWith('uploaded/media-123');
|
||||
expect(mockService.getUploadedMedia).toHaveBeenCalledWith('uploaded/media-123');
|
||||
expect(res.setHeader).toHaveBeenCalledWith('Content-Type', 'image/png');
|
||||
expect(res.setHeader).toHaveBeenCalledWith('Cache-Control', 'public, max-age=31536000, immutable');
|
||||
expect(res.status).toHaveBeenCalledWith(200);
|
||||
@@ -569,7 +573,7 @@ describe('MediaController', () => {
|
||||
});
|
||||
|
||||
describe('auth guards (HTTP)', () => {
|
||||
let app: any;
|
||||
let app: import("@nestjs/common").INestApplication;
|
||||
|
||||
const sessionPort: { getCurrentSession: () => Promise<null | { token: string; user: { id: string } }> } = {
|
||||
getCurrentSession: vi.fn(async () => null),
|
||||
@@ -603,6 +607,8 @@ describe('MediaController', () => {
|
||||
uploadMedia: vi.fn(),
|
||||
getAvatar: vi.fn(),
|
||||
updateAvatar: vi.fn(),
|
||||
getUploadedMedia: vi.fn(async () => ({ bytes: Buffer.from([]), contentType: 'image/png' })),
|
||||
resolveMediaReference: vi.fn(async () => '/path'),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -657,9 +663,9 @@ describe('MediaController', () => {
|
||||
|
||||
const reflector = new Reflector();
|
||||
app.useGlobalGuards(
|
||||
new AuthenticationGuard(sessionPort as any),
|
||||
new AuthorizationGuard(reflector, authorizationService as any),
|
||||
new FeatureAvailabilityGuard(reflector, policyService as any),
|
||||
new AuthenticationGuard(sessionPort as never),
|
||||
new AuthorizationGuard(reflector, authorizationService as never),
|
||||
new FeatureAvailabilityGuard(reflector, policyService as never),
|
||||
);
|
||||
|
||||
await app.init();
|
||||
|
||||
@@ -19,9 +19,7 @@ import type { MulterFile } from './types/MulterFile';
|
||||
import { MediaGenerationService } from '@core/media/domain/services/MediaGenerationService';
|
||||
import type { Logger } from '@core/shared/application/Logger';
|
||||
import { MediaReference } from '@core/domain/media/MediaReference';
|
||||
import { MediaResolverAdapter } from '@adapters/media/MediaResolverAdapter';
|
||||
import { LOGGER_TOKEN, MEDIA_STORAGE_PORT_TOKEN } from './MediaTokens';
|
||||
import type { MediaStoragePort } from '@core/media/application/ports/MediaStoragePort';
|
||||
import { LOGGER_TOKEN } from './MediaTokens';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs/promises';
|
||||
|
||||
@@ -36,8 +34,6 @@ export class MediaController {
|
||||
@Inject(MediaService) private readonly mediaService: MediaService,
|
||||
@Inject(MediaGenerationService) private readonly mediaGenerationService: MediaGenerationService,
|
||||
@Inject(LOGGER_TOKEN) private readonly logger: Logger,
|
||||
@Inject(MediaResolverAdapter) private readonly mediaResolver: MediaResolverAdapter,
|
||||
@Inject(MEDIA_STORAGE_PORT_TOKEN) private readonly mediaStorage: MediaStoragePort,
|
||||
) {}
|
||||
|
||||
@Post('avatar/generate')
|
||||
@@ -272,23 +268,19 @@ export class MediaController {
|
||||
// The mediaId is used as the storage key
|
||||
const storageKey = `uploaded/${mediaId}`;
|
||||
|
||||
// Get file bytes from storage
|
||||
const bytes = await this.mediaStorage.getBytes!(storageKey);
|
||||
if (!bytes) {
|
||||
// Get file bytes from storage via service
|
||||
const result = await this.mediaService.getUploadedMedia(storageKey);
|
||||
if (!result) {
|
||||
this.logger.warn('[MediaController] Uploaded media file not found', { mediaId, storageKey });
|
||||
res.status(HttpStatus.NOT_FOUND).json({ error: 'Media file not found' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Get metadata to determine content type
|
||||
const metadata = await this.mediaStorage.getMetadata!(storageKey);
|
||||
const contentType = metadata?.contentType || 'application/octet-stream';
|
||||
|
||||
res.setHeader('Content-Type', contentType);
|
||||
res.setHeader('Content-Type', result.contentType);
|
||||
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
|
||||
res.status(HttpStatus.OK).send(bytes);
|
||||
res.status(HttpStatus.OK).send(result.bytes);
|
||||
|
||||
this.logger.info('[MediaController] Uploaded media served', { mediaId, storageKey, size: bytes.length });
|
||||
this.logger.info('[MediaController] Uploaded media served', { mediaId, storageKey, size: result.bytes.length });
|
||||
}
|
||||
|
||||
@Public()
|
||||
@@ -339,7 +331,7 @@ export class MediaController {
|
||||
|
||||
if (ref) {
|
||||
refHash = ref.hash();
|
||||
resolvedPath = await this.mediaResolver.resolve(ref);
|
||||
resolvedPath = await this.mediaService.resolveMediaReference(ref);
|
||||
|
||||
if (!resolvedPath) {
|
||||
notes.push('Resolver returned null');
|
||||
@@ -382,7 +374,7 @@ export class MediaController {
|
||||
): Promise<void> {
|
||||
this.logger.debug('[MediaController] Getting media details', { mediaId });
|
||||
const dto: GetMediaOutputDTO | null = await this.mediaService.getMedia(mediaId);
|
||||
|
||||
|
||||
if (dto) {
|
||||
this.logger.info('[MediaController] Media details found', { mediaId });
|
||||
res.status(HttpStatus.OK).json(dto);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { FaceValidationPort } from '@core/media/application/ports/FaceValidation
|
||||
import { AvatarGenerationPort } from '@core/media/application/ports/AvatarGenerationPort';
|
||||
import { MediaStoragePort } from '@core/media/application/ports/MediaStoragePort';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { MediaResolverPort } from '@core/ports/media/MediaResolverPort';
|
||||
|
||||
// Import use cases
|
||||
import { RequestAvatarGenerationUseCase } from '@core/media/application/use-cases/RequestAvatarGenerationUseCase';
|
||||
@@ -16,6 +17,8 @@ import { GetMediaUseCase } from '@core/media/application/use-cases/GetMediaUseCa
|
||||
import { DeleteMediaUseCase } from '@core/media/application/use-cases/DeleteMediaUseCase';
|
||||
import { GetAvatarUseCase } from '@core/media/application/use-cases/GetAvatarUseCase';
|
||||
import { UpdateAvatarUseCase } from '@core/media/application/use-cases/UpdateAvatarUseCase';
|
||||
import { ResolveMediaReferenceUseCase } from '@core/media/application/use-cases/ResolveMediaReferenceUseCase';
|
||||
import { GetUploadedMediaUseCase } from '@core/media/application/use-cases/GetUploadedMediaUseCase';
|
||||
|
||||
// Import presenters
|
||||
import { RequestAvatarGenerationPresenter } from './presenters/RequestAvatarGenerationPresenter';
|
||||
@@ -39,6 +42,9 @@ import {
|
||||
DELETE_MEDIA_USE_CASE_TOKEN,
|
||||
GET_AVATAR_USE_CASE_TOKEN,
|
||||
UPDATE_AVATAR_USE_CASE_TOKEN,
|
||||
RESOLVE_MEDIA_REFERENCE_USE_CASE_TOKEN,
|
||||
GET_UPLOADED_MEDIA_USE_CASE_TOKEN,
|
||||
MEDIA_RESOLVER_PORT_TOKEN,
|
||||
} from './MediaTokens';
|
||||
|
||||
export * from './MediaTokens';
|
||||
@@ -92,7 +98,7 @@ const initLogger = InitializationLogger.getInstance();
|
||||
export const MediaProviders: Provider[] = createLoggedProviders([
|
||||
MediaGenerationService,
|
||||
{
|
||||
provide: MediaResolverAdapter,
|
||||
provide: MEDIA_RESOLVER_PORT_TOKEN,
|
||||
useFactory: () => new MediaResolverAdapter({}),
|
||||
},
|
||||
RequestAvatarGenerationPresenter,
|
||||
@@ -156,4 +162,16 @@ export const MediaProviders: Provider[] = createLoggedProviders([
|
||||
new UpdateAvatarUseCase(avatarRepo, logger),
|
||||
inject: [AVATAR_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
], initLogger);
|
||||
{
|
||||
provide: RESOLVE_MEDIA_REFERENCE_USE_CASE_TOKEN,
|
||||
useFactory: (mediaResolver: MediaResolverPort) =>
|
||||
new ResolveMediaReferenceUseCase(mediaResolver),
|
||||
inject: [MEDIA_RESOLVER_PORT_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GET_UPLOADED_MEDIA_USE_CASE_TOKEN,
|
||||
useFactory: (mediaStorage: MediaStoragePort) =>
|
||||
new GetUploadedMediaUseCase(mediaStorage),
|
||||
inject: [MEDIA_STORAGE_PORT_TOKEN],
|
||||
},
|
||||
], initLogger);
|
||||
|
||||
@@ -16,28 +16,30 @@ describe('MediaService', () => {
|
||||
};
|
||||
|
||||
const service = new MediaService(
|
||||
requestAvatarGenerationUseCase as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
requestAvatarGenerationPresenter as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
requestAvatarGenerationUseCase as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
requestAvatarGenerationPresenter as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(
|
||||
service.requestAvatarGeneration({ userId: 'u1', facePhotoData: {} as any, suitColor: 'red' as any }),
|
||||
service.requestAvatarGeneration({ userId: 'u1', facePhotoData: {} as never, suitColor: 'red' as never }),
|
||||
).resolves.toEqual({ success: true, requestId: 'r1', avatarUrls: ['u1'], errorMessage: '' });
|
||||
|
||||
expect(requestAvatarGenerationUseCase.execute).toHaveBeenCalledWith({
|
||||
userId: 'u1',
|
||||
facePhotoData: {} as any,
|
||||
facePhotoData: {} as never,
|
||||
suitColor: 'red',
|
||||
});
|
||||
expect(requestAvatarGenerationPresenter.transform).toHaveBeenCalledWith({ requestId: 'r1', status: 'completed', avatarUrls: ['u1'] });
|
||||
@@ -45,23 +47,25 @@ describe('MediaService', () => {
|
||||
|
||||
it('requestAvatarGeneration returns failure DTO on error', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR', details: { message: 'fail' } })) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: { success: true } } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR', details: { message: 'fail' } })) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: { success: true } } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(
|
||||
service.requestAvatarGeneration({ userId: 'u1', facePhotoData: {} as any, suitColor: 'red' as any }),
|
||||
service.requestAvatarGeneration({ userId: 'u1', facePhotoData: {} as never, suitColor: 'red' as never }),
|
||||
).resolves.toEqual({
|
||||
success: false,
|
||||
requestId: '',
|
||||
@@ -78,30 +82,32 @@ describe('MediaService', () => {
|
||||
const uploadMediaUseCase = { execute: vi.fn(async () => Result.ok({ mediaId: 'm1', url: 'https://example.com/m1.png' })) };
|
||||
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
uploadMediaUseCase as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
uploadMediaPresenter as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
uploadMediaUseCase as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
uploadMediaPresenter as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(
|
||||
service.uploadMedia({ file: {} as any, userId: 'u1', metadata: { a: 1 } } as any),
|
||||
service.uploadMedia({ file: {} as never, userId: 'u1', metadata: { a: 1 } } as never),
|
||||
).resolves.toEqual({
|
||||
success: true,
|
||||
mediaId: 'm1',
|
||||
});
|
||||
|
||||
expect(uploadMediaUseCase.execute).toHaveBeenCalledWith({
|
||||
file: {} as any,
|
||||
file: {} as never,
|
||||
uploadedBy: 'u1',
|
||||
metadata: { a: 1 },
|
||||
});
|
||||
@@ -116,23 +122,25 @@ describe('MediaService', () => {
|
||||
};
|
||||
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
uploadMediaUseCase as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
uploadMediaPresenter as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
uploadMediaUseCase as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
uploadMediaPresenter as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.uploadMedia({ file: {} as any } as any)).resolves.toEqual({ success: true, mediaId: 'm1' });
|
||||
expect(uploadMediaUseCase.execute).toHaveBeenCalledWith({ file: {} as any, uploadedBy: '', metadata: {} });
|
||||
await expect(service.uploadMedia({ file: {} as never } as never)).resolves.toEqual({ success: true, mediaId: 'm1' });
|
||||
expect(uploadMediaUseCase.execute).toHaveBeenCalledWith({ file: {} as never, uploadedBy: '', metadata: {} });
|
||||
expect(uploadMediaPresenter.transform).toHaveBeenCalledWith({ mediaId: 'm1', url: 'https://example.com/m1.png' });
|
||||
});
|
||||
|
||||
@@ -142,22 +150,24 @@ describe('MediaService', () => {
|
||||
};
|
||||
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
uploadMediaUseCase as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: { success: true } } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
uploadMediaUseCase as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: { success: true } } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.uploadMedia({ file: {} as any, userId: 'u1' } as any)).resolves.toEqual({
|
||||
await expect(service.uploadMedia({ file: {} as never, userId: 'u1' } as never)).resolves.toEqual({
|
||||
success: false,
|
||||
error: 'nope',
|
||||
});
|
||||
@@ -172,19 +182,21 @@ describe('MediaService', () => {
|
||||
};
|
||||
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
getMediaUseCase as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
getMediaPresenter as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
getMediaUseCase as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
getMediaPresenter as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
const result = await service.getMedia('m1');
|
||||
@@ -195,19 +207,21 @@ describe('MediaService', () => {
|
||||
|
||||
it('getMedia returns null on MEDIA_NOT_FOUND', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'MEDIA_NOT_FOUND', details: { message: 'n/a' } })) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'MEDIA_NOT_FOUND', details: { message: 'n/a' } })) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.getMedia('m1')).resolves.toBeNull();
|
||||
@@ -215,19 +229,21 @@ describe('MediaService', () => {
|
||||
|
||||
it('getMedia throws on non-not-found error', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR', details: { message: 'boom' } })) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR', details: { message: 'boom' } })) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.getMedia('m1')).rejects.toThrow('boom');
|
||||
@@ -241,19 +257,21 @@ describe('MediaService', () => {
|
||||
};
|
||||
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
deleteMediaUseCase as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
deleteMediaPresenter as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
deleteMediaUseCase as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
deleteMediaPresenter as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.deleteMedia('m1')).resolves.toEqual({ success: true });
|
||||
@@ -263,19 +281,21 @@ describe('MediaService', () => {
|
||||
|
||||
it('deleteMedia returns failure DTO on error', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR', details: { message: 'nope' } })) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: { success: true } } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR', details: { message: 'nope' } })) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: { success: true } } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.deleteMedia('m1')).resolves.toEqual({ success: false, error: 'nope' });
|
||||
@@ -290,19 +310,21 @@ describe('MediaService', () => {
|
||||
};
|
||||
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
getAvatarUseCase as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
getAvatarPresenter as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
getAvatarUseCase as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
getAvatarPresenter as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.getAvatar('d1')).resolves.toEqual({ avatarUrl: 'https://example.com/avatar.png' });
|
||||
@@ -312,19 +334,21 @@ describe('MediaService', () => {
|
||||
|
||||
it('getAvatar returns null on AVATAR_NOT_FOUND', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'AVATAR_NOT_FOUND', details: { message: 'n/a' } })) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'AVATAR_NOT_FOUND', details: { message: 'n/a' } })) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.getAvatar('d1')).resolves.toBeNull();
|
||||
@@ -332,19 +356,21 @@ describe('MediaService', () => {
|
||||
|
||||
it('getAvatar throws on non-not-found error', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR', details: { message: 'boom' } })) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR', details: { message: 'boom' } })) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.getAvatar('d1')).rejects.toThrow('boom');
|
||||
@@ -358,44 +384,48 @@ describe('MediaService', () => {
|
||||
};
|
||||
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
updateAvatarUseCase as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
updateAvatarPresenter as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
updateAvatarUseCase as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
updateAvatarPresenter as never,
|
||||
);
|
||||
|
||||
await expect(service.updateAvatar('d1', { avatarUrl: 'u1' } as any)).resolves.toEqual({ success: true });
|
||||
await expect(service.updateAvatar('d1', { avatarUrl: 'u1' } as never)).resolves.toEqual({ success: true });
|
||||
expect(updateAvatarUseCase.execute).toHaveBeenCalledWith({ driverId: 'd1', mediaUrl: 'u1' });
|
||||
expect(updateAvatarPresenter.transform).toHaveBeenCalledWith({ avatarId: 'a1', driverId: 'd1' });
|
||||
});
|
||||
|
||||
it('updateAvatar returns failure DTO on error', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR', details: { message: 'nope' } })) } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: { success: true } } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR', details: { message: 'nope' } })) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: { success: true } } as never,
|
||||
);
|
||||
|
||||
await expect(service.updateAvatar('d1', { avatarUrl: 'u' } as any)).resolves.toEqual({
|
||||
await expect(service.updateAvatar('d1', { avatarUrl: 'u' } as never)).resolves.toEqual({
|
||||
success: false,
|
||||
error: 'nope',
|
||||
});
|
||||
@@ -403,23 +433,25 @@ describe('MediaService', () => {
|
||||
|
||||
it('requestAvatarGeneration uses fallback errorMessage when no details.message', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as any)) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: { success: true } } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as never)) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: { success: true } } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(
|
||||
service.requestAvatarGeneration({ userId: 'u1', facePhotoData: {} as any, suitColor: 'red' as any }),
|
||||
service.requestAvatarGeneration({ userId: 'u1', facePhotoData: {} as never, suitColor: 'red' as never }),
|
||||
).resolves.toEqual({
|
||||
success: false,
|
||||
requestId: '',
|
||||
@@ -430,26 +462,28 @@ describe('MediaService', () => {
|
||||
|
||||
it('uploadMedia uses fallback error when no details.message', async () => {
|
||||
const uploadMediaUseCase = {
|
||||
execute: vi.fn(async () => Result.err({ code: 'UPLOAD_FAILED' } as any)),
|
||||
execute: vi.fn(async () => Result.err({ code: 'UPLOAD_FAILED' } as never)),
|
||||
};
|
||||
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
uploadMediaUseCase as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: { success: true } } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
uploadMediaUseCase as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: { success: true } } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.uploadMedia({ file: {} as any, userId: 'u1' } as any)).resolves.toEqual({
|
||||
await expect(service.uploadMedia({ file: {} as never, userId: 'u1' } as never)).resolves.toEqual({
|
||||
success: false,
|
||||
error: 'Upload failed',
|
||||
});
|
||||
@@ -457,19 +491,21 @@ describe('MediaService', () => {
|
||||
|
||||
it('getMedia throws fallback message when no details.message and not not-found', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as any)) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as never)) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.getMedia('m1')).rejects.toThrow('Failed to get media');
|
||||
@@ -477,19 +513,21 @@ describe('MediaService', () => {
|
||||
|
||||
it('deleteMedia uses fallback message when no details.message', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as any)) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: { success: true } } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as never)) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: { success: true } } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.deleteMedia('m1')).resolves.toEqual({ success: false, error: 'Failed to delete media' });
|
||||
@@ -497,19 +535,21 @@ describe('MediaService', () => {
|
||||
|
||||
it('getAvatar throws fallback message when no details.message and not not-found', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as any)) } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as never)) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
);
|
||||
|
||||
await expect(service.getAvatar('d1')).rejects.toThrow('Failed to get avatar');
|
||||
@@ -517,24 +557,26 @@ describe('MediaService', () => {
|
||||
|
||||
it('updateAvatar uses fallback message when no details.message', async () => {
|
||||
const service = new MediaService(
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn() } as any,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as any)) } as any,
|
||||
logger as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: {} } as any,
|
||||
{ responseModel: { success: true } } as any,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as never)) } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
{ execute: vi.fn() } as never,
|
||||
logger as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: {} } as never,
|
||||
{ responseModel: { success: true } } as never,
|
||||
);
|
||||
|
||||
await expect(service.updateAvatar('d1', { avatarUrl: 'u' } as any)).resolves.toEqual({
|
||||
await expect(service.updateAvatar('d1', { avatarUrl: 'u' } as never)).resolves.toEqual({
|
||||
success: false,
|
||||
error: 'Failed to update avatar',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ import type { ValidateFaceInputDTO } from './dtos/ValidateFaceInputDTO';
|
||||
import type { ValidateFaceOutputDTO } from './dtos/ValidateFaceOutputDTO';
|
||||
import type { RacingSuitColor } from '@core/media/domain/types/AvatarGenerationRequest';
|
||||
import type { MulterFile } from './types/MulterFile';
|
||||
import type { MediaReference } from '@core/domain/media/MediaReference';
|
||||
|
||||
type RequestAvatarGenerationInput = RequestAvatarGenerationInputDTO;
|
||||
type UploadMediaInput = UploadMediaInputDTO;
|
||||
@@ -24,6 +25,8 @@ import { GetMediaUseCase } from '@core/media/application/use-cases/GetMediaUseCa
|
||||
import { DeleteMediaUseCase } from '@core/media/application/use-cases/DeleteMediaUseCase';
|
||||
import { GetAvatarUseCase } from '@core/media/application/use-cases/GetAvatarUseCase';
|
||||
import { UpdateAvatarUseCase } from '@core/media/application/use-cases/UpdateAvatarUseCase';
|
||||
import { ResolveMediaReferenceUseCase } from '@core/media/application/use-cases/ResolveMediaReferenceUseCase';
|
||||
import { GetUploadedMediaUseCase, type GetUploadedMediaResult } from '@core/media/application/use-cases/GetUploadedMediaUseCase';
|
||||
|
||||
// Presenters (now transformers)
|
||||
import { RequestAvatarGenerationPresenter } from './presenters/RequestAvatarGenerationPresenter';
|
||||
@@ -40,6 +43,8 @@ import {
|
||||
DELETE_MEDIA_USE_CASE_TOKEN,
|
||||
GET_AVATAR_USE_CASE_TOKEN,
|
||||
UPDATE_AVATAR_USE_CASE_TOKEN,
|
||||
RESOLVE_MEDIA_REFERENCE_USE_CASE_TOKEN,
|
||||
GET_UPLOADED_MEDIA_USE_CASE_TOKEN,
|
||||
LOGGER_TOKEN,
|
||||
} from './MediaTokens';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
@@ -59,6 +64,10 @@ export class MediaService {
|
||||
private readonly getAvatarUseCase: GetAvatarUseCase,
|
||||
@Inject(UPDATE_AVATAR_USE_CASE_TOKEN)
|
||||
private readonly updateAvatarUseCase: UpdateAvatarUseCase,
|
||||
@Inject(RESOLVE_MEDIA_REFERENCE_USE_CASE_TOKEN)
|
||||
private readonly resolveMediaReferenceUseCase: ResolveMediaReferenceUseCase,
|
||||
@Inject(GET_UPLOADED_MEDIA_USE_CASE_TOKEN)
|
||||
private readonly getUploadedMediaUseCase: GetUploadedMediaUseCase,
|
||||
@Inject(LOGGER_TOKEN)
|
||||
private readonly logger: Logger,
|
||||
private readonly requestAvatarGenerationPresenter: RequestAvatarGenerationPresenter,
|
||||
@@ -211,4 +220,20 @@ export class MediaService {
|
||||
|
||||
return { isValid: true };
|
||||
}
|
||||
}
|
||||
|
||||
async resolveMediaReference(reference: MediaReference): Promise<string | null> {
|
||||
const result = await this.resolveMediaReferenceUseCase.execute({ reference });
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.unwrapErr().message);
|
||||
}
|
||||
return result.unwrap();
|
||||
}
|
||||
|
||||
async getUploadedMedia(storageKey: string): Promise<GetUploadedMediaResult | null> {
|
||||
const result = await this.getUploadedMediaUseCase.execute({ storageKey });
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.unwrapErr().message);
|
||||
}
|
||||
return result.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,4 +11,7 @@ export const UPLOAD_MEDIA_USE_CASE_TOKEN = 'UploadMediaUseCase';
|
||||
export const GET_MEDIA_USE_CASE_TOKEN = 'GetMediaUseCase';
|
||||
export const DELETE_MEDIA_USE_CASE_TOKEN = 'DeleteMediaUseCase';
|
||||
export const GET_AVATAR_USE_CASE_TOKEN = 'GetAvatarUseCase';
|
||||
export const UPDATE_AVATAR_USE_CASE_TOKEN = 'UpdateAvatarUseCase';
|
||||
export const UPDATE_AVATAR_USE_CASE_TOKEN = 'UpdateAvatarUseCase';
|
||||
export const RESOLVE_MEDIA_REFERENCE_USE_CASE_TOKEN = 'ResolveMediaReferenceUseCase';
|
||||
export const GET_UPLOADED_MEDIA_USE_CASE_TOKEN = 'GetUploadedMediaUseCase';
|
||||
export const MEDIA_RESOLVER_PORT_TOKEN = 'MediaResolverPort';
|
||||
Reference in New Issue
Block a user