Files
kuber/tests/command/api-migration.test.ts
T
2026-09-03 11:28:30 +07:00

142 lines
3.8 KiB
TypeScript

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<T>(result: T, calls: Call[]) {
return async <R>(path: string, init?: ApiRequestInit): Promise<R> => {
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 } },
},
]);
});
});