mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 03:49:31 +00:00
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:
parent
b3f221f5bd
commit
ba7a3fa5c4
3 changed files with 70 additions and 38 deletions
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue