Co-authored-by: SolitaryThinker <wlsaidhi@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
56 lines
3.2 KiB
TypeScript
56 lines
3.2 KiB
TypeScript
import { act, renderHook, waitFor } from "@testing-library/react";
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { useAssetLibrary } from "./useAssetLibrary";
|
|
|
|
const image = { asset_id: "asset-1", kind: "image", name: "frame.png", mime_type: "image/png", size: 5, url: "/assets/asset-1" };
|
|
|
|
describe("asset library lifecycle", () => {
|
|
beforeEach(() => localStorage.clear());
|
|
afterEach(() => vi.unstubAllGlobals());
|
|
it("uploads the raw file and keeps assignment state separate from uploaded assets", async () => {
|
|
const fetchMock = vi.fn(async () => ({ ok: true, json: async () => image }));
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
const { result } = renderHook(() => useAssetLibrary());
|
|
const file = new File(["image"], "first frame.png", { type: "image/png" });
|
|
await act(async () => { await result.current.uploadAssets([file]); });
|
|
expect(fetchMock).toHaveBeenCalledWith("/assets", expect.objectContaining({ body: file, headers: { "Content-Type": "image/png", "X-Asset-Name": "first%20frame.png" } }));
|
|
act(() => result.current.assignAsset("asset-1", "first_frame"));
|
|
expect(result.current.conditioningAssets).toEqual([{ asset_id: "asset-1", role: "first_frame" }]);
|
|
act(() => result.current.clearConditioning());
|
|
expect(result.current.assets).toHaveLength(1);
|
|
expect(result.current.conditioningAssets).toEqual([]);
|
|
});
|
|
it("identifies stale server assets without downloading their contents", async () => {
|
|
localStorage.setItem("dreamverse-asset-library-v1", JSON.stringify([image]));
|
|
const fetchMock = vi.fn(async () => ({ ok: false, status: 404 }));
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
const { result } = renderHook(() => useAssetLibrary());
|
|
await waitFor(() => expect(result.current.assets).toHaveLength(1));
|
|
act(() => result.current.assignAsset("asset-1", "first_frame"));
|
|
let message: string | null = null;
|
|
await act(async () => { message = await result.current.verifySelectedAssets(); });
|
|
expect(message).toMatch(/Upload it again/);
|
|
expect(result.current.assets[0].missing).toBe(true);
|
|
expect(fetchMock).toHaveBeenCalledWith("/assets/asset-1", expect.objectContaining({ method: "HEAD" }));
|
|
});
|
|
it("deletes both the library entry and its selected references", async () => {
|
|
localStorage.setItem("dreamverse-asset-library-v1", JSON.stringify([image]));
|
|
vi.stubGlobal("fetch", vi.fn(async () => ({ ok: true })));
|
|
const { result } = renderHook(() => useAssetLibrary());
|
|
await waitFor(() => expect(result.current.assets).toHaveLength(1));
|
|
act(() => result.current.assignAsset("asset-1", "reference"));
|
|
await act(async () => { await result.current.removeAsset("asset-1"); });
|
|
expect(result.current.assets).toEqual([]);
|
|
expect(result.current.conditioningAssets).toEqual([]);
|
|
});
|
|
|
|
it("does not mark a valid upload missing when the browser cannot preview its codec", async () => {
|
|
localStorage.setItem("dreamverse-asset-library-v1", JSON.stringify([image]));
|
|
vi.stubGlobal("fetch", vi.fn(async () => ({ ok: true, status: 200 })));
|
|
const { result } = renderHook(() => useAssetLibrary());
|
|
await waitFor(() => expect(result.current.assets).toHaveLength(1));
|
|
await act(async () => { await result.current.checkAssetAvailability("asset-1"); });
|
|
expect(result.current.assets[0].missing).not.toBe(true);
|
|
});
|
|
});
|