mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-15 22:21:20 +00:00
158 lines
5.0 KiB
TypeScript
158 lines
5.0 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, test } from 'bun:test';
|
|
import fs from 'fs';
|
|
import os from 'os';
|
|
import path from 'path';
|
|
|
|
import { getCompletionSuggestions } from '../../../src/commands/completion-backend';
|
|
|
|
const originalHome = process.env.HOME;
|
|
const originalUserProfile = process.env.USERPROFILE;
|
|
const originalCcsHome = process.env.CCS_HOME;
|
|
let tempHome = '';
|
|
|
|
function suggestionValues(
|
|
tokensBeforeCurrent: string[],
|
|
current = '',
|
|
shell: 'bash' | 'fish' | 'powershell' | 'zsh' = 'bash'
|
|
): string[] {
|
|
return getCompletionSuggestions({ tokensBeforeCurrent, current, shell }).map(
|
|
(entry) => entry.value
|
|
);
|
|
}
|
|
|
|
beforeEach(() => {
|
|
tempHome = fs.mkdtempSync(path.join(os.tmpdir(), 'ccs-completion-'));
|
|
fs.mkdirSync(path.join(tempHome, '.ccs'), { recursive: true });
|
|
fs.writeFileSync(
|
|
path.join(tempHome, '.ccs', 'config.json'),
|
|
JSON.stringify(
|
|
{
|
|
profiles: {
|
|
localglm: '~/.ccs/localglm.settings.json',
|
|
},
|
|
cliproxy: {
|
|
'my-codex': {
|
|
provider: 'codex',
|
|
settings: '~/.ccs/my-codex.settings.json',
|
|
},
|
|
},
|
|
},
|
|
null,
|
|
2
|
|
)
|
|
);
|
|
fs.writeFileSync(
|
|
path.join(tempHome, '.ccs', 'profiles.json'),
|
|
JSON.stringify(
|
|
{
|
|
profiles: {
|
|
work: { type: 'account', created: '2026-04-02T00:00:00.000Z' },
|
|
},
|
|
default: 'work',
|
|
},
|
|
null,
|
|
2
|
|
)
|
|
);
|
|
|
|
process.env.HOME = tempHome;
|
|
process.env.USERPROFILE = tempHome;
|
|
process.env.CCS_HOME = tempHome;
|
|
});
|
|
|
|
afterEach(() => {
|
|
if (originalHome === undefined) delete process.env.HOME;
|
|
else process.env.HOME = originalHome;
|
|
if (originalUserProfile === undefined) delete process.env.USERPROFILE;
|
|
else process.env.USERPROFILE = originalUserProfile;
|
|
if (originalCcsHome === undefined) delete process.env.CCS_HOME;
|
|
else process.env.CCS_HOME = originalCcsHome;
|
|
|
|
fs.rmSync(tempHome, { recursive: true, force: true });
|
|
});
|
|
|
|
describe('completion backend', () => {
|
|
test('includes current root commands and dynamic profiles at the top level', () => {
|
|
const values = suggestionValues([]);
|
|
|
|
expect(values).toContain('config');
|
|
expect(values).toContain('docker');
|
|
expect(values).toContain('tokens');
|
|
expect(values).toContain('migrate');
|
|
expect(values).toContain('cursor');
|
|
expect(values).toContain('copilot');
|
|
expect(values).toContain('gemini');
|
|
expect(values).toContain('gitlab');
|
|
expect(values).toContain('codebuddy');
|
|
expect(values).toContain('kilo');
|
|
expect(values).toContain('localglm');
|
|
expect(values).toContain('work');
|
|
expect(values).toContain('my-codex');
|
|
expect(values).not.toContain('__complete');
|
|
expect(values).not.toContain('--install');
|
|
expect(values).not.toContain('--uninstall');
|
|
});
|
|
|
|
test('suggests help topics from the help command', () => {
|
|
const values = suggestionValues(['help']);
|
|
expect(values).toContain('profiles');
|
|
expect(values).toContain('providers');
|
|
expect(values).toContain('completion');
|
|
expect(values).toContain('targets');
|
|
expect(values).not.toContain('api');
|
|
expect(values).not.toContain('__complete');
|
|
});
|
|
|
|
test('suggests lifecycle subcommands for api', () => {
|
|
const values = suggestionValues(['api']);
|
|
expect(values).toEqual(
|
|
expect.arrayContaining(['create', 'discover', 'copy', 'export', 'import', 'remove'])
|
|
);
|
|
});
|
|
|
|
test('suggests account profiles for auth show', () => {
|
|
const values = suggestionValues(['auth', 'show']);
|
|
expect(values).toContain('work');
|
|
expect(values).toContain('--json');
|
|
});
|
|
|
|
test('suggests default lane and account profiles for auth backup', () => {
|
|
const values = suggestionValues(['auth', 'backup']);
|
|
expect(values).toContain('default');
|
|
expect(values).toContain('work');
|
|
expect(values).toContain('--json');
|
|
});
|
|
|
|
test('suggests cliproxy variants for variant-scoped commands', () => {
|
|
const values = suggestionValues(['cliproxy', 'edit']);
|
|
expect(values).toContain('my-codex');
|
|
});
|
|
|
|
test('suggests env format values after the format flag', () => {
|
|
const values = suggestionValues(['env', '--format']);
|
|
expect(values).toEqual(
|
|
expect.arrayContaining(['openai', 'anthropic', 'raw', 'claude-extension'])
|
|
);
|
|
});
|
|
|
|
test('includes live doctor and cliproxy flags from the shared catalog', () => {
|
|
expect(suggestionValues(['doctor'])).toEqual(expect.arrayContaining(['--fix', '-f']));
|
|
expect(suggestionValues(['cliproxy'])).toEqual(expect.arrayContaining(['remove', '--backend']));
|
|
});
|
|
|
|
test('treats cursor as a provider shortcut in completion', () => {
|
|
const values = suggestionValues(['cursor']);
|
|
expect(values).toEqual(
|
|
expect.arrayContaining(['--auth', '--accounts', '--config', '--logout'])
|
|
);
|
|
expect(values).not.toContain('probe');
|
|
expect(values).not.toContain('start');
|
|
});
|
|
|
|
test('filters suggestions by the current token prefix', () => {
|
|
const values = suggestionValues([], 'do');
|
|
expect(values).toEqual(expect.arrayContaining(['docker', 'doctor']));
|
|
expect(values).not.toContain('tokens');
|
|
});
|
|
});
|