Skip to content

Commit 8becf86

Browse files
avalleteclaude
andcommitted
test(cli): deepen live JSON assertions for orgs/projects list
The `--output-format json` live tests only asserted `JSON.parse` succeeded, which proves "command exited and emitted JSON" but not platform correctness. Assert real shape + state instead: - orgs list: `organizations` is a non-empty array of `{ id, slug, name }` (the live token always belongs to at least one org). - projects list: `projects` is an array, and when the runner provisioned a project (SUPABASE_LIVE_PROJECT_REF set) that ref appears in the listing — proving the JSON reflects real platform state. Validated against a real supabox stack: 8 passed (the project-ref containment assertion exercised with a provisioned project). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 2e84e5e commit 8becf86

2 files changed

Lines changed: 37 additions & 19 deletions

File tree

apps/cli/src/legacy/commands/orgs/list/list.live.test.ts

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,26 @@ describeLive("supabase orgs list (live)", () => {
2222
},
2323
);
2424

25-
test(
26-
"emits machine-readable JSON with --output-format json",
27-
{ timeout: LIVE_TIMEOUT_MS },
28-
async () => {
29-
const { exitCode, stdout } = await runSupabaseLive([
30-
"orgs",
31-
"list",
32-
"--output-format",
33-
"json",
34-
]);
35-
expect(exitCode).toBe(0);
36-
// stdout must be payload-only valid JSON in json mode (no spinner/log noise).
37-
expect(() => JSON.parse(stdout)).not.toThrow();
38-
},
39-
);
25+
test("emits organizations as machine-readable JSON", { timeout: LIVE_TIMEOUT_MS }, async () => {
26+
const { exitCode, stdout } = await runSupabaseLive(["orgs", "list", "--output-format", "json"]);
27+
expect(exitCode).toBe(0);
28+
// Payload-only JSON (no spinner/log noise) shaped like the Go CLI's
29+
// { organizations: [{ id, slug, name }], message }. The live token always
30+
// belongs to at least one org (supabox seeds one), so assert a real row —
31+
// not merely that the output parses.
32+
const parsed = JSON.parse(stdout) as {
33+
organizations: Array<{ id: string; slug: string; name: string }>;
34+
};
35+
expect(Array.isArray(parsed.organizations)).toBe(true);
36+
expect(parsed.organizations.length).toBeGreaterThan(0);
37+
expect(parsed.organizations[0]).toEqual(
38+
expect.objectContaining({
39+
id: expect.any(String),
40+
slug: expect.any(String),
41+
name: expect.any(String),
42+
}),
43+
);
44+
});
4045

4146
// Negative path: a bad token must round-trip to the real Management API, come
4247
// back 401, and surface as a non-zero exit with the upstream "Unauthorized"

apps/cli/src/legacy/commands/projects/list/list.live.test.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { expect, test } from "vitest";
22

3-
import { describeLive, runSupabaseLive } from "../../../../../tests/helpers/live.ts";
3+
import {
4+
describeLive,
5+
liveProjectRef,
6+
runSupabaseLive,
7+
} from "../../../../../tests/helpers/live.ts";
48

59
const LIVE_TIMEOUT_MS = 60_000;
610

@@ -16,7 +20,7 @@ describeLive("supabase projects list (live)", () => {
1620
});
1721

1822
test(
19-
"emits machine-readable JSON with --output-format json",
23+
"emits projects as machine-readable JSON, including the provisioned project",
2024
{ timeout: LIVE_TIMEOUT_MS },
2125
async () => {
2226
const { exitCode, stdout } = await runSupabaseLive([
@@ -26,8 +30,17 @@ describeLive("supabase projects list (live)", () => {
2630
"json",
2731
]);
2832
expect(exitCode).toBe(0);
29-
// stdout must be payload-only valid JSON in json mode (no spinner/log noise).
30-
expect(() => JSON.parse(stdout)).not.toThrow();
33+
// Payload-only JSON shaped like { projects: [{ id, ref, name, status, … }], message }.
34+
const parsed = JSON.parse(stdout) as {
35+
projects: Array<{ id: string; ref: string; name: string }>;
36+
};
37+
expect(Array.isArray(parsed.projects)).toBe(true);
38+
const ref = liveProjectRef();
39+
if (ref) {
40+
// When the runner provisioned a project, it must appear in the listing —
41+
// proves the JSON reflects real platform state, not just valid syntax.
42+
expect(parsed.projects.map((project) => project.ref)).toContain(ref);
43+
}
3144
},
3245
);
3346
});

0 commit comments

Comments
 (0)