# test.web/core/loaders/walk.loader.test.ts

> 205 lines of code and 0 definitions.

Tree: Codebase Testing
Language: typescript
Canonical: https://banes-lab.com/anatomy/testing#file-testing-test-web-core-loaders-walk-loader-test-ts
Source text: https://banes-lab.com/source/testing/test.web/core/loaders/walk.loader.test.ts.txt

Listed in [test.web/core/loaders](https://banes-lab.com/api/source/testing/test.web/core/loaders.md), after [test.web/core/loaders/tree.loader.test.ts](https://banes-lab.com/source/testing/test.web/core/loaders/tree.loader.test.ts.md).

## Contained in

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

## Source

```typescript
import {
    DEFINITION_ANCHOR,
    FILE_ANCHOR,
    FOLDER_ANCHOR,
    READING_TAB,
    TREE_TAB,
} from "@banes-lab/web/core/ids/anatomy.ids.ts";
import { SOURCE_ROOT, WALK_ROOT, sourceLocation, walkLocation } from "@banes-lab/web/core/assets/walk.assets.ts";
import { SOURCE_UNAVAILABLE, WALK_UNAVAILABLE } from "@banes-lab/web/configuration/strings/report.strings.ts";
import { afterEach, describe, expect, it, vi } from "vitest";
import { citedDefinition, listDefinitions } from "@banes-lab/web/core/loaders/definition.loader.ts";
import { definitionBlock, definitionHref, sourceLink } from "@banes-lab/web/domain/converters/source.link.converter.ts";
import { definitionIndexOf, specifierResolverOf } from "@banes-lab/web/core/converters/definition.converter.ts";
import { fileId, folderHref, folderId, nodeHref } from "@banes-lab/web/domain/converters/source.converter.ts";
import {
    loadRecords,
    loadSource,
    loadWalk,
    sourceEntryOf,
    sourceNameOf,
} from "@banes-lab/web/core/loaders/walk.loader.ts";
import { ANATOMY } from "@banes-lab/web/core/generated/anatomy.generated.ts";
import { ANATOMY_FACE } from "@banes-lab/web/configuration/constants/vocabulary.constants.ts";
import { ANATOMY_INDEX } from "@banes-lab/web/core/generated/anatomy.index.generated.ts";
import { ANATOMY_PAGE } from "@banes-lab/web/core/ids/page.ids.ts";
import { ANATOMY_TREES } from "@banes-lab/web/core/registries/anatomy.registry.ts";
import { TYPESCRIPT_LANGUAGE } from "@banes-lab/web/configuration/constants/code.constants.ts";
import { citedSource } from "@banes-lab/web/domain/loaders/anatomy.loader.ts";
import { tabLink } from "@banes-lab/web/core/assets/link.assets.ts";
import { targetOf } from "@banes-lab/web/core/converters/folder.converter.ts";
import { targetOfHref } from "@banes-lab/web/domain/converters/reference.converter.ts";

const VECTOR = "walk.a.generated.svg";
const CELLS = "walk.a.generated.json";
const MARKUP = "<svg></svg>";
const VECTOR_TYPE = "image/svg+xml";
const FACTORY = ["core", "factories", "element.factory.ts"].join("/");
const FACTORY_NAME = "element.factory.ts";
const CREATE = "createElement";
const ABSENT = "noSuchDefinitionAnywhere";
const CITED_TITLE = "the factory";
const RENDERER = ["presentation", "renderers", "tab.renderer.ts"].join("/");
const PAYLOAD = {
    columns: ["state", "depth", "label", "file", "line", "name", "text", "severity"],
    rows: [["call", 1, "identifier", "core/a.ts", 3, "go", "go()", null]],
};

const firstFile = function firstFile(): { readonly path: string; readonly source: string | null } {
    const file = ANATOMY.tree.folders
        .flatMap((folder) => folder.folders.flatMap((child) => child.files))
        .find((candidate) => candidate.source !== null);
    if (file === undefined) {
        throw new Error(VECTOR);
    }
    return file;
};

const factoryLine = function factoryLine(): number {
    const cited = citedDefinition(CREATE);
    if (cited?.file !== FACTORY) {
        throw new Error(CREATE);
    }
    return cited.line;
};

afterEach(() => {
    vi.unstubAllGlobals();
});

describe("loadWalk and loadSource", () => {
    it("fetches the vector and its cells once, unpacks the cells by column, and answers null when either is missing", async () => {
        const fetched = vi.fn(async (url: string) => {
            if (url === walkLocation(VECTOR)) {
                return new Response(MARKUP, { headers: { "content-type": VECTOR_TYPE }, status: 200 });
            }
            if (url === walkLocation(CELLS)) {
                return Response.json(PAYLOAD, { status: 200 });
            }
            return new Response("", { status: 404 });
        });
        vi.stubGlobal("fetch", fetched);
        const walk = await loadWalk({ cells: CELLS, steps: 1, vector: VECTOR });
        expect(walk?.markup).toBe(MARKUP);
        expect(walk?.cells[0]).toStrictEqual({
            depth: 1,
            file: "core/a.ts",
            label: "identifier",
            line: 3,
            name: "go",
            ref: "0",
            severity: null,
            state: "call",
            text: "go()",
        });
        await loadWalk({ cells: CELLS, steps: 1, vector: VECTOR });
        expect(fetched).toHaveBeenCalledTimes(2);
        const logged = vi.spyOn(console, "error").mockReturnValue();
        const missing = { cells: "missing.json", steps: 1, vector: "missing.svg" };
        expect(await loadWalk(missing)).toBeNull();
        expect(logged).toHaveBeenCalledWith(WALK_UNAVAILABLE, missing);
        vi.stubGlobal(
            "fetch",
            async (url: string) =>
                new Response(url === sourceLocation("s.txt") ? "text" : "", {
                    status: url === sourceLocation("s.txt") ? 200 : 404,
                }),
        );
        expect(await loadSource("s.txt")).toBe("text");
        expect(await loadSource("gone.txt")).toBeNull();
        expect(logged).toHaveBeenCalledWith(SOURCE_UNAVAILABLE, "gone.txt");
        logged.mockRestore();
        expect(walkLocation(VECTOR)).toBe(WALK_ROOT + VECTOR);
        expect(sourceLocation("s.txt")).toBe(`${SOURCE_ROOT}s.txt`);
    });
});

describe("targetOfHref", () => {
    it("resolves a tree link to the anatomy collection and a reading link to a chapter", () => {
        const id = fileId(FACTORY);
        expect(targetOfHref(tabLink(ANATOMY_PAGE, TREE_TAB, id))).toStrictEqual({
            face: ANATOMY_FACE,
            ref: `${ANATOMY_FACE}:${id}`,
        });
        expect(targetOfHref(tabLink(ANATOMY_PAGE, READING_TAB, "this-page-is-derived"))?.face).toBe("chapter");
    });
});

describe("loadRecords", () => {
    it("answers null for a node with no records asset, and for an asset whose payload is not records", async () => {
        expect(await loadRecords(ANATOMY_INDEX.nodes[`${FILE_ANCHOR}nowhere`])).toBeNull();
        vi.stubGlobal("fetch", async () => Response.json({ node: "not a record" }));
        const logged = vi.spyOn(console, "error").mockReturnValue();
        expect(await loadRecords("records.malformed.generated.json")).toBeNull();
        expect(logged).toHaveBeenCalledWith(SOURCE_UNAVAILABLE, "records.malformed.generated.json");
        logged.mockRestore();
    });
});

describe("citations by definition name", () => {
    it("links a construct to its file and line, keeps an unresolved name as a definition anchor, and cites its source with the line", () => {
        const line = factoryLine();
        expect(definitionHref(CREATE)).toBe(nodeHref(FACTORY, line));
        expect(nodeHref(FACTORY, line)).toBe(tabLink(ANATOMY_PAGE, TREE_TAB, `${fileId(FACTORY)}:${String(line)}`));
        expect(definitionHref(ABSENT)).toBe(tabLink(ANATOMY_PAGE, TREE_TAB, DEFINITION_ANCHOR + ABSENT));
        expect(folderHref("")).toBe(tabLink(ANATOMY_PAGE, TREE_TAB, folderId("")));
        expect(folderId("")).toBe(`${FOLDER_ANCHOR}root`);
        expect(sourceLink(CREATE, CITED_TITLE)).toBe(`<a href="${definitionHref(CREATE)}">${CITED_TITLE}</a>`);
        expect(targetOf(`#${DEFINITION_ANCHOR}${CREATE}:${FACTORY_NAME}`)).toStrictEqual({
            id: DEFINITION_ANCHOR + CREATE,
            line: null,
            text: FACTORY_NAME,
        });
        expect(citedDefinition(CREATE, "nowhere.ts")).toBeNull();
        const block = definitionBlock(CREATE, CITED_TITLE);
        expect(block).toStrictEqual({ file: FACTORY, kind: "definition", line, name: CREATE, title: CITED_TITLE });
        const cited = citedSource(block);
        expect(cited?.location).toStrictEqual({ file: FACTORY, line, name: CREATE });
        expect(cited?.block.kind).toBe("source");
        expect(cited?.block.language).toBe(TYPESCRIPT_LANGUAGE);
        expect(cited?.block.path).toBe(FACTORY);
        expect(cited?.block.source).toBe(sourceNameOf(FACTORY));
        expect(cited?.block.title).toBe(CITED_TITLE);
        expect(citedSource({ ...block, file: "nowhere.ts" })).toBeNull();
        expect(citedSource({ ...block, line: null })).toBeNull();
    });
});

