import "dotenv/config"; import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { promises as fs } from "fs"; import path from "path"; const BASE_URL = "http://localhost"; // /api/video/:id 서브 라우트 TDD // - 존재하는 업로드 파일 id 로 GET /api/video/:id 를 호출하면 200 과 비디오 바이트를 반환해야 한다. // - 존재하지 않는 id 로 호출하면 404 를 반환해야 한다. // Prisma 엔진이 실제로 로드되지 않도록 PrismaClient 를 단순 목으로 대체한다. vi.mock("@prisma/client", () => { class PrismaClient { asset = { // GET /api/video/:id 에서는 MIME 타입 조회에만 사용되므로, 테스트에서는 null 을 반환한다. findUnique: async () => null, }; } return { PrismaClient }; }); describe("/api/video/:id 서브 라우트", () => { const uploadsDir = path.join(process.cwd(), "uploads"); let testId: string; let filePath: string; beforeEach(async () => { await fs.mkdir(uploadsDir, { recursive: true }); testId = `test-video-${Date.now()}`; filePath = path.join(uploadsDir, testId); await fs.writeFile(filePath, Buffer.from("dummy-video-bytes")); }); afterEach(async () => { try { await fs.unlink(filePath); } catch { // 이미 삭제된 경우는 무시한다. } }); it("업로드된 비디오 파일이 존재하면 200 과 비디오 바이트를 반환해야 한다", async () => { const { GET: handleGet } = await import("@/app/api/video/[id]/route"); const requestUrl = `${BASE_URL}/api/video/${testId}`; const res = await handleGet( new Request(requestUrl, { headers: { // Referer 기반 핫링크 방지 로직이 있으므로, 동일 호스트의 referer 를 포함한다. referer: `${BASE_URL}/editor`, }, }), // Next 16 타입 정의에서는 context.params 가 Promise 형태이므로, Promise 로 감싼다. { params: Promise.resolve({ id: testId }) } as any, ); expect(res.status).toBe(200); expect(res.headers.get("Content-Type")).toBe("video/mp4"); const arrayBuffer = await res.arrayBuffer(); const buf = Buffer.from(arrayBuffer); expect(buf.length).toBeGreaterThan(0); }); it("존재하지 않는 비디오 id 로 요청하면 404 를 반환해야 한다", async () => { const { GET: handleGet } = await import("@/app/api/video/[id]/route"); const missingId = `missing-${Date.now()}`; const res = await handleGet( new Request(`${BASE_URL}/api/video/${missingId}`, { headers: { referer: `${BASE_URL}/editor`, }, }), { params: Promise.resolve({ id: missingId }) } as any, ); expect(res.status).toBe(404); }); });