UNPKG

isolate-package

Version:

Isolate monorepo packages to form a self-contained deployable unit

164 lines (138 loc) 4.84 kB
import fs from "fs-extra"; import path from "node:path"; import os from "node:os"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { defineConfig, loadConfigFromFile } from "./config"; /** Shared mock logger instance so assertions can check calls. */ const mockLogger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), }; vi.mock("~/lib/logger", () => ({ useLogger: () => mockLogger, })); describe("loadConfigFromFile", () => { let tempDir: string; let originalCwd: string; beforeEach(async () => { vi.clearAllMocks(); originalCwd = process.cwd(); tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "isolate-config-test-")); process.chdir(tempDir); }); afterEach(async () => { process.chdir(originalCwd); await fs.remove(tempDir); }); it("returns empty object when no config file exists", () => { const config = loadConfigFromFile(); expect(config).toEqual({}); }); it("loads a JSON config file", async () => { await fs.writeJson(path.join(tempDir, "isolate.config.json"), { isolateDirName: "output", workspaceRoot: "../../..", }); const config = loadConfigFromFile(); expect(config).toEqual({ isolateDirName: "output", workspaceRoot: "../../..", }); }); it("loads a TypeScript config file", async () => { await fs.writeFile( path.join(tempDir, "isolate.config.ts"), `export default { isolateDirName: "from-ts", workspaceRoot: "../.." };`, ); const config = loadConfigFromFile(); expect(config).toEqual({ isolateDirName: "from-ts", workspaceRoot: "../..", }); }); it("loads a TypeScript config file that uses defineConfig", async () => { /** * The subprocess can't import from "isolate-package" since it's not * installed in the temp dir, so we inline the defineConfig identity * function to verify the pattern works end-to-end. */ await fs.writeFile( path.join(tempDir, "isolate.config.ts"), [ `const defineConfig = (c: Record<string, unknown>) => c;`, `export default defineConfig({ isolateDirName: "defined" });`, ].join("\n"), ); const config = loadConfigFromFile(); expect(config).toEqual({ isolateDirName: "defined" }); }); it("loads a JavaScript config file", async () => { await fs.writeFile( path.join(tempDir, "isolate.config.js"), `export default { isolateDirName: "from-js", workspaceRoot: "../.." };`, ); const config = loadConfigFromFile(); expect(config).toEqual({ isolateDirName: "from-js", workspaceRoot: "../..", }); }); it("prefers TypeScript config and warns when multiple exist", async () => { await fs.writeJson(path.join(tempDir, "isolate.config.json"), { isolateDirName: "from-json", }); await fs.writeFile( path.join(tempDir, "isolate.config.ts"), `export default { isolateDirName: "from-ts" };`, ); const config = loadConfigFromFile(); expect(config).toEqual({ isolateDirName: "from-ts" }); expect(mockLogger.warn).toHaveBeenCalledWith( expect.stringContaining("Found multiple config files"), ); }); it("prefers JavaScript config over JSON", async () => { await fs.writeJson(path.join(tempDir, "isolate.config.json"), { isolateDirName: "from-json", }); await fs.writeFile( path.join(tempDir, "isolate.config.js"), `export default { isolateDirName: "from-js" };`, ); const config = loadConfigFromFile(); expect(config).toEqual({ isolateDirName: "from-js" }); expect(mockLogger.warn).toHaveBeenCalledWith( expect.stringContaining("Found multiple config files"), ); }); it("throws when the config file has no default export", async () => { await fs.writeFile( path.join(tempDir, "isolate.config.ts"), `export const config = { isolateDirName: "oops" };`, ); expect(() => loadConfigFromFile()).toThrow("Failed to load config from"); }); it("throws when the default export is not an object", async () => { await fs.writeFile( path.join(tempDir, "isolate.config.ts"), `export default "not an object";`, ); expect(() => loadConfigFromFile()).toThrow("Failed to load config from"); }); it("throws when the TypeScript file has a syntax error", async () => { await fs.writeFile( path.join(tempDir, "isolate.config.ts"), `export default {{{`, ); expect(() => loadConfigFromFile()).toThrow("Failed to load config from"); }); }); describe("defineConfig", () => { it("returns the config object unchanged", () => { const input = { isolateDirName: "output", workspaceRoot: "../.." }; const result = defineConfig(input); expect(result).toBe(input); }); });