Files
colour-tools/tests/palette/decode.test.ts
T

67 lines
2.0 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from "vitest";
import { decodeLocalImage } from "../../src/palette/decode";
const nativeUrl = globalThis.URL;
afterEach(() => {
vi.unstubAllGlobals();
});
const installImageElementDecoder = (loadImmediately: boolean) => {
const createObjectURL = vi.fn(() => "blob:local-image");
const revokeObjectURL = vi.fn();
class MockUrl extends nativeUrl {
static createObjectURL = createObjectURL;
static revokeObjectURL = revokeObjectURL;
}
class MockImage {
decoding = "auto";
naturalWidth = 320;
naturalHeight = 180;
onload: (() => void) | null = null;
onerror: (() => void) | null = null;
private source = "";
set src(value: string) {
this.source = value;
if (value && loadImmediately) queueMicrotask(() => this.onload?.());
}
get src(): string {
return this.source;
}
}
vi.stubGlobal("URL", MockUrl);
vi.stubGlobal("Image", MockImage);
vi.stubGlobal("createImageBitmap", undefined);
return { createObjectURL, revokeObjectURL };
};
describe("local image decoding", () => {
it("revokes its object URL as soon as the image has decoded", async () => {
const spies = installImageElementDecoder(true);
const image = await decodeLocalImage(
new File(["image"], "sample.png", { type: "image/png" }),
);
expect(image).toMatchObject({ width: 320, height: 180 });
expect(spies.createObjectURL).toHaveBeenCalledOnce();
expect(spies.revokeObjectURL).toHaveBeenCalledWith("blob:local-image");
image.dispose();
});
it("revokes its object URL when decoding is cancelled", async () => {
const spies = installImageElementDecoder(false);
const controller = new AbortController();
const decoding = decodeLocalImage(
new File(["image"], "sample.png", { type: "image/png" }),
controller.signal,
);
controller.abort();
await expect(decoding).rejects.toMatchObject({ name: "AbortError" });
expect(spies.revokeObjectURL).toHaveBeenCalledWith("blob:local-image");
});
});