frontend/test/data/image_upload.test.ts

151 lines
4.6 KiB
TypeScript

import { describe, it, expect, vi, afterEach } from "vitest";
import {
getIdFromUrl,
generateImageThumbnailUrl,
fetchImages,
createImage,
updateImage,
deleteImage,
getImageData,
URL_PREFIX,
MEDIA_PREFIX,
} from "../../src/data/image_upload";
import type { HomeAssistant } from "../../src/types";
describe("image_upload", () => {
afterEach(() => {
vi.restoreAllMocks();
});
describe("getIdFromUrl", () => {
it("should extract id from URL_PREFIX", () => {
const url = `${URL_PREFIX}12345/some/path`;
const id = getIdFromUrl(url);
expect(id).toBe("12345");
});
it("should extract id from MEDIA_PREFIX", () => {
const url = `${MEDIA_PREFIX}/12345`;
const id = getIdFromUrl(url);
expect(id).toBe("12345");
});
it("should return undefined for invalid url", () => {
const url = "invalid_url";
const id = getIdFromUrl(url);
expect(id).toBeUndefined();
});
});
describe("generateImageThumbnailUrl", () => {
it("should generate thumbnail URL with size", () => {
const url = generateImageThumbnailUrl("12345", 100);
expect(url).toBe("/api/image/serve/12345/100x100");
});
it("should generate original image URL", () => {
const url = generateImageThumbnailUrl("12345", undefined, true);
expect(url).toBe("/api/image/serve/12345/original");
});
it("should throw error if size is not provided and original is false", () => {
expect(() => generateImageThumbnailUrl("12345")).toThrow(
"Size must be provided if original is false"
);
});
});
describe("fetchImages", () => {
it("should fetch images", async () => {
const hass = {
callWS: vi.fn().mockResolvedValue([]),
} as unknown as HomeAssistant;
const images = await fetchImages(hass);
expect(hass.callWS).toHaveBeenCalledWith({ type: "image/list" });
expect(images).toEqual([]);
});
});
describe("createImage", () => {
it("should create an image", async () => {
const file = new File([""], "image.png", { type: "image/png" });
const hass = {
fetchWithAuth: vi.fn().mockResolvedValue({
status: 200,
json: vi.fn().mockResolvedValue({ id: "12345" }),
}),
} as unknown as HomeAssistant;
const image = await createImage(hass, file);
expect(hass.fetchWithAuth).toHaveBeenCalled();
expect(image).toEqual({ id: "12345" });
});
it("should throw error if image is too large", async () => {
const file = new File([""], "image.png", { type: "image/png" });
const hass = {
fetchWithAuth: vi.fn().mockResolvedValue({ status: 413 }),
} as unknown as HomeAssistant;
await expect(createImage(hass, file)).rejects.toThrow(
"Uploaded image is too large (image.png)"
);
});
it("should throw error if fetch fails", async () => {
const file = new File([""], "image.png", { type: "image/png" });
const hass = {
fetchWithAuth: vi.fn().mockResolvedValue({ status: 500 }),
} as unknown as HomeAssistant;
await expect(createImage(hass, file)).rejects.toThrow("Unknown error");
});
});
describe("updateImage", () => {
it("should update an image", async () => {
const hass = {
callWS: vi.fn().mockResolvedValue({}),
} as unknown as HomeAssistant;
const updates = { name: "new name" };
await updateImage(hass, "12345", updates);
expect(hass.callWS).toHaveBeenCalledWith({
type: "image/update",
media_id: "12345",
...updates,
});
});
});
describe("deleteImage", () => {
it("should delete an image", async () => {
const hass = {
callWS: vi.fn().mockResolvedValue({}),
} as unknown as HomeAssistant;
await deleteImage(hass, "12345");
expect(hass.callWS).toHaveBeenCalledWith({
type: "image/delete",
image_id: "12345",
});
});
});
describe("getImageData", () => {
it("should fetch image data", async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: true,
blob: vi.fn().mockResolvedValue(new Blob()),
});
const data = await getImageData("http://example.com/image.png");
expect(global.fetch).toHaveBeenCalledWith("http://example.com/image.png");
expect(data).toBeInstanceOf(Blob);
});
it("should throw error if fetch fails", async () => {
global.fetch = vi
.fn()
.mockResolvedValue({ ok: false, statusText: "Not Found" });
await expect(
getImageData("http://example.com/image.png")
).rejects.toThrow("Failed to fetch image: Not Found");
});
});
});