mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-22 03:14:57 +00:00
test: centralize @clack/prompts mock in test-helpers.ts (#2090)
* test: centralize @clack/prompts mock in test-helpers.ts Adds mockClackPrompts() factory to test-helpers.ts, eliminating ~15-line duplicate mock.module blocks from 19 test files. When @clack/prompts adds a new export, only one file needs updating instead of 19. Fixes #2080 Agent: test-engineer Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * style: fix Biome formatting after merge with main Agent: pr-maintainer Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> --------- Co-authored-by: B <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
65b872afa3
commit
aa7584096d
20 changed files with 225 additions and 528 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, mock } from "bun:test";
|
||||
import { describe, it, expect, beforeEach } from "bun:test";
|
||||
import { mockClackPrompts } from "./test-helpers";
|
||||
import type { Manifest } from "../manifest";
|
||||
|
||||
/**
|
||||
|
|
@ -14,32 +15,7 @@ import type { Manifest } from "../manifest";
|
|||
* 4. No match at all: just the listCmd hint (existing)
|
||||
*/
|
||||
|
||||
// ── Mock @clack/prompts ─────────────────────────────────────────────────────
|
||||
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mock(() => {}),
|
||||
stop: mock(() => {}),
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mock(() => {}),
|
||||
info: mockLogInfo,
|
||||
warn: mock(() => {}),
|
||||
error: mockLogError,
|
||||
success: mock(() => {}),
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const { logError: mockLogError, logInfo: mockLogInfo } = mockClackPrompts();
|
||||
|
||||
// Import after mocking
|
||||
const { checkEntity } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock } from "bun:test";
|
||||
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
|
||||
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
import { mockClackPrompts } from "./test-helpers";
|
||||
import type { SpawnRecord } from "../history.js";
|
||||
import { clearHistory, loadHistory, saveSpawnRecord, filterHistory, getHistoryPath } from "../history.js";
|
||||
|
||||
|
|
@ -282,31 +283,7 @@ describe("clearHistory", () => {
|
|||
|
||||
// ── cmdListClear via mock.module ─────────────────────────────────────────────
|
||||
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogSuccess = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mock(() => {}),
|
||||
stop: mock(() => {}),
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mock(() => {}),
|
||||
info: mockLogInfo,
|
||||
error: mock(() => {}),
|
||||
warn: mock(() => {}),
|
||||
success: mockLogSuccess,
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
confirm: mock(() => Promise.resolve(true)),
|
||||
}));
|
||||
const { logInfo: mockLogInfo, logSuccess: mockLogSuccess } = mockClackPrompts();
|
||||
|
||||
// Import after mock setup
|
||||
const { cmdListClear } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
import { isString } from "@openrouter/spawn-shared";
|
||||
|
||||
|
|
@ -24,36 +24,19 @@ let selectCallIndex = 0;
|
|||
let selectReturnValues: any[] = [];
|
||||
let isCancelValues: Set<any> = new Set();
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockLogWarn = mock(() => {});
|
||||
const mockIntro = mock(() => {});
|
||||
const mockOutro = mock(() => {});
|
||||
const mockCancel = mock(() => {});
|
||||
const mockConfirm = mock(async () => true);
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
const mockSpinnerMessage = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mockSpinnerMessage,
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
error: mockLogError,
|
||||
warn: mockLogWarn,
|
||||
},
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
logWarn: mockLogWarn,
|
||||
intro: mockIntro,
|
||||
outro: mockOutro,
|
||||
cancel: mockCancel,
|
||||
confirm: mockConfirm,
|
||||
text: mock(async () => undefined),
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
spinnerMessage: mockSpinnerMessage,
|
||||
} = mockClackPrompts({
|
||||
autocomplete: mock(async () => {
|
||||
const value = selectReturnValues[selectCallIndex] ?? "claude";
|
||||
selectCallIndex++;
|
||||
|
|
@ -64,8 +47,8 @@ mock.module("@clack/prompts", () => ({
|
|||
selectCallIndex++;
|
||||
return value;
|
||||
}),
|
||||
isCancel: (value: any) => isCancelValues.has(value),
|
||||
}));
|
||||
isCancel: (value: unknown) => isCancelValues.has(value),
|
||||
});
|
||||
|
||||
// Import commands after mock setup
|
||||
const { cmdInteractive } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import type { spyOn } from "bun:test";
|
|||
import { describe, it, expect, beforeEach, afterEach, mock } from "bun:test";
|
||||
import type { Manifest } from "../manifest";
|
||||
import { loadManifest } from "../manifest";
|
||||
import { createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
|
||||
/**
|
||||
* Tests for cmdMatrix, cmdAgents, and cmdClouds listing command output.
|
||||
|
|
@ -130,32 +130,7 @@ const multiTypeManifest: Manifest = {
|
|||
},
|
||||
};
|
||||
|
||||
// ── Mock @clack/prompts ─────────────────────────────────────────────────────
|
||||
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mock(() => {}),
|
||||
info: mock(() => {}),
|
||||
warn: mock(() => {}),
|
||||
error: mock(() => {}),
|
||||
success: mock(() => {}),
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const { spinnerStart: mockSpinnerStart, spinnerStop: mockSpinnerStop } = mockClackPrompts();
|
||||
|
||||
const { cmdMatrix, cmdAgents, cmdClouds, getTerminalWidth } = await import("../commands.js");
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:te
|
|||
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import type { SpawnRecord } from "../history";
|
||||
|
||||
/**
|
||||
|
|
@ -20,33 +20,12 @@ import type { SpawnRecord } from "../history";
|
|||
|
||||
const mockManifest = createMockManifest();
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
error: mock(() => {}),
|
||||
warn: mock(() => {}),
|
||||
success: mock(() => {}),
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
} = mockClackPrompts();
|
||||
|
||||
// Import after mock setup
|
||||
const { cmdLast, buildRecordLabel, buildRecordSubtitle } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:te
|
|||
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import type { SpawnRecord } from "../history";
|
||||
|
||||
/**
|
||||
|
|
@ -27,35 +27,14 @@ import type { SpawnRecord } from "../history";
|
|||
|
||||
const mockManifest = createMockManifest();
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockLogSuccess = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
error: mockLogError,
|
||||
warn: mock(() => {}),
|
||||
success: mockLogSuccess,
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
logSuccess: mockLogSuccess,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
} = mockClackPrompts();
|
||||
|
||||
// Import after mock setup
|
||||
const { cmdList, resolveDisplayName } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:te
|
|||
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
import { isString } from "@openrouter/spawn-shared";
|
||||
|
||||
|
|
@ -21,40 +21,20 @@ const mockManifest = createMockManifest();
|
|||
|
||||
// ── Clack mock refs ──────────────────────────────────────────────────────────
|
||||
|
||||
const mockLogWarn = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
const mockSpinnerMessage = mock(() => {});
|
||||
|
||||
// select returns "rerun" to exercise the "Spawn a new VM" path
|
||||
const mockSelect = mock(async () => "rerun");
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mockSpinnerMessage,
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
warn: mockLogWarn,
|
||||
error: mockLogError,
|
||||
success: mock(() => {}),
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
const {
|
||||
logWarn: mockLogWarn,
|
||||
logStep: mockLogStep,
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
spinnerMessage: mockSpinnerMessage,
|
||||
} = mockClackPrompts({
|
||||
select: mockSelect,
|
||||
autocomplete: mock(async () => "claude"),
|
||||
// First call: returns SPAWN_NAME value (set by --name).
|
||||
// Second call (after rerun clears SPAWN_NAME): returns undefined so no duplicate re-check.
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
});
|
||||
|
||||
const { cmdRun } = await import("../commands.js");
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:te
|
|||
import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
import { isString } from "@openrouter/spawn-shared";
|
||||
|
||||
|
|
@ -29,36 +29,14 @@ import { isString } from "@openrouter/spawn-shared";
|
|||
|
||||
const mockManifest = createMockManifest();
|
||||
|
||||
// ── Mock clack/prompts ───────────────────────────────────────────────────────
|
||||
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
const mockSpinnerMessage = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mockSpinnerMessage,
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
warn: mock(() => {}),
|
||||
error: mockLogError,
|
||||
success: mock(() => {}),
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
spinnerMessage: mockSpinnerMessage,
|
||||
} = mockClackPrompts();
|
||||
|
||||
const { cmdRun } = await import("../commands.js");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
|
||||
/**
|
||||
|
|
@ -48,34 +48,14 @@ const manifestWithCloudNotes = {
|
|||
},
|
||||
};
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockLogWarn = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
error: mockLogError,
|
||||
warn: mockLogWarn,
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
logWarn: mockLogWarn,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
} = mockClackPrompts();
|
||||
|
||||
// Import commands after mock setup
|
||||
const { cmdCloudInfo } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
|
||||
/**
|
||||
|
|
@ -77,35 +77,14 @@ const manyCloudManifest = {
|
|||
},
|
||||
};
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockLogWarn = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
error: mockLogError,
|
||||
warn: mockLogWarn,
|
||||
success: mock(() => {}),
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
logWarn: mockLogWarn,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
} = mockClackPrompts();
|
||||
|
||||
// Import commands after mock setup
|
||||
const { cmdAgentInfo, cmdHelp } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
import { isString } from "@openrouter/spawn-shared";
|
||||
|
||||
|
|
@ -18,34 +18,14 @@ import { isString } from "@openrouter/spawn-shared";
|
|||
|
||||
const mockManifest = createMockManifest();
|
||||
|
||||
// Mock @clack/prompts to prevent TTY output and capture error/info messages
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockLogWarn = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
error: mockLogError,
|
||||
warn: mockLogWarn,
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
logWarn: mockLogWarn,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
} = mockClackPrompts();
|
||||
|
||||
// Import commands after @clack/prompts mock is set up
|
||||
const { cmdRun, cmdAgentInfo } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
|
||||
/**
|
||||
|
|
@ -101,35 +101,14 @@ const manifestWithDistinctNames = {
|
|||
},
|
||||
};
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockLogWarn = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
error: mockLogError,
|
||||
warn: mockLogWarn,
|
||||
success: mock(() => {}),
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
logWarn: mockLogWarn,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
} = mockClackPrompts();
|
||||
|
||||
// Import commands after mock setup
|
||||
const { cmdRun, cmdAgentInfo, cmdCloudInfo, findClosestMatch } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
import { isString } from "@openrouter/spawn-shared";
|
||||
|
||||
|
|
@ -124,35 +124,14 @@ const noCloudManifest = {
|
|||
},
|
||||
};
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockLogWarn = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
error: mockLogError,
|
||||
warn: mockLogWarn,
|
||||
success: mock(() => {}),
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
logWarn: mockLogWarn,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
} = mockClackPrompts();
|
||||
|
||||
// Import commands after mock setup
|
||||
const { cmdRun } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
import { isString } from "@openrouter/spawn-shared";
|
||||
|
||||
|
|
@ -21,35 +21,14 @@ import { isString } from "@openrouter/spawn-shared";
|
|||
* - Edge case: resolution to a key that then fails validation
|
||||
*/
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockLogWarn = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
error: mockLogError,
|
||||
warn: mockLogWarn,
|
||||
success: mock(() => {}),
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
logWarn: mockLogWarn,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
} = mockClackPrompts();
|
||||
|
||||
// Import commands after mock setup
|
||||
const { cmdRun } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
import { isString } from "@openrouter/spawn-shared";
|
||||
import pkg from "../../package.json" with { type: "json" };
|
||||
|
|
@ -21,34 +21,14 @@ const VERSION = pkg.version;
|
|||
|
||||
const mockManifest = createMockManifest();
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
const mockSpinnerMessage = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mockSpinnerMessage,
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
warn: mock(() => {}),
|
||||
error: mockLogError,
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
spinnerMessage: mockSpinnerMessage,
|
||||
} = mockClackPrompts();
|
||||
|
||||
// Mock node:child_process to prevent real subprocess calls in tests:
|
||||
// - execSync: used by performUpdate() to run curl|bash install — without this mock,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks } from "./test-helpers";
|
||||
import { createMockManifest, createConsoleMocks, restoreMocks, mockClackPrompts } from "./test-helpers";
|
||||
import { loadManifest } from "../manifest";
|
||||
import { isString } from "@openrouter/spawn-shared";
|
||||
|
||||
|
|
@ -22,36 +22,15 @@ import { isString } from "@openrouter/spawn-shared";
|
|||
|
||||
const mockManifest = createMockManifest();
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLogError = mock(() => {});
|
||||
const mockLogInfo = mock(() => {});
|
||||
const mockLogStep = mock(() => {});
|
||||
const mockLogWarn = mock(() => {});
|
||||
const mockSpinnerStart = mock(() => {});
|
||||
const mockSpinnerStop = mock(() => {});
|
||||
const mockSpinnerMessage = mock(() => {});
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mockSpinnerStart,
|
||||
stop: mockSpinnerStop,
|
||||
message: mockSpinnerMessage,
|
||||
}),
|
||||
log: {
|
||||
step: mockLogStep,
|
||||
info: mockLogInfo,
|
||||
error: mockLogError,
|
||||
warn: mockLogWarn,
|
||||
success: mock(() => {}),
|
||||
},
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
const {
|
||||
logError: mockLogError,
|
||||
logInfo: mockLogInfo,
|
||||
logStep: mockLogStep,
|
||||
logWarn: mockLogWarn,
|
||||
spinnerStart: mockSpinnerStart,
|
||||
spinnerStop: mockSpinnerStop,
|
||||
spinnerMessage: mockSpinnerMessage,
|
||||
} = mockClackPrompts();
|
||||
|
||||
// Import after mock setup
|
||||
const { cmdRun } = await import("../commands.js");
|
||||
|
|
|
|||
|
|
@ -1,30 +1,17 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock } from "bun:test";
|
||||
import { mockClackPrompts } from "./test-helpers";
|
||||
import { preflightCredentialCheck } from "../commands";
|
||||
import type { Manifest } from "../manifest";
|
||||
|
||||
// Mock @clack/prompts
|
||||
const mockLog = {
|
||||
warn: mock(() => {}),
|
||||
info: mock(() => {}),
|
||||
};
|
||||
const mockConfirm = mock(() => Promise.resolve(true));
|
||||
const mockIsCancel = mock(() => false);
|
||||
mock.module("@clack/prompts", () => ({
|
||||
log: mockLog,
|
||||
confirm: mockConfirm,
|
||||
const clackMocks = mockClackPrompts({
|
||||
isCancel: mockIsCancel,
|
||||
// Stubs for other imports commands.ts might use
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
select: mock(() => Promise.resolve("")),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
spinner: mock(() => ({
|
||||
start: mock(() => {}),
|
||||
stop: mock(() => {}),
|
||||
message: mock(() => {}),
|
||||
})),
|
||||
}));
|
||||
});
|
||||
const mockLog = {
|
||||
warn: clackMocks.logWarn,
|
||||
info: clackMocks.logInfo,
|
||||
};
|
||||
const mockConfirm = clackMocks.confirm;
|
||||
|
||||
function makeManifest(cloudAuth: string): Manifest {
|
||||
const m: Manifest = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { mockClackPrompts } from "./test-helpers";
|
||||
import type { Manifest } from "../manifest";
|
||||
|
||||
/**
|
||||
|
|
@ -123,30 +124,9 @@ const mockExit = spyOn(process, "exit").mockImplementation(() => {
|
|||
throw new Error("process.exit called");
|
||||
});
|
||||
|
||||
const mockLog = {
|
||||
step: mock(() => {}),
|
||||
info: mock(() => {}),
|
||||
error: mock(() => {}),
|
||||
warn: mock(() => {}),
|
||||
success: mock(() => {}),
|
||||
};
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mock(() => {}),
|
||||
stop: mock(() => {}),
|
||||
message: mock(() => {}),
|
||||
}),
|
||||
log: mockLog,
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
mockClackPrompts({
|
||||
select: mock(() => Promise.resolve("hetzner")),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
confirm: mock(() => Promise.resolve(true)),
|
||||
isCancel: () => false,
|
||||
}));
|
||||
});
|
||||
|
||||
// Import after mocks are set up
|
||||
const {
|
||||
|
|
|
|||
|
|
@ -8,26 +8,12 @@
|
|||
import { describe, it, expect, beforeEach, afterEach, mock } from "bun:test";
|
||||
import { mkdirSync, writeFileSync, rmSync, existsSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { mockClackPrompts } from "./test-helpers";
|
||||
|
||||
// ── Mock @clack/prompts ─────────────────────────────────────────────────────
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
multiselect: mock(() => Promise.resolve([])),
|
||||
isCancel: () => false,
|
||||
log: {
|
||||
info: mock(() => {}),
|
||||
warn: mock(() => {}),
|
||||
error: mock(() => {}),
|
||||
step: mock(() => {}),
|
||||
message: mock(() => {}),
|
||||
},
|
||||
spinner: () => ({
|
||||
start: mock(() => {}),
|
||||
stop: mock(() => {}),
|
||||
}),
|
||||
mockClackPrompts({
|
||||
select: mock(() => Promise.resolve("")),
|
||||
text: mock(() => Promise.resolve("")),
|
||||
}));
|
||||
});
|
||||
|
||||
// ── Import after @clack/prompts mock ────────────────────────────────────────
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,88 @@ export function restoreMocks(
|
|||
});
|
||||
}
|
||||
|
||||
// ── @clack/prompts Mock ──────────────────────────────────────────────────────
|
||||
|
||||
export interface ClackPromptsMock {
|
||||
logStep: ReturnType<typeof mock>;
|
||||
logInfo: ReturnType<typeof mock>;
|
||||
logError: ReturnType<typeof mock>;
|
||||
logWarn: ReturnType<typeof mock>;
|
||||
logSuccess: ReturnType<typeof mock>;
|
||||
logMessage: ReturnType<typeof mock>;
|
||||
spinnerStart: ReturnType<typeof mock>;
|
||||
spinnerStop: ReturnType<typeof mock>;
|
||||
spinnerMessage: ReturnType<typeof mock>;
|
||||
intro: ReturnType<typeof mock>;
|
||||
outro: ReturnType<typeof mock>;
|
||||
cancel: ReturnType<typeof mock>;
|
||||
select: ReturnType<typeof mock>;
|
||||
autocomplete: ReturnType<typeof mock>;
|
||||
text: ReturnType<typeof mock>;
|
||||
confirm: ReturnType<typeof mock>;
|
||||
multiselect: ReturnType<typeof mock>;
|
||||
isCancel: (...args: unknown[]) => boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a centralized @clack/prompts mock and registers it via mock.module().
|
||||
*
|
||||
* Returns an object of individual mock refs that tests can use for assertions.
|
||||
* Pass `overrides` to customize specific functions (e.g., custom `select` behavior).
|
||||
*
|
||||
* MUST be called at module top level (before dynamic imports of modules that use @clack/prompts).
|
||||
*/
|
||||
export function mockClackPrompts(overrides?: Partial<ClackPromptsMock>): ClackPromptsMock {
|
||||
const mocks: ClackPromptsMock = {
|
||||
logStep: mock(() => {}),
|
||||
logInfo: mock(() => {}),
|
||||
logError: mock(() => {}),
|
||||
logWarn: mock(() => {}),
|
||||
logSuccess: mock(() => {}),
|
||||
logMessage: mock(() => {}),
|
||||
spinnerStart: mock(() => {}),
|
||||
spinnerStop: mock(() => {}),
|
||||
spinnerMessage: mock(() => {}),
|
||||
intro: mock(() => {}),
|
||||
outro: mock(() => {}),
|
||||
cancel: mock(() => {}),
|
||||
select: mock(() => {}),
|
||||
autocomplete: mock(async () => "claude"),
|
||||
text: mock(async () => undefined),
|
||||
confirm: mock(async () => true),
|
||||
multiselect: mock(() => Promise.resolve([])),
|
||||
isCancel: () => false,
|
||||
...overrides,
|
||||
};
|
||||
|
||||
mock.module("@clack/prompts", () => ({
|
||||
spinner: () => ({
|
||||
start: mocks.spinnerStart,
|
||||
stop: mocks.spinnerStop,
|
||||
message: mocks.spinnerMessage,
|
||||
}),
|
||||
log: {
|
||||
step: mocks.logStep,
|
||||
info: mocks.logInfo,
|
||||
error: mocks.logError,
|
||||
warn: mocks.logWarn,
|
||||
success: mocks.logSuccess,
|
||||
message: mocks.logMessage,
|
||||
},
|
||||
intro: mocks.intro,
|
||||
outro: mocks.outro,
|
||||
cancel: mocks.cancel,
|
||||
select: mocks.select,
|
||||
autocomplete: mocks.autocomplete,
|
||||
text: mocks.text,
|
||||
confirm: mocks.confirm,
|
||||
multiselect: mocks.multiselect,
|
||||
isCancel: mocks.isCancel,
|
||||
}));
|
||||
|
||||
return mocks;
|
||||
}
|
||||
|
||||
// ── Fetch Mocks ────────────────────────────────────────────────────────────────
|
||||
|
||||
export function mockSuccessfulFetch(data: any) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue