Ctrl K
ComunidadGuías…

test/cli-update.test.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Settings' agent CLI versions and Update (server/cli-update.js), with a fake
// registry and a fake execFile: no network, no real `<cli> update`.
import { describe, it, expect, beforeEach } from 'vitest';
import { cliUpdates, startCliUpdate, versionOf, resetCliUpdates } from '../server/cli-update.js';

const agents = [
  { cli: 'claude', version: '2.1.295 (Claude Code)', path: '/bin/claude' },
  { cli: 'codex', version: 'codex-cli 0.157.0', path: '/bin/codex' },
  { cli: 'gemini', version: '0.1.0', path: '/bin/gemini' },
];
const fetchLatest = async (pkg) => ({ '@anthropic-ai/claude-code': '2.1.300', '@openai/codex': '0.157.0' })[pkg];

beforeEach(() => resetCliUpdates());

describe('agent CLI updates', () => {
  it('reads each CLI version off its --version line', () => {
    expect(versionOf('2.1.295 (Claude Code)')).toBe('2.1.295');
    expect(versionOf('codex-cli 0.157.0')).toBe('0.157.0');
    expect(versionOf(null)).toBeNull();
  });

  it('pairs the installed claude and codex with npm\'s latest, and nothing else', async () => {
    expect(await cliUpdates(agents, { fetchLatest })).toEqual({
      claude: { version: '2.1.295', latest: '2.1.300' },
      codex: { version: '0.157.0', latest: '0.157.0' },
    });
    expect(await cliUpdates([], { fetchLatest })).toEqual({});
  });

  it('runs the CLI\'s own `update`, one at a time, and reports how it ended', async () => {
    let done;
    const calls = [];
    const execFile = (file, args, opts, cb) => { calls.push([file, args]); done = cb; return { stdin: { end() {} } }; };
    expect(startCliUpdate('codex', agents, { execFile })).toEqual({ ok: true });
    expect(calls).toEqual([['/bin/codex', ['update']]]);
    expect(startCliUpdate('codex', agents, { execFile }).error).toMatch(/already updating/);
    expect((await cliUpdates(agents, { fetchLatest })).codex.updating).toBe(true);
    done(null, 'Updated to 0.158.0\n', '');
    expect((await cliUpdates(agents, { fetchLatest })).codex.finished).toEqual({ code: 0, log: 'Updated to 0.158.0' });
    // A failure keeps its last lines for the panel.
    startCliUpdate('claude', agents, { execFile });
    done(Object.assign(new Error('exit 1'), { code: 1 }), '', 'EACCES: permission denied');
    expect((await cliUpdates(agents, { fetchLatest })).claude.finished).toEqual({ code: 1, log: 'EACCES: permission denied' });
  });

  it('refuses a CLI it does not update or that is not installed', () => {
    const execFile = () => { throw new Error('must not run'); };
    expect(startCliUpdate('gemini', agents, { execFile }).error).toMatch(/Unknown CLI/);
    expect(startCliUpdate('__proto__', agents, { execFile }).error).toMatch(/Unknown CLI/);
    expect(startCliUpdate('codex', [], { execFile }).error).toMatch(/not installed/);
  });
});