Files
clawX/tests/unit/agents-routes.test.ts
Haze 50e88f6789 Add chat model picker (#924)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Haze <hazeone@users.noreply.github.com>
2026-05-07 15:29:08 +08:00

142 lines
4.4 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
const originalPlatform = process.platform;
const { mockExec } = vi.hoisted(() => ({
mockExec: vi.fn(),
}));
vi.mock('child_process', () => ({
exec: mockExec,
default: {
exec: mockExec,
},
}));
vi.mock('@electron/utils/agent-config', () => ({
assignChannelToAgent: vi.fn(),
clearChannelBinding: vi.fn(),
createAgent: vi.fn(),
deleteAgentConfig: vi.fn(),
listAgentsSnapshot: vi.fn(),
removeAgentWorkspaceDirectory: vi.fn(),
resolveAccountIdForAgent: vi.fn(),
updateAgentModel: vi.fn(),
updateAgentName: vi.fn(),
}));
vi.mock('@electron/utils/channel-config', () => ({
deleteChannelAccountConfig: vi.fn(),
}));
vi.mock('@electron/services/providers/provider-runtime-sync', () => ({
syncAllProviderAuthToRuntime: vi.fn(),
syncAgentModelOverrideToRuntime: vi.fn(),
}));
vi.mock('@electron/api/route-utils', () => ({
parseJsonBody: vi.fn(),
sendJson: vi.fn(),
}));
function setPlatform(platform: string): void {
Object.defineProperty(process, 'platform', { value: platform, writable: true });
}
describe('restartGatewayForAgentDeletion', () => {
beforeEach(() => {
vi.resetAllMocks();
vi.resetModules();
mockExec.mockImplementation((_cmd: string, _opts: object, cb: (err: Error | null, stdout: string) => void) => {
cb(null, '');
return {} as never;
});
});
afterEach(() => {
Object.defineProperty(process, 'platform', { value: originalPlatform, writable: true });
});
it('uses taskkill tree strategy on Windows when gateway pid is known', async () => {
setPlatform('win32');
const { restartGatewayForAgentDeletion } = await import('@electron/api/routes/agents');
const restart = vi.fn().mockResolvedValue(undefined);
const getStatus = vi.fn(() => ({ pid: 4321, port: 18789 }));
await restartGatewayForAgentDeletion({
gatewayManager: {
getStatus,
restart,
},
} as never);
expect(mockExec).toHaveBeenCalledWith(
'taskkill /F /PID 4321 /T',
expect.any(Function),
);
expect(restart).toHaveBeenCalledTimes(1);
});
});
describe('handleAgentRoutes model updates', () => {
beforeEach(() => {
vi.resetAllMocks();
vi.resetModules();
});
afterEach(() => {
Object.defineProperty(process, 'platform', { value: originalPlatform, writable: true });
});
it.each(['linux', 'darwin', 'win32'])(
'updates model config without gateway reload or restart on %s',
async (platform) => {
setPlatform(platform);
const routeUtils = await import('@electron/api/route-utils');
const agentConfig = await import('@electron/utils/agent-config');
const runtimeSync = await import('@electron/services/providers/provider-runtime-sync');
const { handleAgentRoutes } = await import('@electron/api/routes/agents');
vi.mocked(routeUtils.parseJsonBody).mockResolvedValue({ modelRef: 'custom-alpha/model-alpha' });
vi.mocked(agentConfig.updateAgentModel).mockResolvedValue({
agents: [],
defaultAgentId: 'main',
defaultModelRef: 'custom-alpha/model-alpha',
configuredChannelTypes: [],
channelOwners: {},
channelAccountOwners: {},
});
vi.mocked(runtimeSync.syncAllProviderAuthToRuntime).mockResolvedValue(undefined);
vi.mocked(runtimeSync.syncAgentModelOverrideToRuntime).mockResolvedValue(undefined);
const gatewayManager = {
getStatus: vi.fn(() => ({ state: 'running', pid: 1234, port: 18789 })),
debouncedReload: vi.fn(),
debouncedRestart: vi.fn(),
restart: vi.fn(),
};
const handled = await handleAgentRoutes(
{ method: 'PUT' } as never,
{} as never,
new URL('http://127.0.0.1/api/agents/main/model'),
{ gatewayManager } as never,
);
expect(handled).toBe(true);
expect(agentConfig.updateAgentModel).toHaveBeenCalledWith('main', 'custom-alpha/model-alpha');
expect(runtimeSync.syncAllProviderAuthToRuntime).toHaveBeenCalledTimes(1);
expect(runtimeSync.syncAgentModelOverrideToRuntime).toHaveBeenCalledWith('main');
expect(gatewayManager.debouncedReload).not.toHaveBeenCalled();
expect(gatewayManager.debouncedRestart).not.toHaveBeenCalled();
expect(gatewayManager.restart).not.toHaveBeenCalled();
expect(routeUtils.sendJson).toHaveBeenCalledWith(
{},
200,
expect.objectContaining({ success: true }),
);
},
);
});