Enhance canvas functionality by adding media preview capabilities and image upload handling. Introduce compressed image previews during uploads, improve media library integration, and implement retry logic for bridge edge creation. Update dashboard to display media previews and optimize image node handling.
This commit is contained in:
76
components/canvas/__tests__/canvas-media-utils.test.ts
Normal file
76
components/canvas/__tests__/canvas-media-utils.test.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
// @vitest-environment jsdom
|
||||
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { createCompressedImagePreview } from "@/components/canvas/canvas-media-utils";
|
||||
|
||||
class MockImage {
|
||||
onload: (() => void) | null = null;
|
||||
onerror: (() => void) | null = null;
|
||||
naturalWidth = 0;
|
||||
naturalHeight = 0;
|
||||
|
||||
set src(_value: string) {
|
||||
queueMicrotask(() => {
|
||||
this.naturalWidth = 4000;
|
||||
this.naturalHeight = 2000;
|
||||
this.onload?.();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
describe("createCompressedImagePreview", () => {
|
||||
const originalImage = globalThis.Image;
|
||||
const originalCreateObjectURL = URL.createObjectURL;
|
||||
const originalRevokeObjectURL = URL.revokeObjectURL;
|
||||
const drawImage = vi.fn();
|
||||
const toBlob = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.stubGlobal("Image", MockImage);
|
||||
URL.createObjectURL = vi.fn(() => "blob:preview") as typeof URL.createObjectURL;
|
||||
URL.revokeObjectURL = vi.fn() as typeof URL.revokeObjectURL;
|
||||
vi.spyOn(HTMLCanvasElement.prototype, "getContext").mockReturnValue({
|
||||
drawImage,
|
||||
} as unknown as CanvasRenderingContext2D);
|
||||
vi.spyOn(HTMLCanvasElement.prototype, "toBlob").mockImplementation(
|
||||
(callback) => {
|
||||
toBlob();
|
||||
callback(new Blob(["preview"], { type: "image/webp" }));
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
drawImage.mockReset();
|
||||
toBlob.mockReset();
|
||||
vi.stubGlobal("Image", originalImage);
|
||||
URL.createObjectURL = originalCreateObjectURL;
|
||||
URL.revokeObjectURL = originalRevokeObjectURL;
|
||||
});
|
||||
|
||||
it("clamps dimensions to the configured max edge", async () => {
|
||||
const file = new File(["bytes"], "photo.jpg", { type: "image/jpeg" });
|
||||
|
||||
const preview = await createCompressedImagePreview(file);
|
||||
|
||||
expect(preview.width).toBe(640);
|
||||
expect(preview.height).toBe(320);
|
||||
expect(preview.blob.type).toBe("image/webp");
|
||||
expect(drawImage).toHaveBeenCalledTimes(1);
|
||||
expect(toBlob).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("returns fallback mime type when encoder does not produce webp", async () => {
|
||||
vi.spyOn(HTMLCanvasElement.prototype, "toBlob").mockImplementation((callback) => {
|
||||
callback(new Blob(["preview"], { type: "image/png" }));
|
||||
});
|
||||
|
||||
const file = new File(["bytes"], "photo.jpg", { type: "image/jpeg" });
|
||||
|
||||
const preview = await createCompressedImagePreview(file);
|
||||
|
||||
expect(preview.blob.type).toBe("image/png");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user