import { expect, test, vi } from "vitest"; import { uploadLibraryResource } from "@/features/libraries/upload-resource"; test("uploads original thumbnail and gallery files before creating the resource record", async () => { const originalFile = new File(["original"], "ava-original.png", { type: "image/png", }); const thumbnailFile = new File(["thumbnail"], "ava-thumb.png", { type: "image/png", }); const galleryFile = new File(["gallery"], "ava-gallery.png", { type: "image/png", }); const thumbnailGenerator = vi.fn().mockResolvedValue(thumbnailFile); const fetchMock = vi .fn() .mockResolvedValueOnce( new Response( JSON.stringify({ data: { method: "PUT", uploadUrl: "https://upload.test/original", headers: { "content-type": "image/png" }, storageKey: "library/models/2026/ava-original.png", publicUrl: "https://images.test/library/models/2026/ava-original.png", }, }), ), ) .mockResolvedValueOnce(new Response(null, { status: 200 })) .mockResolvedValueOnce( new Response( JSON.stringify({ data: { method: "PUT", uploadUrl: "https://upload.test/thumbnail", headers: { "content-type": "image/png" }, storageKey: "library/models/2026/ava-thumb.png", publicUrl: "https://images.test/library/models/2026/ava-thumb.png", }, }), ), ) .mockResolvedValueOnce(new Response(null, { status: 200 })) .mockResolvedValueOnce( new Response( JSON.stringify({ data: { method: "PUT", uploadUrl: "https://upload.test/gallery", headers: { "content-type": "image/png" }, storageKey: "library/models/2026/ava-gallery.png", publicUrl: "https://images.test/library/models/2026/ava-gallery.png", }, }), ), ) .mockResolvedValueOnce(new Response(null, { status: 200 })) .mockResolvedValueOnce( new Response( JSON.stringify({ data: { item: { id: "12", libraryType: "models", name: "Ava Studio", description: "棚拍女模特", previewUri: "https://images.test/library/models/2026/ava-thumb.png", tags: ["女装", "棚拍"], isMock: false, backendId: 12, }, }, }), { status: 201 }, ), ); const created = await uploadLibraryResource({ fetchFn: fetchMock, thumbnailGenerator, libraryType: "models", values: { name: "Ava Studio", description: "棚拍女模特", tags: ["女装", "棚拍"], gender: "female", ageGroup: "adult", environment: "", category: "", }, files: { original: originalFile, gallery: [galleryFile], }, }); expect(created).toEqual({ id: "12", libraryType: "models", name: "Ava Studio", description: "棚拍女模特", previewUri: "https://images.test/library/models/2026/ava-thumb.png", tags: ["女装", "棚拍"], isMock: false, backendId: 12, }); expect(fetchMock).toHaveBeenNthCalledWith( 1, "/api/libraries/uploads/presign", expect.objectContaining({ method: "POST", }), ); expect(fetchMock).toHaveBeenNthCalledWith( 2, "https://upload.test/original", expect.objectContaining({ method: "PUT", body: originalFile, }), ); expect(fetchMock).toHaveBeenNthCalledWith( 7, "/api/libraries/models", expect.objectContaining({ method: "POST", }), ); expect(fetchMock).toHaveBeenLastCalledWith( "/api/libraries/models", expect.objectContaining({ body: JSON.stringify({ name: "Ava Studio", description: "棚拍女模特", tags: ["女装", "棚拍"], gender: "female", ageGroup: "adult", environment: undefined, category: undefined, files: [ { fileRole: "original", storageKey: "library/models/2026/ava-original.png", publicUrl: "https://images.test/library/models/2026/ava-original.png", mimeType: "image/png", sizeBytes: 8, sortOrder: 0, }, { fileRole: "thumbnail", storageKey: "library/models/2026/ava-thumb.png", publicUrl: "https://images.test/library/models/2026/ava-thumb.png", mimeType: "image/png", sizeBytes: 9, sortOrder: 0, }, { fileRole: "gallery", storageKey: "library/models/2026/ava-gallery.png", publicUrl: "https://images.test/library/models/2026/ava-gallery.png", mimeType: "image/png", sizeBytes: 7, sortOrder: 0, }, ], }), }), ); expect(thumbnailGenerator).toHaveBeenCalledWith(originalFile); });