Files
qinglong/cli/test/internal/environmentTransport.test.cjs
T
whyour 801a71d740 feat(cli): cover OpenAPI with a remote npm CLI and internal panel tools (#3074)
* 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
2026-09-25 23:24:41 +08:00

39 lines
1.9 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const { sourceEnvironment } = require('../../dist/internal/runtime/context');
const { runProcess } = require('../../dist/internal/runtime/process');
test('environment transport preserves multiline values, empty values and exported functions', async () => {
const value = '中文\nsecond=line\r\n"quoted"\\literal';
const env = await sourceEnvironment({ PATH: process.env.PATH, VALUE: value }, [], [], {
command: 'export EMPTY=""; exported_fn() { printf "%s" "$VALUE"; }; export -f exported_fn; set -o pipefail; shopt -s nullglob; printf "user output"',
output: () => {},
});
assert.equal(env.VALUE, value);
assert.equal(env.EMPTY, '');
assert.ok(env.QL_CLI_SHELLOPTS.split(':').includes('pipefail'));
assert.ok(!env.QL_CLI_SHELLOPTS.split(':').includes('allexport'));
assert.ok(env.QL_CLI_BASHOPTS.split(':').includes('nullglob'));
assert.ok(!Object.keys(env).some(key => key.startsWith('__ql_')));
const child = await runProcess('bash', ['--noprofile', '--norc', '-c', 'exported_fn'], { env, capture: true });
assert.equal(child.code, 0);
assert.equal(child.stdout, value);
});
test('environment transport does not execute a Node runtime from user configuration', async () => {
const env = await sourceEnvironment({ PATH: process.env.PATH }, [], [], {
command: 'export NODE_OPTIONS="--this-option-does-not-exist"; export PATH="/nonexistent"',
});
assert.equal(env.NODE_OPTIONS, '--this-option-does-not-exist');
assert.equal(env.PATH, '/nonexistent');
});
for (const redirect of ['exec 3>/dev/null 9>/dev/null', 'exec 3>&-']) {
test(`environment transport survives user descriptors: ${redirect}`, async () => {
const env = await sourceEnvironment({ PATH: process.env.PATH }, [], [], {
command: `${redirect}; export FIXTURE_VALUE=present`,
});
assert.equal(env.FIXTURE_VALUE, 'present');
});
}