test.govlab/quality/core/converters/canon.converter.test.ts

test.govlab/quality/core/converters/canon.converter.test.ts is a file in Codebase Testing. 86 lines of code and 0 definitions.

import {
    canonicalizeId,
    canonicalizeKind,
    isCanonicalId,
    isCanonicalKind,
} from "@govlab/quality/core/converters/canon.converter.ts";
import { describe, expect, it } from "vitest";
import { KIND_SET } from "@govlab/quality/configuration/constants/canon.constants.ts";
import { loadKindMap } from "@govlab/quality/core/loaders/kind.loader.ts";

const KIND_COUNT = 14;
const ARCH_TYPE_COUNT = 165;

describe("canonicalizeId — SOLID/DRY family + de-abbreviation", () => {
    it("folds every SRP spelling to one id", () => {
        expect(canonicalizeId("SRP")).toBe("single-responsibility");
        expect(canonicalizeId("Single Responsibility Principle (SRP)")).toBe("single-responsibility");
        expect(canonicalizeId("Single Responsibility")).toBe("single-responsibility");
    });

    it("maps the rest of the SOLID set", () => {
        expect(canonicalizeId("Open/Closed Principle (OCP)")).toBe("open-closed");
        expect(canonicalizeId("OCP")).toBe("open-closed");
        expect(canonicalizeId("Interface Segregation Principle (ISP)")).toBe("interface-segregation");
        expect(canonicalizeId("Dependency Inversion Principle (DIP)")).toBe("dependency-inversion");
    });

    it("merges Behavioral Subtyping into liskov-substitution", () => {
        expect(canonicalizeId("Liskov Substitution Principle (LSP)")).toBe("liskov-substitution");
        expect(canonicalizeId("Behavioral Subtyping")).toBe("liskov-substitution");
    });

    it("maps DRY to the quality concept duplicate-code", () => {
        expect(canonicalizeId("Do Not Repeat Yourself (DRY)")).toBe("duplicate-code");
        expect(canonicalizeId("DRY")).toBe("duplicate-code");
    });

    it("keeps SRP and SoC distinct", () => {
        expect(canonicalizeId("Separation of Concerns")).toBe("separation-of-concerns");
        expect(canonicalizeId("SRP")).not.toBe(canonicalizeId("SoC"));
    });

    it("de-abbreviates non-SOLID parentheticals to the descriptive name", () => {
        expect(canonicalizeId("Architecture Decision Records (ADR)")).toBe("architecture-decision-records");
        expect(canonicalizeId("Domain-Driven Design (DDD)")).toBe("domain-driven-design");
        expect(canonicalizeId("RBAC")).toBe("role-based-access-control");
    });
});

describe("canonicalizeId — default slugify + idempotency", () => {
    it("leaves an existing kebab concept id unchanged", () => {
        expect(canonicalizeId("type-safety")).toBe("type-safety");
        expect(canonicalizeId("separation-of-concerns")).toBe("separation-of-concerns");
    });

    it("slugifies a plain arch Title-Case name", () => {
        expect(canonicalizeId("Self-Describing Architecture")).toBe("self-describing-architecture");
        expect(canonicalizeId("Ports and Adapters Architecture")).toBe("ports-and-adapters-architecture");
    });

    it("is idempotent", () => {
        for (const term of ["SRP", "Do Not Repeat Yourself (DRY)", "type-safety", "Contract-First Design"]) {
            const once = canonicalizeId(term);
            expect(canonicalizeId(once)).toBe(once);
        }
    });

    it("treats the canonical form as a no-op", () => {
        expect(isCanonicalId("single-responsibility")).toBe(true);
        expect(isCanonicalId("SRP")).toBe(false);
        expect(isCanonicalId("Single Responsibility Principle (SRP)")).toBe(false);
    });
});

describe("canonicalizeKind — every arch type to one kind", () => {
    it("collapses the principle spellings", () => {
        expect(canonicalizeKind("Principle")).toBe("principle");
        expect(canonicalizeKind("Architecture Principle")).toBe("principle");
        expect(canonicalizeKind("Security Principle")).toBe("principle");
    });

    it("applies the ratified overrides", () => {
        expect(canonicalizeKind("Transaction Property")).toBe("constraint");
        expect(canonicalizeKind("Analysis Tool")).toBe("technique");
        expect(canonicalizeKind("Language Property")).toBe("quality-attribute");
    });

    it("returns null for an unknown type", () => {
        expect(canonicalizeKind("Totally Made Up Type")).toBeNull();
    });

    it("has a closed kind set and every mapped kind is in it", () => {
        expect(KIND_SET).toHaveLength(KIND_COUNT);
        for (const kind of loadKindMap().values()) {
            expect(isCanonicalKind(kind)).toBe(true);
        }
    });

    it("covers every distinct arch type value", () => {
        expect(loadKindMap().size).toBe(ARCH_TYPE_COUNT);
    });
});