/** * Unit tests for utils.ts. Run with: * npx tsx --test extensions/imgview/utils.test.ts */ import * as assert from "node:assert/strict"; import * as fs from "node:fs"; import * as os from "node:os"; import * as path from "node:path"; import { describe, it } from "node:test"; import { expandHome, extensionForMime, isSupportedImageMime, resolveImage, sniffMime, tempHtmlForImage, } from "./utils.js"; const PNG_MAGIC = Buffer.from([ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, ]); const JPEG_MAGIC = Buffer.from([0xff, 0xd8, 0xff, 0xe0]); const GIF_MAGIC = Buffer.from([0x47, 0x49, 0x46, 0x38, 0x39, 0x61]); const WEBP_MAGIC = Buffer.from([ 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, ]); describe("sniffMime", () => { it("detects PNG by magic bytes", () => { assert.equal(sniffMime(PNG_MAGIC), "image/png"); }); it("detects JPEG by magic bytes", () => { assert.equal(sniffMime(JPEG_MAGIC), "image/jpeg"); }); it("detects GIF by magic bytes", () => { assert.equal(sniffMime(GIF_MAGIC), "image/gif"); }); it("detects WebP by magic bytes", () => { assert.equal(sniffMime(WEBP_MAGIC), "image/webp"); }); it("detects SVG by content sniff", () => { assert.equal(sniffMime(Buffer.from("")), "image/svg+xml"); assert.equal( sniffMime(Buffer.from("")), "image/svg+xml", ); }); it("falls back to extension hint when bytes are unknown", () => { assert.equal(sniffMime(Buffer.from([1, 2, 3, 4]), "/x/y.png"), "image/png"); assert.equal(sniffMime(Buffer.from([1, 2, 3, 4]), "/x/y.jpeg"), "image/jpeg"); }); it("returns octet-stream when nothing matches", () => { assert.equal(sniffMime(Buffer.from([1, 2, 3, 4])), "application/octet-stream"); }); }); describe("extensionForMime", () => { it("maps common MIMEs to extensions", () => { assert.equal(extensionForMime("image/png"), "png"); assert.equal(extensionForMime("image/jpeg"), "jpg"); assert.equal(extensionForMime("image/jpg"), "jpg"); assert.equal(extensionForMime("image/gif"), "gif"); assert.equal(extensionForMime("image/webp"), "webp"); assert.equal(extensionForMime("image/svg+xml"), "svg"); assert.equal(extensionForMime("application/zip"), "bin"); }); }); describe("isSupportedImageMime", () => { it("accepts supported image MIMEs", () => { assert.equal(isSupportedImageMime("image/png"), true); assert.equal(isSupportedImageMime("image/jpeg"), true); assert.equal(isSupportedImageMime("IMAGE/PNG"), true); assert.equal(isSupportedImageMime("image/svg+xml"), true); }); it("rejects non-image and unknown MIMEs", () => { assert.equal(isSupportedImageMime("application/pdf"), false); assert.equal(isSupportedImageMime("text/plain"), false); assert.equal(isSupportedImageMime(""), false); }); }); describe("expandHome", () => { it("expands a leading ~", () => { assert.equal(expandHome("~"), os.homedir()); assert.equal(expandHome("~/foo"), path.join(os.homedir(), "foo")); }); it("leaves other paths alone", () => { assert.equal(expandHome("/abs"), "/abs"); assert.equal(expandHome("rel/path"), "rel/path"); assert.equal(expandHome("~weird"), "~weird"); // not "~/" }); }); describe("resolveImage (data URI)", () => { it("decodes a base64 data: URI", async () => { const dataUri = `data:image/png;base64,${PNG_MAGIC.toString("base64")}`; const resolved = await resolveImage(dataUri, "/tmp"); assert.equal(resolved.mimeType, "image/png"); assert.equal(resolved.sourceLabel, ""); assert.equal(resolved.extension, "png"); assert.deepEqual(resolved.bytes.subarray(0, 4), PNG_MAGIC.subarray(0, 4)); }); it("rejects malformed data: URIs", async () => { await assert.rejects( () => resolveImage("data:not-a-uri", "/tmp"), /malformed data:/, ); }); }); describe("resolveImage (file)", () => { it("loads a real PNG file from disk", async () => { const tmp = await fs.promises.mkdtemp(path.join(os.tmpdir(), "imgview-")); const file = path.join(tmp, "x.png"); await fs.promises.writeFile(file, PNG_MAGIC); const resolved = await resolveImage(file, tmp); assert.equal(resolved.mimeType, "image/png"); assert.equal(resolved.sourceLabel, file); assert.equal(resolved.extension, "png"); }); it("errors clearly on a missing file", async () => { await assert.rejects( () => resolveImage("/no/such/file/exists.png", "/tmp"), /cannot read/, ); }); }); describe("tempHtmlForImage", () => { it("writes an HTML file containing the data URI and source label", async () => { const tmp = await fs.promises.mkdtemp(path.join(os.tmpdir(), "imgview-html-")); const htmlPath = await tempHtmlForImage( { bytes: PNG_MAGIC, mimeType: "image/png", sourceLabel: "test/.png", extension: "png", }, tmp, ); assert.match(htmlPath, /\.html$/); const html = await fs.promises.readFile(htmlPath, "utf8"); assert.match(html, /data:image\/png;base64,/); assert.match(html, /test\/<source>\.png/); }); });