79 lines · 2.7 KB · TypeScript
RawDownload
import { beforeEach, describe, expect, it, vi } from "vite-plus/test";import { PROJECT_FAVICON_MAX_DATA_URL_LENGTH } from "@t3tools/client-runtime/project-favicon-cache"; const native = vi.hoisted(() => ({  load: vi.fn(async (_url: string, options: { maxWidth: number; maxHeight: number }) => ({    width: options.maxWidth,    height: options.maxHeight,    release: vi.fn(),  })),  write: vi.fn(async () => {}),  path: vi.fn(async () => "/cache/thumbnail"),  read: vi.fn(),  remove: vi.fn(),}));vi.mock("expo-image", () => ({  Image: {    loadAsync: native.load,    writeToCacheAsync: native.write,    getCachePathAsync: native.path,  },}));vi.mock("expo-file-system", () => ({  File: class {    size = 24_000;    base64 = native.read;    delete = native.remove;  },})); import { downscaleProjectFavicon } from "./projectFaviconCache"; const png = "iVBORw0KGgoAAAAA";const image = { url: "https://remote/icon.png" }; beforeEach(() => {  vi.clearAllMocks();  native.read.mockReset().mockResolvedValue(png);  native.load.mockReset().mockImplementation(async (_url, { maxWidth }) => ({    width: maxWidth,    height: maxWidth,    release: vi.fn(),  }));}); describe("mobile project icon thumbnails", () => {  it("reduces an oversized encoding and deletes temporary thumbnail files", async () => {    native.read.mockResolvedValueOnce(      `iVBORw0KGgo${"a".repeat(PROJECT_FAVICON_MAX_DATA_URL_LENGTH)}`,    );    const thumbnail = await downscaleProjectFavicon(image, new AbortController().signal);    expect(thumbnail).toBe(`data:image/png;base64,${png}`);    expect(native.load.mock.calls.map(([, options]) => options.maxWidth)).toEqual([96, 48]);    expect(native.remove).toHaveBeenCalledTimes(2);    for (const call of native.load.mock.results)      expect((await call.value).release).toHaveBeenCalledOnce();  });   it("releases a decoded image when its request was canceled", async () => {    const controller = new AbortController();    const release = vi.fn();    native.load.mockImplementationOnce(async () => {      controller.abort();      return { width: 96, height: 96, release };    });    await expect(downscaleProjectFavicon(image, controller.signal)).rejects.toThrow();    expect(release).toHaveBeenCalledOnce();    expect(native.write).not.toHaveBeenCalled();  });   it("rejects an image the native decoder did not downsize", async () => {    const release = vi.fn();    native.load.mockResolvedValueOnce({ width: 4000, height: 3000, release });    await expect(downscaleProjectFavicon(image, new AbortController().signal)).rejects.toThrow(      "not resized",    );    expect(native.write).not.toHaveBeenCalled();    expect(release).toHaveBeenCalledOnce();  });});