jest.mock("uuid", () => ({ v4: jest.fn(() => "mocked-uuid"), })); import { CACHE_MANAGER } from "@nestjs/cache-manager"; import { BadRequestException } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { Test, TestingModule } from "@nestjs/testing"; import { MediaService } from "../media/media.service"; import { S3Service } from "../s3/s3.service"; import { ContentsService } from "./contents.service"; import { ContentsRepository } from "./repositories/contents.repository"; describe("ContentsService", () => { let service: ContentsService; let s3Service: S3Service; let mediaService: MediaService; const mockContentsRepository = { findAll: jest.fn(), count: jest.fn(), create: jest.fn(), incrementViews: jest.fn(), incrementUsage: jest.fn(), softDelete: jest.fn(), findOne: jest.fn(), findBySlug: jest.fn(), }; const mockS3Service = { getUploadUrl: jest.fn(), uploadFile: jest.fn(), }; const mockMediaService = { scanFile: jest.fn(), processImage: jest.fn(), processVideo: jest.fn(), }; const mockConfigService = { get: jest.fn(), }; const mockCacheManager = { clear: jest.fn(), del: jest.fn(), }; beforeEach(async () => { jest.clearAllMocks(); const module: TestingModule = await Test.createTestingModule({ providers: [ ContentsService, { provide: ContentsRepository, useValue: mockContentsRepository }, { provide: S3Service, useValue: mockS3Service }, { provide: MediaService, useValue: mockMediaService }, { provide: ConfigService, useValue: mockConfigService }, { provide: CACHE_MANAGER, useValue: mockCacheManager }, ], }).compile(); service = module.get(ContentsService); s3Service = module.get(S3Service); mediaService = module.get(MediaService); }); it("should be defined", () => { expect(service).toBeDefined(); }); describe("getUploadUrl", () => { it("should return an upload URL", async () => { mockS3Service.getUploadUrl.mockResolvedValue("http://s3/url"); const result = await service.getUploadUrl("user1", "test.png"); expect(result).toHaveProperty("url", "http://s3/url"); expect(result).toHaveProperty("key"); expect(result.key).toContain("uploads/user1/"); }); }); describe("uploadAndProcess", () => { const file = { buffer: Buffer.from("test"), originalname: "test.png", mimetype: "image/png", size: 1000, } as Express.Multer.File; it("should upload and process an image", async () => { mockConfigService.get.mockReturnValue(1024); // max size mockMediaService.scanFile.mockResolvedValue({ isInfected: false }); mockMediaService.processImage.mockResolvedValue({ buffer: Buffer.from("processed"), extension: "webp", mimeType: "image/webp", size: 500, }); mockContentsRepository.findBySlug.mockResolvedValue(null); mockContentsRepository.create.mockResolvedValue({ id: "content-id" }); const result = await service.uploadAndProcess("user1", file, { title: "Meme", type: "meme", }); expect(mediaService.scanFile).toHaveBeenCalled(); expect(mediaService.processImage).toHaveBeenCalled(); expect(s3Service.uploadFile).toHaveBeenCalled(); expect(result).toEqual({ id: "content-id" }); }); it("should throw if file is infected", async () => { mockConfigService.get.mockReturnValue(1024); mockMediaService.scanFile.mockResolvedValue({ isInfected: true, virusName: "Eicar", }); await expect( service.uploadAndProcess("user1", file, { title: "X", type: "meme" }), ).rejects.toThrow(BadRequestException); }); }); describe("findAll", () => { it("should return contents and total count", async () => { mockContentsRepository.count.mockResolvedValue(10); mockContentsRepository.findAll.mockResolvedValue([{ id: "1" }]); const result = await service.findAll({ limit: 10, offset: 0 }); expect(result.totalCount).toBe(10); expect(result.data).toHaveLength(1); }); }); describe("incrementViews", () => { it("should increment views", async () => { mockContentsRepository.incrementViews.mockResolvedValue([ { id: "1", views: 1 }, ]); const result = await service.incrementViews("1"); expect(mockContentsRepository.incrementViews).toHaveBeenCalledWith("1"); expect(result[0].views).toBe(1); }); }); });