Files
Termix/plugins/ssh-terminal/tests/backend/images/image-utils.test.ts
T

77 lines
2.6 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
exceedsImageStorageLimit,
exceedsNormalizedImageSize,
imageExtensionForFormat,
createConcurrencyLimiter,
isExpiredImage,
isImageFilename,
} from "../../../src/backend/images/image-utils.js";
describe("terminal image utilities", () => {
it("accepts UUID-based image filenames", () => {
expect(isImageFilename("b797234d-eb5d-4b1b-b7f3-17c26f257506.jpeg")).toBe(
true,
);
});
it("rejects unsafe or unrelated filenames", () => {
expect(isImageFilename("../secrets.txt")).toBe(false);
expect(isImageFilename("not-an-image.jpeg")).toBe(false);
expect(isImageFilename("b797234d-eb5d-4b1b-b7f3-17c26f257506")).toBe(false);
});
it("maps decoded raster formats while excluding SVG", () => {
expect(imageExtensionForFormat("jpeg")).toBe("jpg");
expect(imageExtensionForFormat("heif")).toBe("heif");
expect(imageExtensionForFormat("tiff")).toBe("tiff");
expect(imageExtensionForFormat("svg")).toBeUndefined();
expect(imageExtensionForFormat(undefined)).toBeUndefined();
});
it("rejects normalized output beyond the byte ceiling", () => {
expect(exceedsNormalizedImageSize(10_000_001, 10_000_000)).toBe(true);
expect(exceedsNormalizedImageSize(10_000_000, 10_000_000)).toBe(false);
});
it("expires files older than the configured TTL", () => {
expect(isExpiredImage(1_000, 3_000, 1_000)).toBe(true);
expect(isExpiredImage(2_500, 3_000, 1_000)).toBe(false);
});
it("treats a zero TTL as retention disabled", () => {
expect(isExpiredImage(1_000, 999_999, 0)).toBe(false);
});
it("bounds the admission queue", async () => {
const limiter = createConcurrencyLimiter(1, 0);
const release = await limiter.acquire();
await expect(limiter.acquire()).rejects.toThrow("queue is full");
release();
});
it("rejects uploads that exceed the count or byte limit", () => {
expect(exceedsImageStorageLimit(100, 10, 1, 100, 1000)).toBe(true);
expect(exceedsImageStorageLimit(1, 900, 101, 100, 1000)).toBe(true);
expect(exceedsImageStorageLimit(1, 900, 100, 100, 1000)).toBe(false);
});
it("bounds concurrent work", async () => {
const limiter = createConcurrencyLimiter(1);
let active = 0;
let peak = 0;
const task = async () => {
const release = await limiter.acquire();
active += 1;
peak = Math.max(peak, active);
await new Promise((resolve) => setTimeout(resolve, 5));
active -= 1;
release();
};
await Promise.all([task(), task(), task()]);
expect(peak).toBe(1);
expect(limiter.active).toBe(0);
});
});