/*
Unit tests for yaml syntax validate covering its documented public contract and regression-sensitive edge cases.
- Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only.
- RFC-0792: initial unit tests for yaml-syntax-error validation rule.
*/
import { test, expect, beforeEach, afterEach } from "vitest";
import { mkdtemp, rm, mkdir, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { stringify as stringifyYaml } from "yaml";
import { runSternsystemValidate } from "./sternsystem-validate.ts";
import { makeInput, makeContext, writeSystemConfig, BASE_SETUP } from "./test-helpers.ts";
let testRoot: string;
let workspaceRoot: string;
beforeEach(async () => {
testRoot = await mkdtemp(join(tmpdir(), "yaml-syntax-validate-test-"));
workspaceRoot = join(testRoot, "workspace");
await mkdir(workspaceRoot, { recursive: true });
await BASE_SETUP(workspaceRoot);
});
afterEach(async () => {
await rm(testRoot, { recursive: true, force: true });
});
test("valid YAML files produce no yaml-syntax-error violations", async () => {
await writeSystemConfig(workspaceRoot, [
{ path: "../systems-cache/test-bundle", storageType: "non-bare" },
]);
const cacheDir = join(workspaceRoot, "..", "systems-cache", "test-bundle");
const validDnsRecords = {
records: [{ type: "A", name: "example.com", content: "1.2.3.4" }],
};
await writeFile(join(cacheDir, "dns-records.yaml"), stringifyYaml(validDnsRecords), "utf8");
const result = await runSternsystemValidate(makeInput({}), makeContext(workspaceRoot));
const yamlViolations = result.data!.violations.filter((v) => v.rule === "yaml-syntax-error");
expect(yamlViolations).toHaveLength(0);
});
test("broken YAML file produces yaml-syntax-error violation with file name and error message", async () => {
await writeSystemConfig(workspaceRoot, [
{ path: "../systems-cache/test-bundle", storageType: "non-bare" },
]);
const cacheDir = join(workspaceRoot, "..", "systems-cache", "test-bundle");
const brokenYaml = "records:\n - type: A\n name: example.com\n content: 1.2.3.4\n";
await writeFile(join(cacheDir, "dns-records.yaml"), brokenYaml, "utf8");
const result = await runSternsystemValidate(makeInput({}), makeContext(workspaceRoot));
const yamlViolations = result.data!.violations.filter((v) => v.rule === "yaml-syntax-error");
expect(yamlViolations).toHaveLength(1);
expect(yamlViolations[0].message).toContain("dns-records.yaml");
expect(yamlViolations[0].message).toContain("YAML syntax error");
});
test("system directory with only system-config.yaml produces no yaml-syntax-error violations", async () => {
await writeSystemConfig(workspaceRoot, [
{ path: "../systems-cache/test-bundle", storageType: "non-bare" },
]);
const result = await runSternsystemValidate(makeInput({}), makeContext(workspaceRoot));
const yamlViolations = result.data!.violations.filter((v) => v.rule === "yaml-syntax-error");
expect(yamlViolations).toHaveLength(0);
});
test("YAML file in subdirectory is not scanned", async () => {
await writeSystemConfig(workspaceRoot, [
{ path: "../systems-cache/test-bundle", storageType: "non-bare" },
]);
const cacheDir = join(workspaceRoot, "..", "systems-cache", "test-bundle");
await mkdir(join(cacheDir, "subdir"), { recursive: true });
const brokenYaml = "records:\n - type: A\n name: example.com\n content: 1.2.3.4\n";
await writeFile(join(cacheDir, "subdir", "broken.yaml"), brokenYaml, "utf8");
const result = await runSternsystemValidate(makeInput({}), makeContext(workspaceRoot));
const yamlViolations = result.data!.violations.filter((v) => v.rule === "yaml-syntax-error");
expect(yamlViolations).toHaveLength(0);
});