import { describe, expect, test } from "bun:test"; import { renderUsage } from "citty"; import { login, logout, whoami } from "../../command/auth"; import { db } from "../../command/db"; import { down } from "../../command/down"; import { exec } from "../../command/exec"; import { exportCommand } from "../../command/export"; import { logs } from "../../command/logs"; import { initializeCompletion, main } from "../../command/main"; import { maintenance } from "../../command/maintenance"; import { ps } from "../../command/ps"; import { restart } from "../../command/restart"; import { rollback } from "../../command/rollback"; import { s3 } from "../../command/s3"; import { start } from "../../command/start"; import { stop } from "../../command/stop"; import { up } from "../../command/up"; type Command = { meta?: { name?: string; description?: string; hidden?: boolean }; args?: Record>; subCommands?: Record; run?: unknown; }; describe("CLI command definitions", () => { const commands = [ ["kuber", "Deploy and manage projects on Kubernetes", main], ["up", "Create and start deployments", up], ["login", "Log in to the cluster", login], ["logout", "Log out of kuber.astrxl.dev", logout], ["whoami", "Show the current kuber user", whoami], ["start", "Start deployments without rebuilding images", start], ["stop", "Stop all deployments", stop], ["restart", "Restart deployments", restart], ["rollback", "Roll deployments back to the previous release", rollback], ["maintenance", "Toggle maintenance page on hostnames", maintenance], ["s3", "View project object storage settings", s3], ["down", "Delete managed resources except ingress and PVCs", down], ["ps", "List deployments", ps], ["logs", "Show deployment logs", logs], ["exec", "Execute a command inside a deployment pod", exec], ["export", "Write rendered manifests to a YAML file", exportCommand], ["db", "View project databases and credentials", db], ] as const; test.each(commands)( "defines %s command metadata", (name, description, command) => { const definition = command as Command; expect(definition.meta).toMatchObject({ name, description }); if (name !== "kuber" && name !== "db" && name !== "s3") expect(typeof definition.run).toBe("function"); if (name === "kuber") expect(definition.run).toBeUndefined(); }, ); test("defines the rollback command alias", () => { expect((rollback as Command).meta).toMatchObject({ alias: "fuck" }); }); test("defines build, cleanup, listing, logging, and export flags", () => { expect((up as Command).args?.build).toMatchObject({ type: "boolean", alias: "b", default: true, }); expect((down as Command).args?.full).toMatchObject({ type: "boolean", alias: "f", }); expect((ps as Command).args?.all).toMatchObject({ type: "boolean", alias: "a", }); expect((logs as Command).args?.follow).toMatchObject({ type: "boolean", alias: "f", }); expect((exportCommand as Command).args?.output).toMatchObject({ type: "string", alias: "o", }); expect((main as Command).args?.config).toMatchObject({ type: "string", }); expect((login as Command).args?.session).toMatchObject({ type: "boolean", }); }); test("defines both database inspection subcommands", () => { const subCommands = (db as Command).subCommands; expect(Object.keys(subCommands ?? {}).sort()).toEqual(["creds", "ls"]); expect(subCommands?.ls?.meta?.name).toBe("ls"); expect(subCommands?.creds?.meta?.name).toBe("creds"); expect(typeof subCommands?.ls?.run).toBe("function"); expect(typeof subCommands?.creds?.run).toBe("function"); }); test("defines S3 inspection subcommands", () => { const subCommands = (s3 as Command).subCommands; expect(Object.keys(subCommands ?? {}).sort()).toEqual([ "creds", "ls", "ui", ]); expect(subCommands?.ls?.meta?.name).toBe("ls"); expect(subCommands?.creds?.meta?.name).toBe("creds"); expect(subCommands?.ui?.meta?.name).toBe("ui"); expect(typeof subCommands?.ls?.run).toBe("function"); expect(typeof subCommands?.creds?.run).toBe("function"); expect(typeof subCommands?.ui?.run).toBe("function"); }); test("registers shell completion on the root command", async () => { await initializeCompletion(); expect((await Promise.resolve(main.meta))?.name).toBe("kuber"); expect( Object.keys((await Promise.resolve(main.subCommands)) ?? {}), ).toContain("complete"); }); test("hides internal commands only from root help", async () => { const usage = await renderUsage(main); for (const name of [ "ci", "whoami", "logout", "operations", "maintenance", "audit", "users", ]) { expect(usage).not.toContain(name); expect(usage).not.toContain(`${name}|`); } for (const name of ["add", "login", "up"]) expect(usage).toContain(name); }); test("does not mutate exported command metadata when loading hidden commands", async () => { await renderUsage(main); const { ci } = await import("../../command/ci"); const { whoami, logout } = await import("../../command/auth"); const { operations } = await import("../../command/operations"); const { maintenance } = await import("../../command/maintenance"); const { audit } = await import("../../command/audit"); const { users } = await import("../../command/users"); for (const command of [ ci, whoami, logout, operations, maintenance, audit, users, ]) expect( (command as Command & { meta?: { hidden?: boolean } }).meta?.hidden, ).toBeUndefined(); }); });