/**
* Unit tests for Tool Icons Utility
*
* Tests icon generation for tool categories and behavior annotations.
*/
import { describe, it, expect } from "vitest";
import {
getToolIcons,
getCategoryIcon,
getAllCategoryIcons,
} from "../icons.js";
import type { ToolGroup } from "../../types/index.js";
describe("Tool Icons Utility", () => {
describe("getToolIcons", () => {
it("should return warning icon for destructive tools", () => {
const icons = getToolIcons("core", { destructiveHint: true });
expect(icons.length).toBe(1);
expect(icons[0]?.mimeType).toBe("image/svg+xml");
// Warning icons have red color
expect(icons[0]?.src).toContain("data:image/svg+xml;base64,");
});
it("should return admin icon for VACUUM operations", () => {
const icons = getToolIcons("admin", { title: "VACUUM Tables" });
expect(icons.length).toBe(1);
expect(icons[0]?.mimeType).toBe("image/svg+xml");
});
it("should return admin icon for ANALYZE operations", () => {
const icons = getToolIcons("admin", {
title: "Analyze Table Statistics",
});
expect(icons.length).toBe(1);
});
it("should return admin icon for REINDEX operations", () => {
const icons = getToolIcons("admin", { title: "Reindex Database" });
expect(icons.length).toBe(1);
});
it("should return category icon for non-destructive tools", () => {
const icons = getToolIcons("core", { readOnlyHint: true });
expect(icons.length).toBe(1);
expect(icons[0]?.mimeType).toBe("image/svg+xml");
});
it("should return category icon when no annotations provided", () => {
const icons = getToolIcons("vector");
expect(icons.length).toBe(1);
});
it("should handle undefined annotations title", () => {
const icons = getToolIcons("postgis", { readOnlyHint: true });
expect(icons.length).toBe(1);
});
});
describe("getCategoryIcon", () => {
const toolGroups: ToolGroup[] = [
"core",
"transactions",
"jsonb",
"text",
"performance",
"admin",
"monitoring",
"backup",
"schema",
"vector",
"postgis",
"partitioning",
"stats",
"cron",
"partman",
"kcache",
"citext",
"ltree",
"pgcrypto",
"codemode",
];
it.each(toolGroups)("should return icon for %s group", (group) => {
const icons = getCategoryIcon(group);
expect(icons.length).toBe(1);
expect(icons[0]?.src).toBeDefined();
expect(icons[0]?.mimeType).toBe("image/svg+xml");
expect(icons[0]?.sizes).toEqual(["any"]);
});
});
describe("getAllCategoryIcons", () => {
it("should return icons for all tool groups", () => {
const allIcons = getAllCategoryIcons();
expect(Object.keys(allIcons).length).toBeGreaterThan(0);
});
it("should return valid icons for each group", () => {
const allIcons = getAllCategoryIcons();
for (const [, icons] of Object.entries(allIcons)) {
expect(icons.length).toBe(1);
expect(icons[0]?.src).toContain("data:image/svg+xml;base64,");
expect(icons[0]?.mimeType).toBe("image/svg+xml");
expect(icons[0]?.sizes).toEqual(["any"]);
}
});
it("should include core group", () => {
const allIcons = getAllCategoryIcons();
expect(allIcons["core"]).toBeDefined();
});
it("should include vector group", () => {
const allIcons = getAllCategoryIcons();
expect(allIcons["vector"]).toBeDefined();
});
it("should include postgis group", () => {
const allIcons = getAllCategoryIcons();
expect(allIcons["postgis"]).toBeDefined();
});
it("should include codemode group", () => {
const allIcons = getAllCategoryIcons();
expect(allIcons["codemode"]).toBeDefined();
});
});
describe("Icon Data URI Format", () => {
it("should generate valid base64 encoded SVG", () => {
const icons = getCategoryIcon("core");
const src = icons[0]?.src ?? "";
// Should be a data URI
expect(src.startsWith("data:image/svg+xml;base64,")).toBe(true);
// Extract base64 part and decode
const base64Part = src.replace("data:image/svg+xml;base64,", "");
const decodedSvg = Buffer.from(base64Part, "base64").toString("utf-8");
// Should be valid SVG
expect(decodedSvg).toContain("<svg");
expect(decodedSvg).toContain("</svg>");
expect(decodedSvg).toContain("viewBox");
});
it("should include stroke properties in SVG", () => {
const icons = getCategoryIcon("transactions");
const src = icons[0]?.src ?? "";
const base64Part = src.replace("data:image/svg+xml;base64,", "");
const decodedSvg = Buffer.from(base64Part, "base64").toString("utf-8");
expect(decodedSvg).toContain("stroke=");
expect(decodedSvg).toContain("stroke-width");
});
});
});