import type { ChildProcess } from 'child_process'; import { EventEmitter } from 'events'; import { beforeEach, describe, expect, it, vi } from 'vitest'; vi.mock('@main/services/team/ClaudeBinaryResolver', () => ({ ClaudeBinaryResolver: { resolve: vi.fn() }, })); vi.mock('@main/utils/childProcess', () => ({ spawnCli: vi.fn(), })); import { TeamProvisioningService } from '@main/services/team/TeamProvisioningService'; import { ClaudeBinaryResolver } from '@main/services/team/ClaudeBinaryResolver'; import { spawnCli } from '@main/utils/childProcess'; function allowConsoleLogs() { vi.spyOn(console, 'error').mockImplementation(() => {}); vi.spyOn(console, 'warn').mockImplementation(() => {}); } function createFakeChild(exitCode: number): ChildProcess { const child = Object.assign(new EventEmitter(), { stdout: null, stderr: null, stdin: null, }) as unknown as ChildProcess; setImmediate(() => child.emit('close', exitCode)); return child; } describe('TeamProvisioningService', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('warmup', () => { it('does not throw when spawnCli rejects', async () => { allowConsoleLogs(); vi.mocked(ClaudeBinaryResolver.resolve).mockResolvedValue('C:\\path\\claude'); let callCount = 0; vi.mocked(spawnCli).mockImplementation(() => { callCount++; if (callCount === 1) { throw new Error('spawn EINVAL'); } return createFakeChild(0); }); const svc = new TeamProvisioningService(); await expect(svc.warmup()).resolves.not.toThrow(); expect(spawnCli).toHaveBeenCalled(); }); }); });