Files
rea/tests/boundary/cli/versionReportCli.test.ts
T
kiran 5d2c8c2b78 feat(cli)!: export row-oriented results as JSON Lines (#5629)
* feat(cli): add JSON Lines output for row-oriented results (#5487)

- Support opt-in JSON Lines format (--format jsonl) for row-oriented results and collection views with clear record boundaries
- Preserve stable source identities and stream records deterministically line-by-line
- Emit final coverage and limitation metadata as a distinct line with https://rea.dev/schemas/jsonl-coverage-v1.json to prevent confusion with data rows
- Distinguish error outputs with https://rea.dev/schemas/jsonl-error-v1.json
- Reject non-row-oriented results that lack record boundaries with an unreadable_output error
- Document JSON Lines streaming conventions in docs/cli.md
- Add boundary tests covering empty results, multiline strings, partial coverage, large fields, and non-row rejection

* fix(cli): preserve diagnostics, provenance, and nested collections in JSONL

* fix(cli): frame classified failures and reject unrepresented JSONL facets

---------

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-24 02:13:28 +08:00

104 lines
3.6 KiB
TypeScript

import { readFile } from "node:fs/promises";
import { randomUUID } from "node:crypto";
import { mkdir } from "node:fs/promises";
import { join } from "node:path";
import { expect } from "vitest";
import { z } from "zod";
import { versionReportSchema } from "../../../src/domain/versionReport.js";
import { SUPPORTED_NODE_VERSION_RANGE } from "../../../src/domain/runtimeVersion.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { cliTest } from "../../support/cli/cliFixture.js";
const packageSchema = z.object({ name: z.string(), version: z.string() });
cliTest(
"reports version and runtime as a document only when a format is selected",
async ({ cli }) => {
const { name, version } = packageSchema.parse(
JSON.parse(await readFile("package.json", "utf8")),
);
// Unique private values: the report must carry none of them. Literal
// report values such as "node" or "linux" cannot collide with these.
const marker = `rea-private-${randomUUID()}`;
const cwd = await createTestTempDirectory(`${marker}-cwd-`);
const home = join(cwd, `${marker}-home`);
await mkdir(home);
const environment = {
HOME: home,
USERPROFILE: home,
REA_VERSION_REPORT_PRIVATE_MARKER: marker,
};
const json = await cli.run({
arguments: ["--version", "--json"],
cwd,
environment,
});
expect(json.exitCode, json.stderr).toBe(0);
// Piped JSON is one compact document.
expect(json.stdout.trimEnd().split("\n")).toHaveLength(1);
const report = versionReportSchema.parse(JSON.parse(json.stdout));
expect(report).toEqual({
name,
version,
runtime: { id: "node", version: process.versions.node },
platform: process.platform,
architecture: process.arch,
supported_runtime: {
range: SUPPORTED_NODE_VERSION_RANGE,
satisfied: true,
},
});
expect(json.stdout).not.toContain(marker);
const jsonl = await cli.run({
arguments: ["--version", "--format", "jsonl"],
cwd,
environment,
});
expect(jsonl.exitCode, jsonl.stderr).toBe(0);
expect(jsonl.stdout.trimEnd().split("\n")).toHaveLength(1);
expect(versionReportSchema.parse(JSON.parse(jsonl.stdout))).toEqual(report);
const yaml = await cli.run({
arguments: ["--version", "--format=yaml"],
cwd,
});
expect(yaml.exitCode, yaml.stderr).toBe(0);
expect(yaml.stdout).toContain(`version: ${version}`);
expect(yaml.stdout).toContain(`architecture: ${process.arch}`);
// Plain --version keeps the bare version string.
const plain = await cli.run({ arguments: ["--version"], cwd });
expect(plain.exitCode, plain.stderr).toBe(0);
expect(plain.stdout).toBe(`${version}\n`);
// Valid other output controls keep the plain version; invalid
// combinations keep their existing output-flag error.
const filtered = await cli.run({
arguments: ["--version", "--json", "--filter-output", "version"],
cwd,
});
expect(filtered.exitCode, filtered.stderr).toBe(0);
expect(filtered.stdout).toBe(`${version}\n`);
const windowed = await cli.run({
arguments: ["--version", "--json", "--token-limit", "5"],
cwd,
});
expect(windowed.exitCode).toBe(1);
expect(windowed.json).toMatchObject({
error: { code: "UNSUPPORTED_OUTPUT_COMBINATION" },
});
// Help keeps precedence over --version.
const help = await cli.run({
arguments: ["--version", "--json", "--help"],
cwd,
});
expect(help.exitCode, help.stderr).toBe(0);
expect(help.stdout).toContain("Usage: rea");
},
);