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

> 86 lines of code and 0 definitions.

Tree: Codebase Testing
Language: typescript
Canonical: https://banes-lab.com/anatomy/testing#file-testing-test-govlab-quality-core-converters-canon-converter-test-ts
Source text: https://banes-lab.com/source/testing/test.govlab/quality/core/converters/canon.converter.test.ts.txt

Listed in [test.govlab/quality/core/converters](https://banes-lab.com/api/source/testing/test.govlab/quality/core/converters.md), after [test.govlab/quality/core/converters/canon.concept.converter.test.ts](https://banes-lab.com/source/testing/test.govlab/quality/core/converters/canon.concept.converter.test.ts.md) and before [test.govlab/quality/core/converters/comment.converter.test.ts](https://banes-lab.com/source/testing/test.govlab/quality/core/converters/comment.converter.test.ts.md).

## Contained in

- [test.govlab/quality/core/converters](https://banes-lab.com/anatomy/testing/folder-testing-test-govlab-quality-core-converters.md)

## Source

```typescript
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);
    });
});
```
