test.build/core/loaders/icons.loader.test.ts

test.build/core/loaders/icons.loader.test.ts is a file in Codebase Testing. 48 lines of code and 0 definitions.

import { describe, expect, it, vi } from "vitest";
import { discoverIcons, iconPathsOf } from "@banes-lab/build-scripts/core/loaders/icons.loader.ts";
import type { readFileSync as ReadFile } from "node:fs";
import { iconSource } from "@banes-lab/build-scripts/core/resolvers/icons.resolver.ts";
import { pathlessIcon } from "@banes-lab/build-scripts/configuration/strings/icons.strings.ts";

const ICON_PREFIX = "bi-";
const EVEN_ODD_ICON = "diagram-3";
const NONZERO_ICON = "check2";
const { PATHLESS_ICON, PATHLESS_FILE } = vi.hoisted(() => ({
    PATHLESS_FILE: "pathless-planted.svg",
    PATHLESS_ICON: "pathless-planted",
}));

vi.mock("node:fs", async () => {
    const actual = await vi.importActual<{ readonly readFileSync: typeof ReadFile }>("node:fs");
    return {
        ...actual,
        readFileSync: (file: string, encoding: "utf8") =>
            file.endsWith(PATHLESS_FILE) ? "<svg></svg>" : actual.readFileSync(file, encoding),
    };
});

describe("iconSource", () => {
    it("names the icon's own SVG file in the icon package", () => {
        expect(iconSource(NONZERO_ICON).endsWith(`/icons/${NONZERO_ICON}.svg`)).toBe(true);
    });
});

describe("iconPathsOf", () => {
    it("refuses an SVG file that draws no path", () => {
        expect(() => iconPathsOf(PATHLESS_ICON)).toThrow(pathlessIcon(ICON_PREFIX + PATHLESS_ICON));
    });

    it("reads every path of an icon with its fill rule", () => {
        const evenOdd = iconPathsOf(EVEN_ODD_ICON);
        expect(evenOdd.length).toBeGreaterThan(0);
        expect(evenOdd.every((path) => path.evenOdd && path.d.startsWith("M"))).toBe(true);
        expect(iconPathsOf(NONZERO_ICON).some((path) => path.evenOdd)).toBe(false);
    });

    it("refuses a name the icon package draws no file for", () => {
        expect(() => iconPathsOf("no-such-icon-anywhere")).toThrow();
    });
});

describe("discoverIcons", () => {
    it("collects every icon name the icon modules declare, without the prefix, sorted and deduplicated", async () => {
        const names = await discoverIcons();
        expect(names.length).toBeGreaterThan(0);
        expect(names.every((name) => name.length > 0 && !name.startsWith(ICON_PREFIX))).toBe(true);
        expect(new Set(names).size).toBe(names.length);
        expect([...names].toSorted((a, b) => a.localeCompare(b))).toStrictEqual(names);
    });
});