import { describe, expect, test } from "bun:test"; import { getDatabaseCredentials } from "../../command/db"; import { runDown } from "../../command/down"; import { runPs } from "../../command/ps"; import { runRestart } from "../../command/restart"; import { runRollback } from "../../command/rollback"; import { getRemoteS3Credentials } from "../../command/s3"; import { runStop } from "../../command/stop"; import type { ApiRequestInit } from "../../lib/api"; type Call = { path: string; init?: ApiRequestInit }; function requestReturning(result: T, calls: Call[]) { return async (path: string, init?: ApiRequestInit): Promise => { calls.push({ path, init }); return result as unknown as R; }; } describe("workspace API command runners", () => { test("ps requests structured status and renders it locally", async () => { const calls: Call[] = []; const output = await runPs( "shop/demo", true, requestReturning( [ { namespace: "shop-demo", roots: [ { id: "Deployment/web", status: { label: "1/1", level: "good" as const }, children: [], }, ], }, ], calls, ), ); expect(calls).toEqual([ { path: "/workspaces/shop%2Fdemo/status?includeIdle=true", init: undefined, }, ]); expect(output).toContain("Deployment/web"); expect(output).toContain("\u001b[42m"); }); test("stop and restart use lifecycle actions with optional targeting", async () => { const calls: Call[] = []; const request = requestReturning({ deployments: ["web"] }, calls); await runStop("shop", request); await runRestart("shop", undefined, request); await runRestart("shop", "worker", request); expect(calls).toEqual([ { path: "/workspaces/shop/lifecycle", init: { method: "POST", json: { action: "stop" } }, }, { path: "/workspaces/shop/lifecycle", init: { method: "POST", json: { action: "restart" } }, }, { path: "/workspaces/shop/lifecycle", init: { method: "POST", json: { action: "restart", services: ["worker"] }, }, }, ]); }); test("rollback and down delegate complete server-side operations", async () => { const calls: Call[] = []; await runRollback( "shop", "web", 45_000, requestReturning({ deployments: ["web"] }, calls), ); await runDown( "shop", true, requestReturning({ full: true, retained: [], delete: [] }, calls), ); expect(calls).toEqual([ { path: "/workspaces/shop/rollback", init: { method: "POST", json: { services: ["web"], timeoutMs: 45_000 }, }, }, { path: "/workspaces/shop/down", init: { method: "POST", json: { full: true } }, }, ]); }); test("database and S3 credential requests send resolved local claims", async () => { const calls: Call[] = []; const databaseClaim = { service: "web", username: "app", database: "app", secretName: "postgres-app", }; const s3Claim = { service: "web", key: "assets", bucket: "assets" }; await getDatabaseCredentials( "shop", databaseClaim, requestReturning({ username: "app", password: "secret" }, calls), ); await getRemoteS3Credentials( "shop", s3Claim, requestReturning({ AWS_ACCESS_KEY_ID: "key" }, calls), ); expect(calls).toEqual([ { path: "/workspaces/shop/databases/credentials", init: { method: "POST", json: { claim: databaseClaim } }, }, { path: "/workspaces/shop/storage/credentials", init: { method: "POST", json: { claim: s3Claim } }, }, ]); }); });