import { execFile } from "node:child_process"; import { mkdir, mkdtemp, rm, symlink, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { promisify } from "node:util"; import { afterEach, describe, expect, it } from "vitest"; const execute = promisify(execFile); const temporaryRoots: string[] = []; describe("legacy project manifest builder", () => { afterEach(async () => { while (temporaryRoots.length > 0) { const root = temporaryRoots.pop(); if (root !== undefined) await rm(root, { recursive: true, force: true }); } }); it("stops at a project root and excludes trash projects", async () => { const root = await mkdtemp(join(tmpdir(), "cph-legacy-manifest-")); temporaryRoots.push(root); const projectRoot = join(root, "物理", "legacy__牛顿力学"); await mkdir(join(projectRoot, "workspace", "nested"), { recursive: true }); await mkdir(join(projectRoot, "_raw"), { recursive: true }); await mkdir(join(root, ".trash", "deleted"), { recursive: true }); await writeFile(join(projectRoot, "project.json"), JSON.stringify({ id: "legacy", name: "牛顿力学", folderPath: ["物理"], })); await writeFile(join(projectRoot, "workspace", "nested", "project.json"), "not metadata"); await writeFile(join(projectRoot, "_raw", "project.json"), "not metadata"); await writeFile(join(root, ".trash", "deleted", "project.json"), JSON.stringify({ id: "deleted", name: "Deleted", })); const { stdout } = await execute(process.execPath, [ resolve("deploy/build_legacy_project_manifest.mjs"), root, ]); expect(JSON.parse(stdout)).toEqual([{ legacyId: "legacy", name: "牛顿力学", folderPath: ["物理"], sourceRelativePath: "物理/legacy__牛顿力学", }]); }); it("reports untracked symlinked entries instead of silently omitting them", async () => { const root = await mkdtemp(join(tmpdir(), "cph-legacy-manifest-link-")); temporaryRoots.push(root); await symlink("/tmp", join(root, "linked-project")); const result = await execute(process.execPath, [ resolve("deploy/build_legacy_project_manifest.mjs"), root, ]); expect(result.stderr).toContain("skip untracked symbolic link"); expect(JSON.parse(result.stdout)).toEqual([]); }); });