From ad075f89205dd66eac7d13060fd736d910ea8fae Mon Sep 17 00:00:00 2001 From: 7ttp <117663341+7ttp@users.noreply.github.com> Date: Wed, 2 Sep 2026 19:29:13 +0530 Subject: [PATCH 1/2] test: pin config diff live noise suppression only --- .../commands/config/diff/diff.live.test.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/apps/cli/src/legacy/commands/config/diff/diff.live.test.ts b/apps/cli/src/legacy/commands/config/diff/diff.live.test.ts index 94737817ef..2887a5e8cf 100644 --- a/apps/cli/src/legacy/commands/config/diff/diff.live.test.ts +++ b/apps/cli/src/legacy/commands/config/diff/diff.live.test.ts @@ -1,5 +1,6 @@ import { expect } from "vitest"; +import { stripAnsi } from "../../../../../tests/helpers/ansi.ts"; import { requireLiveSuccess, test } from "../../../../../tests/helpers/live.ts"; // Golden path only: the one thing mocks cannot prove is the real @@ -11,15 +12,16 @@ test("diffs a freshly-initialized config against the project", async ({ cli, pro const result = await cli(["config", "diff", "--project-ref", project.ref]); expect(`${result.stdout}${result.stderr}`).not.toContain("Unauthorized"); expect(result.stderr).toContain(`Comparing against project ${project.ref} using base config`); - expect(result.stderr).toContain("Comparison scope:"); - // The GoTrue-keyed auth record — the one surface mocks cannot prove — must - // classify CLEANLY against a fresh config: the platform's reports of - // unconfigured state (session zeros canonicalized to "0s" via - // unconfiguredValue, platform-rendered mailer subjects via platformRendered, - // disabled notification toggles) are suppressed by the registry's declared - // baselines, not flagged as drift. Asserting only exit 0 here would let that noise through silently. - const authChangeLines = result.stdout.split("\n").filter((line) => line.startsWith("auth.")); - expect(authChangeLines, result.stdout).toEqual([]); + expect(result.stderr).toMatch(/^Comparison scope: [^(\n]*\bauth\b/mu); + // A fresh project legitimately drifts from the init template (confirmations, + // TOTP, site URL), but the registry's declared baselines must still suppress + // the platform's unconfigured-state noise: "0s" sessions, platform-rendered + // mailer subjects, disabled notification toggles. + const stdout = stripAnsi(result.stdout); + const authNoiseLines = stdout + .split("\n") + .filter((line) => /^auth\.(sessions|email\.(template|notification))\./u.test(line)); + expect(authNoiseLines, stdout).toEqual([]); // Read-only success regardless of drift (no --exit-code passed). requireLiveSuccess(result, "config diff"); }); From ffdaf2ce103742115a397dfe81feb4248f4523ad Mon Sep 17 00:00:00 2001 From: 7ttp <117663341+7ttp@users.noreply.github.com> Date: Wed, 2 Sep 2026 20:45:30 +0530 Subject: [PATCH 2/2] test: derive config diff live baselines from registry --- .../commands/config/diff/diff.live.test.ts | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/apps/cli/src/legacy/commands/config/diff/diff.live.test.ts b/apps/cli/src/legacy/commands/config/diff/diff.live.test.ts index 2887a5e8cf..3599778558 100644 --- a/apps/cli/src/legacy/commands/config/diff/diff.live.test.ts +++ b/apps/cli/src/legacy/commands/config/diff/diff.live.test.ts @@ -1,6 +1,6 @@ +import { type ConfigChangeClass, projectConfigMappingRows } from "@supabase/config/internal"; import { expect } from "vitest"; -import { stripAnsi } from "../../../../../tests/helpers/ansi.ts"; import { requireLiveSuccess, test } from "../../../../../tests/helpers/live.ts"; // Golden path only: the one thing mocks cannot prove is the real @@ -9,19 +9,36 @@ import { requireLiveSuccess, test } from "../../../../../tests/helpers/live.ts"; // in diff.integration.test.ts. The `workspace` fixture behind `cli` is a // fresh `supabase init` project directory. test("diffs a freshly-initialized config against the project", async ({ cli, project }) => { - const result = await cli(["config", "diff", "--project-ref", project.ref]); - expect(`${result.stdout}${result.stderr}`).not.toContain("Unauthorized"); - expect(result.stderr).toContain(`Comparing against project ${project.ref} using base config`); - expect(result.stderr).toMatch(/^Comparison scope: [^(\n]*\bauth\b/mu); - // A fresh project legitimately drifts from the init template (confirmations, - // TOTP, site URL), but the registry's declared baselines must still suppress - // the platform's unconfigured-state noise: "0s" sessions, platform-rendered - // mailer subjects, disabled notification toggles. - const stdout = stripAnsi(result.stdout); - const authNoiseLines = stdout - .split("\n") - .filter((line) => /^auth\.(sessions|email\.(template|notification))\./u.test(line)); - expect(authNoiseLines, stdout).toEqual([]); + const result = await cli([ + "config", + "diff", + "--project-ref", + project.ref, + "--output-format", + "json", + ]); // Read-only success regardless of drift (no --exit-code passed). requireLiveSuccess(result, "config diff"); + expect(result.stderr).toContain(`Comparing against project ${project.ref} using base config`); + const payload = JSON.parse(result.stdout) as { + scope: { present: string[] }; + changes: Array<{ path: string[]; class: ConfigChangeClass }>; + }; + expect(payload.scope.present).toContain("auth"); + const changes = payload.changes.map(({ path, class: kind }) => ({ path: path.join("."), kind })); + const classified = changes.map((change) => `${change.path} [${change.kind}]`).join("\n"); + // A fresh project legitimately drifts from the init template (confirmations, + // TOTP, site URL), so remote auth values must reach classification, while + // the registry's declared baselines suppress the platform's own defaults. + expect( + changes.some((change) => change.path.startsWith("auth.") && change.kind !== "local_only"), + classified, + ).toBe(true); + const baselines = projectConfigMappingRows + .filter((row) => row.unconfiguredValue !== undefined || row.platformRendered === true) + .map((row) => row.configPath.join(".")); + expect( + changes.filter((change) => baselines.includes(change.path)), + classified, + ).toEqual([]); });