# test.paths/core/resolvers/location.resolver.test.ts

> 153 lines of code and 0 definitions.

Tree: Codebase Testing
Language: typescript
Canonical: https://banes-lab.com/anatomy/testing#file-testing-test-paths-core-resolvers-location-resolver-test-ts
Source text: https://banes-lab.com/source/testing/test.paths/core/resolvers/location.resolver.test.ts.txt

Listed in [test.paths/core/resolvers](https://banes-lab.com/api/source/testing/test.paths/core/resolvers.md).

## Contained in

- [test.paths/core/resolvers](https://banes-lab.com/anatomy/testing/folder-testing-test-paths-core-resolvers.md)

## Source

```typescript
import { ROOT, absolutePath, paths, relativePath } from "@ssot/paths";
import {
    branchWithoutLocation,
    descendsThroughLeaf,
    rootNotFound,
    unknownKey,
} from "@ssot/paths/configuration/strings/location.strings.ts";
import { describe, expect, it } from "vitest";
import { isPathTree, isRecord } from "@ssot/paths/core/predicates/location.predicate.ts";
import { readFileSync, readdirSync } from "node:fs";
import { LOCATION_TREE } from "@ssot/paths/core/loaders/location.loader.ts";
import { excludeMatcher } from "@govlab/quality/config";
import path from "node:path";
import ts from "typescript";

const isExcluded = await excludeMatcher(process.cwd());

const KEY_FUNCTIONS = new Set(["relativePath", "absolutePath"]);

const filesUnder = function filesUnder(dir: string): string[] {
    return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
        const full = path.join(dir, entry.name);
        if (isExcluded(full)) {
            return [];
        }
        if (entry.isDirectory()) {
            return filesUnder(full);
        }
        return entry.name.endsWith(".ts") && !entry.name.includes(".test.") ? [full] : [];
    });
};

const keyOf = function keyOf(node: ts.Node): string | null {
    if (!ts.isCallExpression(node) || !ts.isIdentifier(node.expression)) {
        return null;
    }
    const [first] = node.arguments;
    const isKeyCall = KEY_FUNCTIONS.has(node.expression.text);
    return isKeyCall && first !== undefined && ts.isStringLiteralLike(first) ? first.text : null;
};

const keysIn = function keysIn(file: string, text: string): string[] {
    const keys: string[] = [];
    const visit = function visit(node: ts.Node): void {
        const key = keyOf(node);
        if (key !== null) {
            keys.push(key);
        }
        ts.forEachChild(node, visit);
    };
    visit(ts.createSourceFile(file, text, ts.ScriptTarget.Latest, false, ts.ScriptKind.TS));
    return keys;
};

interface KeyUse {
    file: string;
    key: string;
}

const collectKeyUses = function collectKeyUses(): KeyUse[] {
    return filesUnder(ROOT).flatMap((file) => {
        const text = readFileSync(file, "utf8");
        const mentions = [...KEY_FUNCTIONS].some((name) => text.includes(name));
        return (mentions ? keysIn(file, text) : []).map((key) => ({
            file: path.relative(ROOT, file).split(path.sep).join("/"),
            key,
        }));
    });
};

describe("isRecord and isPathTree", () => {
    it("accepts a tree whose every leaf is a string, and nothing else", () => {
        expect(isRecord({})).toBe(true);
        expect(isRecord(null)).toBe(false);
        expect(isPathTree({ a: "x", b: { c: "z", root: "y" } })).toBe(true);
        expect(isPathTree({ a: 1 })).toBe(false);
        expect(isPathTree("x")).toBe(false);
    });
});

describe("LOCATION_TREE and paths", () => {
    it("loads the declared tree, and freezes every leaf joined onto the root", () => {
        expect(isPathTree(LOCATION_TREE)).toBe(true);
        expect(Object.isFrozen(paths)).toBe(true);
        expect(Object.keys(paths)).toStrictEqual(Object.keys(LOCATION_TREE));
    });
});

describe("absolutePath and relativePath", () => {
    it("resolve a branch by its own location and a leaf beneath it", () => {
        const member = relativePath("project.paths");
        expect(member.length).toBeGreaterThan(0);
        expect(absolutePath("project.paths")).toBe(path.join(ROOT, member));
        expect(relativePath("project.paths", "a", "b")).toBe(`${member}/a/b`);
    });

    it("refuse an unknown key, a branch with no location and a step through a leaf", () => {
        expect(() => relativePath("no.such.key")).toThrow(unknownKey("no.such.key"));
        expect(() => relativePath("project")).toThrow(branchWithoutLocation("project"));
        expect(() => relativePath("project.paths.deeper")).toThrow(descendsThroughLeaf("project.paths.deeper"));
        expect(rootNotFound("banes-lab")).toContain("'banes-lab'");
    });
});

describe("relativePath composition", () => {
    it("resolves a flat key", () => {
        expect(relativePath("thirdParty")).toBe("_third-party");
        expect(relativePath("docArch")).toBe("doc-arch");
    });

    it("prefixes a child with its branch location", () => {
        expect(relativePath("govlab.constants")).toBe("govlab.root/govlab.constants");
        expect(relativePath("govlabHost.reports.lint")).toBe(".govlab/_quality.reports.generated/lint");
        expect(relativePath("codebase.testing.rules")).toBe("codebase.testing/test.rules");
    });

    it("composes through more than one branch", () => {
        expect(relativePath("govlab.utils.codeParse")).toBe("govlab.root/govlab.utils/code-parse");
    });

    it("returns a branch's own location without doubling the segment", () => {
        expect(relativePath("govlab.root")).toBe("govlab.root");
        expect(relativePath("govlab.utils.root")).toBe("govlab.root/govlab.utils");
        expect(relativePath("app.root")).toBe("banes-lab.root");
    });

    it("appends extra segments after the resolved key", () => {
        expect(relativePath("govlab.quality", "runtime")).toBe("govlab.root/govlab.quality/runtime");
    });

    it("rejects an unknown key rather than resolving to nothing", () => {
        expect(() => relativePath("govlab.nope")).toThrow("unknown path key");
    });

    it("resolves a branch that declares its own location, so a key survives gaining children", () => {
        expect(relativePath("govlab.utils")).toBe("govlab.root/govlab.utils");
        expect(relativePath("app.root")).toBe("banes-lab.root");
        expect(relativePath("codebase.testing")).toBe("codebase.testing");
    });

    it("rejects a branch that declares no location of its own", () => {
        expect(() => relativePath("codebase")).toThrow("no own location");
    });

    it("anchors the composed path at the workspace root", () => {
        expect(absolutePath("govlab.utils.codeParse").split("\\").join("/")).toContain(
            "govlab.root/govlab.utils/code-parse",
        );
    });
});

describe("every paths SSOT key used in the workspace resolves", () => {
    const uses = collectKeyUses();

    it("finds key uses to check", () => {
        expect(uses.length).toBeGreaterThan(0);
    });

    it("counts only a real call, never a call written inside a string sample", () => {
        const sample = 'const text = \'relativePath("no.such.key")\';\nrelativePath("app.root");';
        expect(keysIn("sample.ts", sample)).toStrictEqual(["app.root"]);
    });

    it("resolves every key, so a renamed or deleted key cannot ship", () => {
        const broken = uses
            .filter((use) => {
                try {
                    relativePath(use.key);
                    return false;
                } catch {
                    return true;
                }
            })
            .map((use) => `${use.file} → relativePath("${use.key}")`);
        expect([...new Set(broken)]).toEqual([]);
    });
});
```
