// Row 325 (#1821): factory validation must load the repository's actual project document. import { test } from "node:test"; import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { REPO, REPO_ROLES, systemConfig, tmp, writeJson } from "./helpers.mjs"; const CASE1 = join(REPO, "docs/guides/case1-business.mosaic-stack.json"); const PROJECT = join(REPO, ".mosaic/project.json"); const document = () => JSON.parse(readFileSync(CASE1, "utf8")); function fixture(t, { oldKey = false } = {}) { const root = tmp(); t.after(() => rmSync(root, { recursive: true, force: true })); const doc = document(); assert.equal(Object.keys(doc.projects).length, 1); const [key] = Object.keys(doc.projects); const projectRoot = join(root, "checkout"); const projectFile = join(projectRoot, ".mosaic/project.json"); const bytes = readFileSync(PROJECT); mkdirSync(join(projectRoot, ".mosaic"), { recursive: true }); writeFileSync(projectFile, bytes); assert.deepEqual(readFileSync(projectFile), bytes, "fixture must use the real project's unmodified bytes"); const entry = { ...doc.projects[key], root: projectRoot }; doc.projects = { [oldKey ? "mosaic-stack" : key]: entry }; const config = systemConfig(root); writeJson(join(root, "config/businesses/mosaic-stack.json"), doc); return { project: JSON.parse(bytes), projectFile, validate: () => spawnSync(process.execPath, [join(REPO, "packages/organization/src/cli.mjs"), "validate", "mosaic-stack"], { env: { ...process.env, HOME: root, MOSAIC_CONFIG: config, MOSAIC_ROLES_DIR: REPO_ROLES }, encoding: "utf8", timeout: 30000, }), }; } test("row 325: the Case 1 project's sole key matches the repository project id", () => { const doc = document(); const project = JSON.parse(readFileSync(PROJECT, "utf8")); assert.equal(project.id, "stack"); assert.deepEqual(Object.keys(doc.projects), [project.id]); assert.equal(doc.id, "mosaic-stack"); assert.equal(doc.projects[project.id].root, "/srv/mosaic/src/mosaic-stack"); }); test("row 325: real business validate reports the copied repository project valid", (t) => { const x = fixture(t); const r = x.validate(); assert.equal(r.status, 0, r.stdout + r.stderr); const result = JSON.parse(r.stdout); assert.equal(result.business, "mosaic-stack"); assert.deepEqual(result.projects, { [x.project.id]: "valid" }); assert.doesNotMatch(r.stderr, /no project file|project variables/); }); test("row 325: the old mosaic-stack project key refuses against those same project bytes", (t) => { const x = fixture(t, { oldKey: true }); const r = x.validate(); assert.equal(r.status, 2, r.stdout + r.stderr); assert.equal(r.stdout, ""); assert.match(r.stderr, /project file of project mosaic-stack has id that does not match the declared project key/); // The refusal names the declared key, never the project root (PR #1916). assert.ok(!r.stderr.includes(x.projectFile), r.stderr); assert.doesNotMatch(r.stderr, /no project file/); });