diff --git a/src/commands/branch/create.test.ts b/src/commands/branch/create.test.ts index b4aff14..45fec7f 100644 --- a/src/commands/branch/create.test.ts +++ b/src/commands/branch/create.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { Command } from 'commander'; import { registerBranchCreateCommand } from './create.js'; @@ -70,18 +70,18 @@ describe('branch create', () => { it('rejects when no project linked', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue(null); + (getProjectConfig as Mock).mockReturnValue(null); const program = new Command().exitOverride(); program.option('--json').option('--api-url ').option('-y, --yes'); registerBranchCreateCommand(program); let exitCode: number | undefined; const origExit = process.exit; - (process.exit as any) = (code?: number) => { + process.exit = ((code?: number) => { exitCode = code; throw new Error('__exit__'); - }; + }) as typeof process.exit; const origStderr = process.stderr.write.bind(process.stderr); - process.stderr.write = (() => true) as any; + process.stderr.write = (() => true) as typeof process.stderr.write; try { await program .parseAsync(['create', 'feat-x', '--mode', 'schema-only', '--no-switch', '--json'], { @@ -97,7 +97,7 @@ describe('branch create', () => { it('rejects an invalid --mode value before any API call', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -107,12 +107,12 @@ describe('branch create', () => { registerBranchCreateCommand(program); let exitCode: number | undefined; const origExit = process.exit; - (process.exit as any) = (code?: number) => { + process.exit = ((code?: number) => { exitCode = code; throw new Error('__exit__'); - }; + }) as typeof process.exit; const origStderr = process.stderr.write.bind(process.stderr); - process.stderr.write = (() => true) as any; + process.stderr.write = (() => true) as typeof process.stderr.write; try { await program .parseAsync(['create', 'feat-x', '--mode', 'bogus', '--no-switch', '--json'], { @@ -130,7 +130,7 @@ describe('branch create', () => { it('happy path with --json: posts then prints branch payload', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -168,7 +168,7 @@ describe('branch create', () => { it('happy path without --no-switch invokes runBranchSwitch', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -205,7 +205,7 @@ describe('branch create', () => { it('switch failure after a successful create reports "switch failed", not "creation failed"', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -215,19 +215,19 @@ describe('branch create', () => { oss_host: 'https://p1ky.us-east.insforge.app', }); const { runBranchSwitch } = await import('./switch.js'); - (runBranchSwitch as any).mockRejectedValueOnce(new Error('network down')); + (runBranchSwitch as Mock).mockRejectedValueOnce(new Error('network down')); const program = new Command().exitOverride(); program.option('--json').option('--api-url ').option('-y, --yes'); registerBranchCreateCommand(program); let exitCode: number | undefined; const origExit = process.exit; - (process.exit as any) = (code?: number) => { + process.exit = ((code?: number) => { exitCode = code; throw new Error('__exit__'); - }; + }) as typeof process.exit; const origStderr = process.stderr.write.bind(process.stderr); - process.stderr.write = (() => true) as any; + process.stderr.write = (() => true) as typeof process.stderr.write; try { await program .parseAsync(['create', 'feat-x', '--mode', 'full'], { from: 'user' }) @@ -249,7 +249,7 @@ describe('branch create', () => { it('non-JSON path drives the spinner and keeps it active through switch', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', diff --git a/src/commands/branch/delete.test.ts b/src/commands/branch/delete.test.ts index a82ee94..7634a1c 100644 --- a/src/commands/branch/delete.test.ts +++ b/src/commands/branch/delete.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { Command } from 'commander'; import { registerBranchDeleteCommand } from './delete.js'; @@ -59,7 +59,7 @@ describe('branch delete', () => { it('happy path with --yes calls deleteBranchApi and captures analytics', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -75,7 +75,7 @@ describe('branch delete', () => { it('errors when the named branch does not exist', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -90,7 +90,7 @@ describe('branch delete', () => { it('auto-switches back to parent when deleting the currently active branch', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'b1', project_name: 'feat-x', org_id: 'o1', @@ -112,7 +112,7 @@ describe('branch delete', () => { it('does not auto-switch when the deleted branch is not the currently active one', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -125,14 +125,14 @@ describe('branch delete', () => { it('does not abort the delete command when post-delete switch-back fails', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'b1', project_name: 'feat-x', org_id: 'o1', branched_from: { project_id: 'p1', project_name: 'parent' }, }); const { runBranchSwitch } = await import('./switch.js'); - (runBranchSwitch as any).mockRejectedValueOnce(new Error('no parent backup')); + (runBranchSwitch as Mock).mockRejectedValueOnce(new Error('no parent backup')); const program = makeProgram(); await runSilently(program, ['delete', 'feat-x', '--yes', '--json']); // Delete still went through despite the switch-back failure. @@ -142,7 +142,7 @@ describe('branch delete', () => { it('json mode reports switched_back=true when the active branch was deleted', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'b1', project_name: 'feat-x', org_id: 'o1', diff --git a/src/commands/branch/list.test.ts b/src/commands/branch/list.test.ts index 7d47cca..5dd6ebd 100644 --- a/src/commands/branch/list.test.ts +++ b/src/commands/branch/list.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { Command } from 'commander'; import { registerBranchListCommand } from './list.js'; @@ -69,7 +69,7 @@ describe('branch list', () => { it('lists siblings against project_id when not on a branch', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -86,7 +86,7 @@ describe('branch list', () => { it('lists siblings against branched_from.project_id when currently switched onto a branch', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'b1', project_name: 'feat-x', org_id: 'o1', @@ -104,7 +104,7 @@ describe('branch list', () => { it('json mode emits a single JSON document with the branches array', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -119,7 +119,7 @@ describe('branch list', () => { it('table mode marks the current branch with `*`', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'b1', project_name: 'feat-x', org_id: 'o1', @@ -143,7 +143,7 @@ describe('branch list', () => { it('does not mark any branch when currently on the parent', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -159,13 +159,13 @@ describe('branch list', () => { it('prints "No branches." when the API returns an empty list', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', }); const { listBranchesApi } = await import('../../lib/api/platform.js'); - (listBranchesApi as any).mockResolvedValueOnce([]); + (listBranchesApi as Mock).mockResolvedValueOnce([]); const program = makeProgram(); const logs = await runWithCapturedLog(program, ['list']); expect(logs.join('\n')).toContain('No branches.'); diff --git a/src/commands/branch/merge.test.ts b/src/commands/branch/merge.test.ts index 63794b4..327c610 100644 --- a/src/commands/branch/merge.test.ts +++ b/src/commands/branch/merge.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { Command } from 'commander'; import { registerBranchMergeCommand } from './merge.js'; @@ -143,7 +143,7 @@ describe('branch merge', () => { it('conflict path exits with code 2 and prints per-conflict summary', async () => { const { mergeBranchDryRunApi } = await import('../../lib/api/platform.js'); - (mergeBranchDryRunApi as any).mockResolvedValueOnce({ + (mergeBranchDryRunApi as Mock).mockResolvedValueOnce({ summary: { added: 0, modified: 0, conflicts: 1 }, rendered_sql: '-- ⚠️ MERGE BLOCKED: 1 conflict(s) detected.', changes: [], @@ -167,14 +167,14 @@ describe('branch merge', () => { // overwrite the meaningful first exit. The first call is what the user sees. let exitCode: number | undefined; const origExit = process.exit; - (process.exit as any) = (code?: number) => { + process.exit = ((code?: number) => { if (exitCode === undefined) exitCode = code; throw new Error('__exit__'); - }; + }) as typeof process.exit; const origLog = console.log; console.log = () => {}; const origStderr = process.stderr.write.bind(process.stderr); - process.stderr.write = (() => true) as any; + process.stderr.write = (() => true) as typeof process.stderr.write; try { await program .parseAsync(['merge', 'feat-x', '--dry-run'], { from: 'user' }) diff --git a/src/commands/branch/switch.test.ts b/src/commands/branch/switch.test.ts index d99d62f..7a0cb4d 100644 --- a/src/commands/branch/switch.test.ts +++ b/src/commands/branch/switch.test.ts @@ -1,11 +1,12 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { runBranchSwitch } from './switch.js'; +import type { ProjectConfig } from '../../types.js'; -const saveCalls: any[] = []; +const saveCalls: ProjectConfig[] = []; vi.mock('../../lib/config.js', () => ({ getProjectConfig: vi.fn(), - saveProjectConfig: vi.fn((c: any) => saveCalls.push(c)), + saveProjectConfig: vi.fn((c: ProjectConfig) => saveCalls.push(c)), getProjectConfigFile: () => '/tmp/_test_/.insforge/project.json', getParentBackupFile: () => '/tmp/_test_/.insforge/project.parent.json', buildOssHost: (appkey: string, region: string) => `https://${appkey}.${region}.insforge.app`, @@ -59,7 +60,7 @@ describe('runBranchSwitch', () => { it('switches from parent to a branch and creates parent.json backup', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1', @@ -86,7 +87,7 @@ describe('runBranchSwitch', () => { it('preserves parent backup when switching branch -> branch', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'b0', project_name: 'feat-y', org_id: 'o1', @@ -107,9 +108,9 @@ describe('runBranchSwitch', () => { it('refuses to switch to a branch not in ready state', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1' }); + (getProjectConfig as Mock).mockReturnValue({ project_id: 'p1', project_name: 'parent', org_id: 'o1' }); const { listBranchesApi } = await import('../../lib/api/platform.js'); - (listBranchesApi as any).mockResolvedValueOnce([ + (listBranchesApi as Mock).mockResolvedValueOnce([ { id: 'b1', name: 'feat-x', @@ -129,7 +130,7 @@ describe('runBranchSwitch', () => { it('--parent restores from backup and removes the backup file', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'b1', project_name: 'feat-x', org_id: 'o1', @@ -148,7 +149,7 @@ describe('runBranchSwitch', () => { it('rejects passing both a branch name and --parent', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ + (getProjectConfig as Mock).mockReturnValue({ project_id: 'b1', project_name: 'feat-x', org_id: 'o1', @@ -161,7 +162,7 @@ describe('runBranchSwitch', () => { it('--parent fails clearly when no backup exists', async () => { const { getProjectConfig } = await import('../../lib/config.js'); - (getProjectConfig as any).mockReturnValue({ project_id: 'b1', project_name: 'feat-x', org_id: 'o1' }); + (getProjectConfig as Mock).mockReturnValue({ project_id: 'b1', project_name: 'feat-x', org_id: 'o1' }); fsMock.existsSync.mockReturnValueOnce(false); await expect( runBranchSwitch({ toParent: true, apiUrl: undefined, json: true }), diff --git a/src/commands/memory/memory.test.ts b/src/commands/memory/memory.test.ts index c9b19de..ec2755a 100644 --- a/src/commands/memory/memory.test.ts +++ b/src/commands/memory/memory.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { Command } from 'commander'; import { registerMemoryCommands } from './index.js'; @@ -49,13 +49,13 @@ describe('memory commands', () => { it('remember stores a single fact (not transcript) and honors --kind/--title', async () => { const { ossFetch } = await import('../../lib/api/oss.js'); - (ossFetch as any).mockResolvedValue(mockResponse({ results: [{ action: 'ADD', title: 'T' }] })); + (ossFetch as Mock).mockResolvedValue(mockResponse({ results: [{ action: 'ADD', title: 'T' }] })); await run(['memory', 'remember', 'some content', '--scope', 's', '--kind', 'decision', '--title', 'T']); - const [path, opts] = (ossFetch as any).mock.calls[0]; + const [path, opts] = (ossFetch as Mock).mock.calls[0]; expect(path).toBe('/api/memory/remember'); - const body = JSON.parse(opts.body); + const body = JSON.parse(opts?.body as string); expect(body).toMatchObject({ scope: 's', kind: 'decision', title: 'T', content: 'some content' }); expect(body.transcript).toBeUndefined(); @@ -65,32 +65,32 @@ describe('memory commands', () => { it('remember --transcript sends transcript mode', async () => { const { ossFetch } = await import('../../lib/api/oss.js'); - (ossFetch as any).mockResolvedValue(mockResponse({ results: [] })); + (ossFetch as Mock).mockResolvedValue(mockResponse({ results: [] })); await run(['memory', 'remember', 'a long transcript', '--transcript', '--scope', 's']); - const body = JSON.parse((ossFetch as any).mock.calls[0][1].body); + const body = JSON.parse((ossFetch as Mock).mock.calls[0][1]?.body as string); expect(body.transcript).toBe('a long transcript'); expect(body.content).toBeUndefined(); }); it('recall posts the query to the recall endpoint', async () => { const { ossFetch } = await import('../../lib/api/oss.js'); - (ossFetch as any).mockResolvedValue(mockResponse({ memories: [] })); + (ossFetch as Mock).mockResolvedValue(mockResponse({ memories: [] })); await run(['memory', 'recall', 'where is the secret', '--scope', 's', '--limit', '3']); - const [path, opts] = (ossFetch as any).mock.calls[0]; + const [path, opts] = (ossFetch as Mock).mock.calls[0]; expect(path).toBe('/api/memory/recall'); - expect(JSON.parse(opts.body)).toMatchObject({ scope: 's', query: 'where is the secret', limit: 3 }); + expect(JSON.parse(opts?.body as string)).toMatchObject({ scope: 's', query: 'where is the secret', limit: 3 }); }); it('list hits the index endpoint', async () => { const { ossFetch } = await import('../../lib/api/oss.js'); - (ossFetch as any).mockResolvedValue(mockResponse({ entries: [] })); + (ossFetch as Mock).mockResolvedValue(mockResponse({ entries: [] })); await run(['memory', 'list', '--scope', 's']); - expect((ossFetch as any).mock.calls[0][0]).toBe('/api/memory/index'); + expect((ossFetch as Mock).mock.calls[0][0]).toBe('/api/memory/index'); }); });