# test.govlab/docs/core/analyzers/program.fixture.ts

> 46 lines of code and 9 definitions.

Tree: Codebase Testing
Language: typescript
Canonical: https://banes-lab.com/anatomy/testing#file-testing-test-govlab-docs-core-analyzers-program-fixture-ts
Source text: https://banes-lab.com/source/testing/test.govlab/docs/core/analyzers/program.fixture.ts.txt

Listed in [test.govlab/docs/core/analyzers](https://banes-lab.com/api/source/testing/test.govlab/docs/core/analyzers.md), after [test.govlab/docs/core/analyzers/package.analyzer.test.ts](https://banes-lab.com/source/testing/test.govlab/docs/core/analyzers/package.analyzer.test.ts.md) and before [test.govlab/docs/core/analyzers/reference.analyzer.test.ts](https://banes-lab.com/source/testing/test.govlab/docs/core/analyzers/reference.analyzer.test.ts.md).

## Definitions

- `ProgramFixture` (interface_declaration, line 9, exported)
- `programFor` (lexical_declaration, line 15, exported)
- `dir` (lexical_declaration, line 16, exported)
- `paths` (lexical_declaration, line 17, exported)
- `full` (lexical_declaration, line 18, exported)
- `program` (lexical_declaration, line 23, exported)
- `defined` (lexical_declaration, line 33, exported)
- `sourceFileOf` (lexical_declaration, line 40, exported)
- `file` (lexical_declaration, line 41, exported)

## Contained in

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

## Source

```typescript
import { dirname, join } from "node:path";
import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
import type { ProgramAnalysis } from "@govlab/docs/types/code.types.ts";
import { moduleCompilerOptions } from "@govlab/docs/core/resolvers/program.resolver.ts";
import { tmpdir } from "node:os";
import ts from "typescript";
import { writeVerbatim } from "@govlab/canonical-write";

export interface ProgramFixture {
    analysis: ProgramAnalysis;
    dir: string;
    dispose: () => void;
}

export const programFor = function programFor(files: Readonly<Record<string, string>>): ProgramFixture {
    const dir = mkdtempSync(join(tmpdir(), "doc-program-"));
    const paths = Object.entries(files).map(([rel, body]) => {
        const full = join(dir, ...rel.split("/"));
        mkdirSync(dirname(full), { recursive: true });
        writeVerbatim(full, body);
        return full;
    });
    const program = ts.createProgram(paths, moduleCompilerOptions(dir));
    return {
        analysis: { checker: program.getTypeChecker(), dirPosix: dir.split("\\").join("/"), program },
        dir,
        dispose: () => {
            rmSync(dir, { force: true, recursive: true });
        },
    };
};

export const defined = function defined<T>(value: T | null | undefined, label: string): T {
    if (value === undefined || value === null) {
        throw new Error(label);
    }
    return value;
};

export const sourceFileOf = function sourceFileOf(fixture: ProgramFixture, rel: string): ts.SourceFile {
    const file = fixture.analysis.program.getSourceFile(
        join(fixture.dir, ...rel.split("/"))
            .split("\\")
            .join("/"),
    );
    if (file === undefined) {
        throw new Error(rel);
    }
    return file;
};
```
