test: remove duplicate and theatrical tests (#2600)

- billing-guidance.test.ts: move stderrSpy.mockRestore() from each test
  body to afterEach so restores run even when a test throws
- junie-agent.test.ts: add missing afterEach to restore stderrSpy that
  was leaking across tests
- cloud-init.test.ts: consolidate repetitive needsNode/needsBun tests
  into data-driven loops (8 individual its -> 2 parameterized loops)

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
A 2026-03-13 17:55:34 -07:00 committed by GitHub
parent b3f221f5bd
commit ba7a3fa5c4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 70 additions and 38 deletions

View file

@ -1,6 +1,6 @@
import type { BillingGuidanceDeps } from "../shared/billing-guidance";
import { beforeEach, describe, expect, it, mock, spyOn } from "bun:test";
import { afterEach, beforeEach, describe, expect, it, mock, spyOn } from "bun:test";
import { handleBillingError, isBillingError, showNonBillingError } from "../shared/billing-guidance";
// ── Mock deps (injected via DI, not mock.module) ──────────────────────────
@ -101,20 +101,22 @@ describe("handleBillingError", () => {
mockPrompt.mockClear();
});
afterEach(() => {
stderrSpy.mockRestore();
});
it("opens billing URL and returns true when user presses Enter", async () => {
mockPrompt.mockImplementation(() => Promise.resolve(""));
const deps = createMockDeps();
const result = await handleBillingError("hetzner", deps);
expect(result).toBe(true);
expect(deps.openBrowser).toHaveBeenCalledWith("https://console.hetzner.cloud/");
stderrSpy.mockRestore();
});
it("returns false when prompt throws (Ctrl+C)", async () => {
mockPrompt.mockImplementation(() => Promise.reject(new Error("cancelled")));
const result = await handleBillingError("digitalocean", createMockDeps());
expect(result).toBe(false);
stderrSpy.mockRestore();
});
it("works for clouds without billing URL", async () => {
@ -123,7 +125,6 @@ describe("handleBillingError", () => {
const result = await handleBillingError("unknown", deps);
expect(result).toBe(true);
expect(deps.openBrowser).not.toHaveBeenCalled();
stderrSpy.mockRestore();
});
});
@ -134,6 +135,10 @@ describe("showNonBillingError", () => {
stderrSpy = spyOn(process.stderr, "write").mockImplementation(() => true);
});
afterEach(() => {
stderrSpy.mockRestore();
});
it("does not throw", () => {
const deps = createMockDeps();
expect(() => {
@ -145,6 +150,5 @@ describe("showNonBillingError", () => {
deps,
);
}).not.toThrow();
stderrSpy.mockRestore();
});
});

View file

@ -47,44 +47,68 @@ describe("getPackagesForTier", () => {
});
describe("needsNode", () => {
it("returns true for 'node' tier", () => {
expect(needsNode("node")).toBe(true);
});
it("returns true for 'full' tier", () => {
expect(needsNode("full")).toBe(true);
});
it("returns false for 'minimal' tier", () => {
expect(needsNode("minimal")).toBe(false);
});
it("returns false for 'bun' tier", () => {
expect(needsNode("bun")).toBe(false);
});
const cases: Array<
[
Parameters<typeof needsNode>[0],
boolean,
]
> = [
[
"node",
true,
],
[
"full",
true,
],
[
"minimal",
false,
],
[
"bun",
false,
],
];
for (const [tier, expected] of cases) {
it(`returns ${expected} for '${tier}' tier`, () => {
expect(needsNode(tier)).toBe(expected);
});
}
it("defaults to true (full tier)", () => {
expect(needsNode()).toBe(true);
});
});
describe("needsBun", () => {
it("returns true for 'bun' tier", () => {
expect(needsBun("bun")).toBe(true);
});
it("returns true for 'full' tier", () => {
expect(needsBun("full")).toBe(true);
});
it("returns false for 'minimal' tier", () => {
expect(needsBun("minimal")).toBe(false);
});
it("returns false for 'node' tier", () => {
expect(needsBun("node")).toBe(false);
});
const cases: Array<
[
Parameters<typeof needsBun>[0],
boolean,
]
> = [
[
"bun",
true,
],
[
"full",
true,
],
[
"minimal",
false,
],
[
"node",
false,
],
];
for (const [tier, expected] of cases) {
it(`returns ${expected} for '${tier}' tier`, () => {
expect(needsBun(tier)).toBe(expected);
});
}
it("defaults to true (full tier)", () => {
expect(needsBun()).toBe(true);
});

View file

@ -8,7 +8,7 @@
* - cloudInitTier is 'node' (npm-installed agent)
*/
import { beforeEach, describe, expect, it, mock, spyOn } from "bun:test";
import { afterEach, beforeEach, describe, expect, it, mock, spyOn } from "bun:test";
// ── Suppress stderr output from logStep/logError during tests ────────────────
@ -18,6 +18,10 @@ beforeEach(() => {
stderrSpy = spyOn(process.stderr, "write").mockImplementation(() => true);
});
afterEach(() => {
stderrSpy.mockRestore();
});
// ── Import module under test ──────────────────────────────────────────────────
// agent-setup.ts doesn't import oauth, so no mock needed.