diff --git a/packages/cli/src/__tests__/cmd-listing-output.test.ts b/packages/cli/src/__tests__/cmd-listing-output.test.ts index 4c4906e5..b1591104 100644 --- a/packages/cli/src/__tests__/cmd-listing-output.test.ts +++ b/packages/cli/src/__tests__/cmd-listing-output.test.ts @@ -132,7 +132,7 @@ const multiTypeManifest: Manifest = { const { spinnerStart: mockSpinnerStart, spinnerStop: mockSpinnerStop } = mockClackPrompts(); -const { cmdMatrix, cmdAgents, cmdClouds, getTerminalWidth } = await import("../commands.js"); +const { cmdMatrix, cmdAgents, cmdClouds } = await import("../commands.js"); // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/packages/cli/src/__tests__/cmdlast.test.ts b/packages/cli/src/__tests__/cmdlast.test.ts index f088d70a..7ee7b7f2 100644 --- a/packages/cli/src/__tests__/cmdlast.test.ts +++ b/packages/cli/src/__tests__/cmdlast.test.ts @@ -39,7 +39,6 @@ describe("cmdLast", () => { let consoleMocks: ReturnType; let originalFetch: typeof global.fetch; let processExitSpy: ReturnType; - let cmdRunMock: ReturnType; function writeHistory(records: SpawnRecord[]) { writeFileSync(join(testDir, "history.json"), JSON.stringify(records)); @@ -53,10 +52,6 @@ describe("cmdLast", () => { return mockLogStep.mock.calls.map((c: any[]) => c.join(" ")).join("\n"); } - function consoleOutput(): string { - return consoleMocks.log.mock.calls.map((c: any[]) => c.join(" ")).join("\n"); - } - beforeEach(async () => { testDir = join(homedir(), `spawn-cmdlast-test-${Date.now()}-${Math.random()}`); mkdirSync(testDir, { @@ -77,9 +72,6 @@ describe("cmdLast", () => { originalFetch = global.fetch; - // Mock cmdRun to avoid actually spawning a process - cmdRunMock = mock(() => Promise.resolve()); - // Prime the manifest cache with mock data global.fetch = mock(() => Promise.resolve(new Response(JSON.stringify(mockManifest)))); await loadManifest(true); diff --git a/packages/cli/src/__tests__/cmdlist-integration.test.ts b/packages/cli/src/__tests__/cmdlist-integration.test.ts index 934c072e..dc3e0512 100644 --- a/packages/cli/src/__tests__/cmdlist-integration.test.ts +++ b/packages/cli/src/__tests__/cmdlist-integration.test.ts @@ -37,7 +37,7 @@ const { } = mockClackPrompts(); // Import after mock setup -const { cmdList, resolveDisplayName } = await import("../commands.js"); +const { cmdList } = await import("../commands.js"); const { loadManifest, _resetCacheForTesting } = await import("../manifest.js"); // ── Test Setup ────────────────────────────────────────────────────────────────── @@ -61,10 +61,6 @@ describe("cmdList integration", () => { return mockLogInfo.mock.calls.map((c: any[]) => c.join(" ")).join("\n"); } - function consoleErrorOutput(): string { - return consoleMocks.error.mock.calls.map((c: any[]) => c.join(" ")).join("\n"); - } - beforeEach(async () => { testDir = join(homedir(), `spawn-cmdlist-test-${Date.now()}-${Math.random()}`); mkdirSync(testDir, { diff --git a/packages/cli/src/__tests__/commands-update-download.test.ts b/packages/cli/src/__tests__/commands-update-download.test.ts index d30a5a39..5b1d4ba5 100644 --- a/packages/cli/src/__tests__/commands-update-download.test.ts +++ b/packages/cli/src/__tests__/commands-update-download.test.ts @@ -372,7 +372,6 @@ describe("Script download and execution", () => { }); it("should show network error message when primary 500 and fallback 502", async () => { - const callIndex = 0; global.fetch = mock(async (url: string) => { if (isString(url) && url.includes("manifest.json")) { return new Response(JSON.stringify(mockManifest)); diff --git a/packages/cli/src/__tests__/download-and-failure.test.ts b/packages/cli/src/__tests__/download-and-failure.test.ts index 7a761291..638e6e93 100644 --- a/packages/cli/src/__tests__/download-and-failure.test.ts +++ b/packages/cli/src/__tests__/download-and-failure.test.ts @@ -42,7 +42,7 @@ describe("Download and Failure Pipeline", () => { /** Set up fetch to return manifest from manifest URLs and custom responses for script URLs */ function setupFetch(scriptHandler: (url: string) => Promise) { - global.fetch = mock(async (url: string | URL | Request, init?: RequestInit) => { + global.fetch = mock(async (url: string | URL | Request) => { const urlStr = isString(url) ? url : url instanceof URL ? url.toString() : url.url; if (urlStr.includes("manifest.json")) { return new Response(JSON.stringify(mockManifest)); @@ -280,9 +280,7 @@ describe("Download and Failure Pipeline", () => { }); it("should show mixed error for primary 404 and fallback 500", async () => { - let callCount = 0; await setupFetch(async (url) => { - callCount++; if (url.includes("openrouter.ai")) { return new Response("Not Found", { status: 404, diff --git a/packages/cli/src/__tests__/manifest-integrity.test.ts b/packages/cli/src/__tests__/manifest-integrity.test.ts index d0efb443..912a3a01 100644 --- a/packages/cli/src/__tests__/manifest-integrity.test.ts +++ b/packages/cli/src/__tests__/manifest-integrity.test.ts @@ -96,7 +96,7 @@ describe("Manifest Integrity", () => { "implemented", "missing", ]; - for (const [key, status] of matrixEntries) { + for (const [, status] of matrixEntries) { expect(validStatuses).toContain(status); } }); diff --git a/packages/cli/src/__tests__/manifest-type-contracts.test.ts b/packages/cli/src/__tests__/manifest-type-contracts.test.ts index a4636a31..deb07818 100644 --- a/packages/cli/src/__tests__/manifest-type-contracts.test.ts +++ b/packages/cli/src/__tests__/manifest-type-contracts.test.ts @@ -68,7 +68,7 @@ describe("Agent required field types", () => { }); it("env values should all be strings", () => { - for (const [envKey, envVal] of Object.entries(agent.env)) { + for (const [, envVal] of Object.entries(agent.env)) { expect(typeof envVal).toBe("string"); } }); @@ -219,7 +219,7 @@ describe("Cloud optional field types (when present)", () => { describe("Cloud type values", () => { const validTypes = new Set(); - for (const [key, cloud] of allClouds) { + for (const [, cloud] of allClouds) { validTypes.add(cloud.type); } @@ -241,11 +241,12 @@ describe("Cloud type values", () => { describe("Env var interpolation patterns", () => { it("env values with ${...} should reference valid-looking env var names", () => { - const varRefPattern = /\$\{([^}]+)\}/g; - for (const [key, agent] of allAgents) { - for (const [envKey, envVal] of Object.entries(agent.env)) { - let match; - while ((match = varRefPattern.exec(envVal)) !== null) { + for (const [, agent] of allAgents) { + for (const [, envVal] of Object.entries(agent.env)) { + const matches = [ + ...envVal.matchAll(/\$\{([^}]+)\}/g), + ]; + for (const match of matches) { const refName = match[1]; // Referenced env var names should look like valid env vars expect(refName).toMatch(/^[A-Z][A-Z0-9_]*$/); @@ -255,8 +256,8 @@ describe("Env var interpolation patterns", () => { }); it("env values should not contain unmatched ${", () => { - for (const [key, agent] of allAgents) { - for (const [envKey, envVal] of Object.entries(agent.env)) { + for (const [, agent] of allAgents) { + for (const [, envVal] of Object.entries(agent.env)) { // Count ${ and } occurrences const opens = (envVal.match(/\$\{/g) || []).length; const closes = (envVal.match(/\}/g) || []).length; @@ -271,7 +272,7 @@ describe("Env var interpolation patterns", () => { describe("Agent launch command consistency", () => { it("launch commands should not contain dangerous shell metacharacters", () => { - for (const [key, agent] of allAgents) { + for (const [, agent] of allAgents) { // Launch commands shouldn't have pipe-to-bash or command substitution expect(agent.launch).not.toMatch(/\|\s*bash/); expect(agent.launch).not.toMatch(/\|\s*sh/); @@ -281,7 +282,7 @@ describe("Agent launch command consistency", () => { }); it("install commands should be strings (can contain pipe for curl|bash)", () => { - for (const [key, agent] of allAgents) { + for (const [, agent] of allAgents) { expect(typeof agent.install).toBe("string"); expect(agent.install.trim().length).toBeGreaterThan(0); } @@ -292,11 +293,11 @@ describe("Agent launch command consistency", () => { describe("Interactive prompts structure", () => { it("all interactive_prompts entries should have non-empty prompt text and string defaults", () => { - for (const [key, agent] of allAgents) { + for (const [, agent] of allAgents) { if (agent.interactive_prompts === undefined) { continue; } - for (const [promptKey, entry] of Object.entries(agent.interactive_prompts)) { + for (const [, entry] of Object.entries(agent.interactive_prompts)) { expect(entry.prompt.trim().length).toBeGreaterThan(0); expect(entry.default).toBeDefined(); expect(typeof entry.default).toBe("string"); @@ -386,7 +387,7 @@ describe("Agent metadata field types", () => { describe("Config files structure", () => { it("config file paths should look like file paths and values should be objects", () => { - for (const [key, agent] of allAgents) { + for (const [, agent] of allAgents) { if (agent.config_files === undefined) { continue; }