mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 14:15:24 +00:00
77 lines
2.6 KiB
TypeScript
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);
|
|
});
|
|
});
|