/*
Unit tests for env persist covering collectEnvFiles; persistEnvFilesToCacheClone; restoreEnvFilesFromCacheClone. It also guards the 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-1311: Compass header sweep — declares the env suite's contract for test-file scaffold coverage.
*/
import { test, expect, describe, beforeEach, afterEach } from "vitest";
import { mkdtempSync, rmSync, writeFileSync, readFileSync } from "node:fs";
import { join } from "node:path";
import {
collectEnvFiles,
persistEnvFilesToCacheClone,
restoreEnvFilesFromCacheClone,
} from "../env-persist.ts";
let workpieceDir: string;
let cacheCloneDir: string;
beforeEach(() => {
workpieceDir = mkdtempSync(join(process.cwd(), "tmp-env-workpiece-"));
cacheCloneDir = mkdtempSync(join(process.cwd(), "tmp-env-cache-"));
});
afterEach(() => {
rmSync(workpieceDir, { recursive: true, force: true });
rmSync(cacheCloneDir, { recursive: true, force: true });
});
describe("collectEnvFiles", () => {
test("returns empty array when dir does not exist", async () => {
expect(await collectEnvFiles("/nonexistent/path")).toEqual([]);
});
test("collects .env files", async () => {
writeFileSync(join(workpieceDir, ".env"), "KEY=value\n");
writeFileSync(join(workpieceDir, ".env.production"), "KEY2=value2\n");
const files = await collectEnvFiles(workpieceDir);
expect(files).toContain(".env");
expect(files).toContain(".env.production");
});
test("excludes .env.example", async () => {
writeFileSync(join(workpieceDir, ".env"), "KEY=value\n");
writeFileSync(join(workpieceDir, ".env.example"), "KEY=value\n");
const files = await collectEnvFiles(workpieceDir);
expect(files).toContain(".env");
expect(files).not.toContain(".env.example");
});
test("excludes .env.*.example pattern", async () => {
writeFileSync(join(workpieceDir, ".env"), "KEY=value\n");
writeFileSync(join(workpieceDir, ".env.production.example"), "KEY=value\n");
const files = await collectEnvFiles(workpieceDir);
expect(files).toContain(".env");
expect(files).not.toContain(".env.production.example");
});
});
describe("persistEnvFilesToCacheClone", () => {
test("copies .env files from workpiece to cache clone", async () => {
writeFileSync(join(workpieceDir, ".env"), "KEY=value\n");
const result = await persistEnvFilesToCacheClone(workpieceDir, cacheCloneDir);
expect(result.copied).toContain(".env");
expect(result.skipped).toEqual([]);
const content = readFileSync(join(cacheCloneDir, ".env"), "utf8");
expect(content).toBe("KEY=value\n");
});
test("returns empty copied when no .env files exist", async () => {
const result = await persistEnvFilesToCacheClone(workpieceDir, cacheCloneDir);
expect(result.copied).toEqual([]);
});
});
describe("restoreEnvFilesFromCacheClone", () => {
test("copies .env files from cache clone to workpiece", async () => {
writeFileSync(join(cacheCloneDir, ".env"), "KEY=value\n");
const result = await restoreEnvFilesFromCacheClone(cacheCloneDir, workpieceDir);
expect(result.copied).toContain(".env");
const content = readFileSync(join(workpieceDir, ".env"), "utf8");
expect(content).toBe("KEY=value\n");
});
test("replaces PUBLIC_IMAGE_PROVIDER with build-portable", async () => {
writeFileSync(join(cacheCloneDir, ".env"), "PUBLIC_IMAGE_PROVIDER=astro\nOTHER=value\n");
await restoreEnvFilesFromCacheClone(cacheCloneDir, workpieceDir);
const content = readFileSync(join(workpieceDir, ".env"), "utf8");
expect(content).toContain("PUBLIC_IMAGE_PROVIDER=build-portable");
expect(content).not.toContain("PUBLIC_IMAGE_PROVIDER=astro");
expect(content).toContain("OTHER=value");
});
test("returns empty copied when no .env files exist", async () => {
const result = await restoreEnvFilesFromCacheClone(cacheCloneDir, workpieceDir);
expect(result.copied).toEqual([]);
});
});