describe("specifierResolverOf", () => {
    it("resolves an aliased or relative specifier to a file in the set, and nothing outside it", () => {
        const resolve = specifierResolverOf(new Set([FACTORY, RENDERER, "build~core/a.ts"]));
        expect(resolve(`#${["factories", "element.factory"].join("/")}`, RENDERER)).toBe(FACTORY);
        expect(resolve("./tab.renderer", ["presentation", "renderers", "chapter.renderer.ts"].join("/"))).toBe(
            RENDERER,
        );
        expect(resolve("#a", "build~core/b.ts")).toBe("build~core/a.ts");
        expect(resolve("#a", RENDERER)).toBeNull();
        expect(resolve("vitest", RENDERER)).toBeNull();
    });
});

describe("sourceNameOf and the definition index", () => {
    it("finds a file's source asset by path, definitions by name, and files by import specifier", () => {
        const index = definitionIndexOf(ANATOMY_TREES.map((tree) => tree.snapshot.tree));
        const file = firstFile();
        expect(sourceNameOf(file.path)).toBe(file.source);
        expect(sourceEntryOf(file.path)?.source).toBe(file.source);
        expect(sourceEntryOf("nowhere.ts")).toBeNull();
        expect(sourceNameOf("nowhere.ts")).toBeNull();
        const named = index.definitionsNamed(CREATE);
        expect(named.some((location) => location.file === FACTORY)).toBe(true);
        expect(index.definitionsNamed(ABSENT)).toStrictEqual([]);
        expect(listDefinitions()).toStrictEqual(index.listDefinitions());
        expect(
            index.listDefinitions().every((location) => index.definitionsNamed(location.name).includes(location)),
        ).toBe(true);
        expect(index.resolveSpecifier(`#${["core", "factories", "element.factory"].join("/")}`, RENDERER)).toBe(
            FACTORY,
        );
        expect(index.resolveSpecifier(`#${["core", "assets", "link.assets"].join("/")}`, RENDERER)).toBe(
            ["core", "assets", "link.assets.ts"].join("/"),
        );
        expect(
            index.resolveSpecifier("./tab.renderer", ["presentation", "renderers", "chapter.renderer.ts"].join("/")),
        ).toBe(RENDERER);
        expect(
            index.resolveSpecifier(
                ["..", "renderers", "tab.renderer"].join("/"),
                ["presentation", "widgets", "tab.widget.ts"].join("/"),
            ),
        ).toBe(RENDERER);
        expect(index.resolveSpecifier("@govlab/constants", RENDERER)?.endsWith("index.ts")).toBe(true);
        expect(index.resolveSpecifier("vitest", RENDERER)).toBeNull();
        expect(index.resolveSpecifier(`#${["core", "missing"].join("/")}`, RENDERER)).toBeNull();
    });
});
```
