mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-28 09:02:12 +08:00
* feat(cli): add unified Commander CLI for QingLong 2.x * fix(cli): publish via npm and address security review feedback * ci(cli): package npm artifacts and remove evaluation collateral * test(cli): use a fixed shell fixture for log retention * refactor(cli): separate remote npm client from panel tools * feat(cli): cover active panel OpenAPI resources * docs(cli): unify authentication and skill guidance * refactor(cli): isolate internal commands and generate Commander help * refactor(cli): organize remote and internal modules by responsibility * ci(cli): publish verified npm archives from master * fix(cli): publish under the whyour npm scope * ci: use npm trusted publishing for both packages * docs: introduce the published CLI on the project homepage * fix(cli): preserve server log truncation and correct login hints * fix(cli): accept dashboard record request bodies * fix(cli): preserve stdin for local task execution * fix(cli): resolve task executables after changing directory * fix(cli): preserve shell function tasks and sanitize test failures * fix(cli): preserve shell hook state and resolve workdir after hooks * fix(cli): preserve cleanup across shared shell task timeouts * fix(cli): isolate shell control descriptors and reap timed-out descendants
44 lines
2.5 KiB
JavaScript
44 lines
2.5 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const { parse } = require('../helpers/commands.cjs');
|
|
const { parseExecution } = require('../../dist/runner');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
test('Commander adapter preserves literal values, option polarity, duplicate errors and IDs', () => {
|
|
assert.equal(parse(['task','list','--search','00123']).values.search, '00123');
|
|
assert.equal(parse(['local','start','--no-startup'], 'local').values['no-startup'], true);
|
|
assert.equal(parse(['local','start'], 'local').values['no-startup'], undefined);
|
|
assert.equal(parse(['auth','login','--url=--json']).values.url, '--json');
|
|
assert.deepEqual(parse(['local','resetpwd','--','-literal'], 'local').positionals, ['-literal']);
|
|
for (const args of [
|
|
['task','list','--search','--json'], ['auth','login','--url','--json'],
|
|
['task','list','-p','2','--page','3'], ['task','list','--json','--json'],
|
|
['--json','task','list','--json'], ['task','list','unexpected'],
|
|
['task','run','0'], ['task','run','script.js'], ['task','list','--size','201'],
|
|
['task','list','--json=false'],
|
|
]) assert.throws(() => parse(args), { exitCode:2 }, JSON.stringify(args));
|
|
assert.ok(parse(['auth','login','--help']).help);
|
|
assert.ok(parse(['--help']).help);
|
|
});
|
|
|
|
test('Commander task parsing stops at the script and preserves the execution separator', () => {
|
|
const args = ['--root','/isolated','--json','script.sh','now','--','--json','--root','-literal'];
|
|
const parsed = parseExecution(args);
|
|
assert.equal(parsed.values.root, '/isolated');
|
|
assert.equal(parsed.values.json, true);
|
|
assert.deepEqual(parsed.execution.scriptArgs, ['--json','--root','-literal']);
|
|
assert.deepEqual(parseExecution(['script.sh','--json']).execution.argv, ['script.sh','--json']);
|
|
assert.deepEqual(parseExecution(['--','-script','--','-x']).execution.scriptArgs, ['-x']);
|
|
assert.throws(() => parseExecution(['--root','--json','script.sh']), { exitCode:2 });
|
|
});
|
|
|
|
test('Commander is bundled once with its license and has no external runtime resolution', () => {
|
|
const manifest = require('../../package.json');
|
|
assert.equal(manifest.devDependencies.commander, '15.0.0');
|
|
assert.equal(Object.keys(manifest.dependencies || {}).length, 0);
|
|
const bundled = fs.readFileSync(path.join(__dirname,'../../dist/shared/cli/commander.js'), 'utf8');
|
|
assert.doesNotMatch(bundled, /require\(["']commander["']\)/);
|
|
assert.match(fs.readFileSync(path.join(__dirname,'../../dist/licenses/commander-LICENSE'), 'utf8'), /MIT/);
|
|
});
|