import { describe, expect, it } from "vitest"; import { createStackConfig, formatServiceLogs, getDefaultTemporalCandidates, resolveTemporalCli, selectServicesForLogs, } from "../../scripts/dev-stack/stack.mjs"; describe("createStackConfig", () => { it("derives frontend and sibling backend paths from the workspace root", () => { const config = createStackConfig("/Volumes/DockCase/codes/auto-virtual-tryon-frontend"); expect(config.frontendRoot).toBe("/Volumes/DockCase/codes/auto-virtual-tryon-frontend"); expect(config.backendRoot).toBe("/Volumes/DockCase/codes/auto-virtual-tryon"); expect(config.runtimeRoot).toBe( "/Volumes/DockCase/codes/auto-virtual-tryon-frontend/.dev-stack", ); expect(config.temporalDatabaseFile).toBe( "/Volumes/DockCase/codes/auto-virtual-tryon-frontend/.dev-stack/temporal-cli-dev.db", ); }); it("builds the expected service commands", () => { const config = createStackConfig("/Volumes/DockCase/codes/auto-virtual-tryon-frontend"); expect(config.services).toEqual([ { key: "temporal", cwd: "/Volumes/DockCase/codes/auto-virtual-tryon-frontend/.dev-stack", port: 7233, command: [ "__TEMPORAL_CLI__", "server", "start-dev", "--ip", "127.0.0.1", "--port", "7233", "--headless", "--db-filename", "/Volumes/DockCase/codes/auto-virtual-tryon-frontend/.dev-stack/temporal-cli-dev.db", ], }, { key: "backend-api", cwd: "/Volumes/DockCase/codes/auto-virtual-tryon", port: 8000, command: [ "/Volumes/DockCase/codes/auto-virtual-tryon/.venv/bin/python", "-m", "uvicorn", "app.main:app", "--host", "127.0.0.1", "--port", "8000", ], }, { key: "backend-worker", cwd: "/Volumes/DockCase/codes/auto-virtual-tryon", port: null, command: [ "/Volumes/DockCase/codes/auto-virtual-tryon/.venv/bin/python", "-m", "app.workers.runner", ], }, { key: "frontend", cwd: "/Volumes/DockCase/codes/auto-virtual-tryon-frontend", port: 3000, command: [ "/Volumes/DockCase/codes/auto-virtual-tryon-frontend/node_modules/.bin/next", "dev", "--hostname", "127.0.0.1", "--port", "3000", ], }, ]); }); }); describe("resolveTemporalCli", () => { it("prefers a CLI already available on PATH", () => { const resolved = resolveTemporalCli({ pathLookupResult: "/usr/local/bin/temporal", candidatePaths: ["/tmp/temporal-sdk-python-1.24.0"], existingPaths: new Set(["/usr/local/bin/temporal", "/tmp/temporal-sdk-python-1.24.0"]), }); expect(resolved).toBe("/usr/local/bin/temporal"); }); it("falls back to a downloaded SDK binary when PATH does not contain temporal", () => { const resolved = resolveTemporalCli({ pathLookupResult: null, candidatePaths: ["/tmp/temporal-sdk-python-1.24.0", "/tmp/temporal-cli"], existingPaths: new Set(["/tmp/temporal-sdk-python-1.24.0"]), }); expect(resolved).toBe("/tmp/temporal-sdk-python-1.24.0"); }); it("returns null when no temporal binary is available", () => { const resolved = resolveTemporalCli({ pathLookupResult: null, candidatePaths: ["/tmp/temporal-sdk-python-1.24.0"], existingPaths: new Set(), }); expect(resolved).toBeNull(); }); }); describe("getDefaultTemporalCandidates", () => { it("includes the known SDK cache binary names under the temp directory", () => { expect(getDefaultTemporalCandidates("/var/folders/example/T")).toEqual([ "/var/folders/example/T/temporal-sdk-python-1.24.0", "/var/folders/example/T/temporal-sdk-python-1.25.0", "/var/folders/example/T/temporal-sdk-python-1.26.0", "/var/folders/example/T/temporal-cli", ]); }); }); describe("selectServicesForLogs", () => { it("returns every service when no filter is provided", () => { const config = createStackConfig("/Volumes/DockCase/codes/auto-virtual-tryon-frontend"); expect( selectServicesForLogs(config.services, null).map((service: { key: string }) => service.key), ).toEqual(["temporal", "backend-api", "backend-worker", "frontend"]); }); it("filters to a single service key", () => { const config = createStackConfig("/Volumes/DockCase/codes/auto-virtual-tryon-frontend"); expect( selectServicesForLogs(config.services, "frontend").map((service: { key: string }) => service.key), ).toEqual(["frontend"]); }); it("throws a helpful error for an unknown service", () => { const config = createStackConfig("/Volumes/DockCase/codes/auto-virtual-tryon-frontend"); expect(() => selectServicesForLogs(config.services, "foo")).toThrow( "Unknown service \"foo\". Expected one of: temporal, backend-api, backend-worker, frontend", ); }); }); describe("formatServiceLogs", () => { it("formats sections with stable headers and preserves line order", () => { const output = formatServiceLogs([ { key: "frontend", logFilePath: "/tmp/frontend.log", lines: ["> dev", "ready"], }, { key: "backend-api", logFilePath: "/tmp/backend-api.log", lines: [], }, ]); expect(output).toBe( [ "--- frontend (/tmp/frontend.log) ---", "> dev", "ready", "", "--- backend-api (/tmp/backend-api.log) ---", "(log file is empty)", ].join("\n"), ); }); });