# test.govlab/pipeline/core/converters/report.converter.test.ts

> 75 lines of code and 0 definitions.

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

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

## Contained in

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

## Source

```typescript
import {
    VERIFY_REPORT_FILE,
    VIOLATIONS_REPORT_FILE,
} from "@govlab/pipeline/configuration/constants/report.constants.ts";
import {
    buildArtifact,
    outputOf,
    rowOf,
    rowsOf,
    tallyByStage,
} from "@govlab/pipeline/core/converters/report.converter.ts";
import { describe, expect, it } from "vitest";
import type { ReportRow } from "@govlab/pipeline/types/stage.types.ts";

const LABEL = "verify-codebase";

const row = function row(over: Partial<ReportRow> = {}): ReportRow {
    return { code: 0, count: null, label: "step", out: "", stage: "prepare", ...over };
};

describe("report locations", () => {
    it("names two distinct artifacts", () => {
        expect(VERIFY_REPORT_FILE).not.toBe(VIOLATIONS_REPORT_FILE);
    });
});

describe("tallyByStage", () => {
    it("separates passed from failed within one stage", () => {
        const tally = tallyByStage([row(), row({ code: 1 }), row()]);
        expect(tally.get("prepare")).toStrictEqual({ failed: 1, passed: 2, violations: 0 });
    });

    it("sums counted violations and reads an absent count as zero", () => {
        const tally = tallyByStage([row({ count: 4 }), row({ count: null }), row({ count: 6 })]);
        expect(tally.get("prepare")?.violations).toBe(10);
    });

    it("keeps stages apart", () => {
        const tally = tallyByStage([row(), row({ code: 1, stage: "linting" })]);
        expect([...tally.keys()]).toStrictEqual(["prepare", "linting"]);
    });

    it("tallies nothing for no rows", () => {
        expect(tallyByStage([]).size).toBe(0);
    });
});

describe("buildArtifact", () => {
    it("reports ok only when every step passed", () => {
        expect(buildArtifact([row(), row()], LABEL).ok).toBe(true);
        expect(buildArtifact([row(), row({ code: 1 })], LABEL).ok).toBe(false);
    });

    it("totals steps, passes, failures and violations across the run", () => {
        const artifact = buildArtifact([row({ count: 2 }), row({ code: 1, count: 3, stage: "linting" })], LABEL);
        expect(artifact.totals).toStrictEqual({ failed: 1, passed: 1, steps: 2, violations: 5 });
    });

    it("keeps stages in the order they first appear", () => {
        const artifact = buildArtifact([row({ stage: "linting" }), row({ stage: "prepare" })], LABEL);
        expect(artifact.stages.map((entry) => entry.stage)).toStrictEqual(["linting", "prepare"]);
    });

    it("carries each step's outcome into its stage", () => {
        const artifact = buildArtifact([row({ code: 1, count: 9, label: "Lint" })], LABEL);
        expect(artifact.stages[0]?.steps).toStrictEqual([{ label: "Lint", ok: false, violations: 9 }]);
    });

    it("reports an empty run as ok with no stages", () => {
        const artifact = buildArtifact([], LABEL);
        expect(artifact.ok).toBe(true);
        expect(artifact.stages).toStrictEqual([]);
    });
});

describe("rowOf, outputOf and rowsOf", () => {
    it("read the violation count off a captured outcome", () => {
        expect(rowOf("linting", "Lint", { code: 1, out: "3 errors" }).count).toBe(3);
    });

    it("round-trip a row through its stored output, keeping pass and fail", () => {
        const failed = rowOf("linting", "Lint", { code: 2, out: "3 errors" });
        const [back] = rowsOf([outputOf(failed)]);
        expect(back?.code).not.toBe(0);
        expect(back?.count).toBe(3);
        const passed = outputOf(row());
        expect(rowsOf([passed])[0]?.code).toBe(0);
    });
});
```
