import assert from "node:assert/strict"; import { test } from "node:test"; import { Chalk } from "chalk"; import fetchMock from "fetch-mock"; import { getAsciiArt, getFaviconUrl, Jimp, readImage, rgbTo256Color, } from "./nodeinfo.ts"; const HTML_WITH_SMALL_ICON = ` Test Site Test `; test("getFaviconUrl - small favicon.ico and apple-touch-icon.png", async () => { fetchMock.spyGlobal(); fetchMock.get("https://example.com/", { body: HTML_WITH_SMALL_ICON, headers: { "Content-Type": "text/html" }, }); const result = await getFaviconUrl("https://example.com/"); assert.equal(result.href, "https://example.com/apple-touch-icon.png"); fetchMock.hardReset(); }); const HTML_WITH_ICON = ` Test Site Test `; test("getFaviconUrl - favicon.ico and apple-touch-icon.png", async () => { fetchMock.spyGlobal(); fetchMock.get("https://example.com/", { body: HTML_WITH_ICON, headers: { "Content-Type": "text/html" }, }); const result = await getFaviconUrl("https://example.com/"); assert.equal(result.href, "https://example.com/favicon.ico"); fetchMock.hardReset(); }); const HTML_WITH_SVG_ONLY = ` Test Site Test `; test("getFaviconUrl - svg icons only falls back to /favicon.ico", async () => { fetchMock.spyGlobal(); fetchMock.get("https://example.com/", { body: HTML_WITH_SVG_ONLY, headers: { "Content-Type": "text/html" }, }); const result = await getFaviconUrl("https://example.com/"); assert.equal(result.href, "https://example.com/favicon.ico"); fetchMock.hardReset(); }); const HTML_WITH_UPPERCASE_SVG_ONLY = ` Test Site Test `; test("getFaviconUrl - uppercase svg icons only falls back to /favicon.ico", async () => { fetchMock.spyGlobal(); fetchMock.get("https://example.com/", { body: HTML_WITH_UPPERCASE_SVG_ONLY, headers: { "Content-Type": "text/html" }, }); const result = await getFaviconUrl("https://example.com/"); assert.equal(result.href, "https://example.com/favicon.ico"); fetchMock.hardReset(); }); const HTML_WITH_UPPERCASE_SVG_WITH_QUERY = ` Test Site Test `; test("getFaviconUrl - uppercase svg icons with query and hash fall back to /favicon.ico", async () => { fetchMock.spyGlobal(); fetchMock.get("https://example.com/", { body: HTML_WITH_UPPERCASE_SVG_WITH_QUERY, headers: { "Content-Type": "text/html" }, }); const result = await getFaviconUrl("https://example.com/"); assert.equal(result.href, "https://example.com/favicon.ico"); fetchMock.hardReset(); }); const HTML_WITHOUT_ICON = ` Test Site Test `; test("getFaviconUrl - falls back to /favicon.ico", async () => { fetchMock.spyGlobal(); fetchMock.get("https://example.com/", { body: HTML_WITHOUT_ICON, headers: { "Content-Type": "text/html" }, }); const result = await getFaviconUrl("https://example.com/"); assert.equal(result.href, "https://example.com/favicon.ico"); fetchMock.hardReset(); }); test("rgbTo256Color - check RGB cube", () => { const CUBE_VALUES = [0, 95, 135, 175, 215, 255]; const colors: Array<{ r: number; g: number; b: number }> = []; for (let r = 0; r < 6; r++) { for (let g = 0; g < 6; g++) { for (let b = 0; b < 6; b++) { colors.push({ r: CUBE_VALUES[r], g: CUBE_VALUES[g], b: CUBE_VALUES[b], }); } } } // Expected color indices for the above colors (16-231) // RGB cube: 6x6x6 = 216 colors, indices 16-231 const expected_color_idx = Array.from( { length: colors.length }, (_, i) => 16 + i, ); const results = colors.map((color) => rgbTo256Color(color.r, color.g, color.b) ); assert.deepEqual(results, expected_color_idx); }); test("rgbTo256Color - check grayscale", () => { const grayscale = Array.from({ length: 24 }).map( (_, idx) => ({ r: 8 + idx * 10, g: 8 + idx * 10, b: 8 + idx * 10, }), ); const expected_gray_idx = Array.from( { length: grayscale.length }, (_, i) => 232 + i, ); const results = grayscale.map((GRAY) => rgbTo256Color(GRAY.r, GRAY.g, GRAY.b) ); assert.deepEqual(results, expected_gray_idx); }); async function createTestImage( color: number, ): Promise>> { const image = new Jimp({ width: 1, height: 1, color }); const imageBuffer = await image.getBuffer("image/png"); return readImage(imageBuffer); } test("getAsciiArt - Darkest Letter without color support", async () => { const blackResult = getAsciiArt( await createTestImage(0x000000ff), 1, "none", new Chalk({ level: 0 }), ); assert.equal(blackResult, "â–ˆ"); }); test("getAsciiArt - Brightest Letter without color support", async () => { const whiteResult = getAsciiArt( await createTestImage(0xffffffff), 1, "none", new Chalk({ level: 0 }), ); assert.equal(whiteResult, " "); }); test("getAsciiArt - Darkest Letter with 256 color support", async () => { const blackResult = getAsciiArt( await createTestImage(0x000000ff), 1, "256color", new Chalk({ level: 2 }), ); assert.equal(blackResult, "\u001b[38;5;16mâ–ˆ\u001b[39m"); }); test("getAsciiArt - Brightest Letter with 256 color support", async () => { const whiteResult = getAsciiArt( await createTestImage(0xffffffff), 1, "256color", new Chalk({ level: 2 }), ); assert.equal(whiteResult, "\u001b[38;5;231m \u001b[39m"); }); test("getAsciiArt - Darkest Letter with true color support", async () => { const blackResult = getAsciiArt( await createTestImage(0x000000ff), 1, "truecolor", new Chalk({ level: 3 }), ); assert.equal(blackResult, "\u001b[38;2;0;0;0mâ–ˆ\u001b[39m"); }); test("getAsciiArt - Brightest Letter with true color support", async () => { const whiteResult = getAsciiArt( await createTestImage(0xffffffff), 1, "truecolor", new Chalk({ level: 3 }), ); assert.equal(whiteResult, "\u001b[38;2;255;255;255m \u001b[39m"); });