1import { describe, expect, it } from "vite-plus/test";
2
3import { extractIcnsPng } from "./icns.ts";
4
5function pngHeader(size: number): Uint8Array {
6 const png = new Uint8Array(24);
7 png.set([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0, 0, 0, 13, 0x49, 0x48, 0x44, 0x52]);
8 new DataView(png.buffer).setUint32(16, size);
9 new DataView(png.buffer).setUint32(20, size);
10 return png;
11}
12
13function icns(...entries: ReadonlyArray<readonly [type: string, data: Uint8Array]>): Uint8Array {
14 const length = 8 + entries.reduce((total, [, data]) => total + 8 + data.length, 0);
15 const bytes = new Uint8Array(length);
16 const view = new DataView(bytes.buffer);
17 bytes.set(new TextEncoder().encode("icns"));
18 view.setUint32(4, length);
19 let offset = 8;
20 for (const [type, data] of entries) {
21 bytes.set(new TextEncoder().encode(type), offset);
22 view.setUint32(offset + 4, 8 + data.length);
23 bytes.set(data, offset + 8);
24 offset += 8 + data.length;
25 }
26 return bytes;
27}
28
29const widthOf = (png: Uint8Array | null) =>
30 png ? new DataView(png.buffer, png.byteOffset).getUint32(16) : null;
31
32describe("extractIcnsPng", () => {
33 it("picks the smallest PNG that covers the requested size", () => {
34 const file = icns(
35 ["TOC ", new Uint8Array(16)],
36 ["ic09", pngHeader(512)],
37 ["icp5", pngHeader(32)],
38 ["ic07", pngHeader(128)],
39 ["ic08", pngHeader(256)],
40 );
41
42 expect(widthOf(extractIcnsPng(file, 96))).toBe(128);
43 });
44
45 it("falls back to the largest PNG when none covers the requested size", () => {
46 const file = icns(["icp4", pngHeader(16)], ["icp5", pngHeader(32)]);
47
48 expect(widthOf(extractIcnsPng(file, 96))).toBe(32);
49 });
50
51 it("returns null for files without a PNG entry or with a foreign header", () => {
52 expect(extractIcnsPng(icns(["it32", new Uint8Array(64)]), 96)).toBeNull();
53 expect(extractIcnsPng(pngHeader(128), 96)).toBeNull();
54 });
55
56 it("stops at an entry whose length runs past the file", () => {
57 const file = icns(["ic07", pngHeader(128)], ["ic08", pngHeader(256)]);
58 new DataView(file.buffer).setUint32(8 + 8 + 24 + 4, 4096);
59
60 expect(widthOf(extractIcnsPng(file, 200))).toBe(128);
61 });
62});