mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-20 23:11:46 +02:00
* test(lib): cover feedback-links routes and payload Pins the three public issue routes to the ECC repository and checks each template name actually exists under .github/ISSUE_TEMPLATE. Also locks the ecc.feedback.v1 payload shape, the no-diagnostics-upload promise, and that every call returns fresh copies so a caller cannot alter the frozen route table. * test(lib): cover cursor-agent-names prefixing and path handling Pins the ecc- prefix rule the Cursor install applies to agent files: idempotent, lowercase-prefix only, empty names pass through. Covers the relative path variant across backslash, repeated, and trailing separators, and that a leading separator cannot re-root the destination under the target agents directory. * test(lib): cover agent-tool-map Pi mapping and authority invariant Pins the Claude to Pi tool table: six core tools, every target a real Pi built-in, and read-only tools never escalating to bash, edit, or write. Covers the unsupported path for MCP, web, unknown, empty, and non-string names, and that prototype member names like constructor are not treated as table hits. * test(lib): cover compute-sponsor URL and passive copy Pins the compute URL to the bare https route with no path, query, or credentials, and that the sponsor copy links it exactly once and nowhere else. Locks the wording that keeps the link passive, keeps the ecc ito find bridge opt-in and non-reserving, and does not claim managed inference is live. The existing surface test only reads docs and CLI output, so the module itself had no direct test. * test(lib): cover invocation-environment precedence and isolation Pins the three branches every install path relies on: an explicit env is copied and wins, a scoped homeDir yields an empty environment so ambient variables cannot leak into a contained install, and anything else snapshots process.env. Also checks the copy is shallow, own-keys only, and never writes back.
107 lines
3.6 KiB
JavaScript
107 lines
3.6 KiB
JavaScript
'use strict';
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const { resolveInvocationEnvironment } = require('../../scripts/lib/invocation-environment');
|
|
|
|
const PROBE = 'ECC_INVOCATION_ENVIRONMENT_PROBE';
|
|
|
|
function withProbe(value, fn) {
|
|
const saved = process.env[PROBE];
|
|
process.env[PROBE] = value;
|
|
try {
|
|
return fn();
|
|
} finally {
|
|
if (saved === undefined) {
|
|
delete process.env[PROBE];
|
|
} else {
|
|
process.env[PROBE] = saved;
|
|
}
|
|
}
|
|
}
|
|
|
|
test('with no options the ambient process environment is returned as a copy', () => {
|
|
withProbe('ambient', () => {
|
|
const resolved = resolveInvocationEnvironment();
|
|
assert.notEqual(resolved, process.env);
|
|
assert.deepEqual(resolved, { ...process.env });
|
|
assert.equal(resolved[PROBE], 'ambient');
|
|
});
|
|
});
|
|
|
|
test('an empty options object behaves like no options', () => {
|
|
withProbe('ambient', () => {
|
|
assert.deepEqual(resolveInvocationEnvironment({}), { ...process.env });
|
|
});
|
|
});
|
|
|
|
test('mutating the copy never writes back to process.env', () => {
|
|
const resolved = resolveInvocationEnvironment();
|
|
resolved[PROBE] = 'leaked';
|
|
delete resolved.PATH;
|
|
assert.equal(process.env[PROBE], undefined);
|
|
assert.equal(typeof process.env.PATH, 'string');
|
|
});
|
|
|
|
test('the copy is a snapshot and does not see later process.env changes', () => {
|
|
const resolved = resolveInvocationEnvironment();
|
|
withProbe('later', () => {
|
|
assert.equal(resolved[PROBE], undefined);
|
|
});
|
|
});
|
|
|
|
test('an explicit env is copied, not shared, and replaces the ambient environment', () => {
|
|
withProbe('ambient', () => {
|
|
const source = { HOME: '/scoped/home', PATH: '/scoped/bin' };
|
|
const resolved = resolveInvocationEnvironment({ env: source });
|
|
assert.notEqual(resolved, source);
|
|
assert.deepEqual(resolved, source);
|
|
assert.equal(resolved[PROBE], undefined);
|
|
|
|
resolved.EXTRA = '1';
|
|
assert.equal(source.EXTRA, undefined);
|
|
});
|
|
});
|
|
|
|
test('only own enumerable keys of an explicit env are copied', () => {
|
|
const source = Object.create({ INHERITED: 'yes' });
|
|
source.OWN = 'yes';
|
|
Object.defineProperty(source, 'HIDDEN', { value: 'yes', enumerable: false });
|
|
assert.deepEqual(resolveInvocationEnvironment({ env: source }), { OWN: 'yes' });
|
|
});
|
|
|
|
test('env: null and env: undefined mean an empty environment, not the ambient one', () => {
|
|
withProbe('ambient', () => {
|
|
assert.deepEqual(resolveInvocationEnvironment({ env: null }), {});
|
|
assert.deepEqual(resolveInvocationEnvironment({ env: undefined }), {});
|
|
});
|
|
});
|
|
|
|
test('an explicit env wins over homeDir', () => {
|
|
const resolved = resolveInvocationEnvironment({ env: { A: '1' }, homeDir: '/scoped' });
|
|
assert.deepEqual(resolved, { A: '1' });
|
|
});
|
|
|
|
test('a scoped homeDir gives an empty environment so ambient variables cannot leak into the install', () => {
|
|
withProbe('ambient', () => {
|
|
const resolved = resolveInvocationEnvironment({ homeDir: '/scoped/home' });
|
|
assert.deepEqual(resolved, {});
|
|
assert.equal(resolved.HOME, undefined);
|
|
assert.equal(resolved[PROBE], undefined);
|
|
});
|
|
});
|
|
|
|
test('a blank or non-string homeDir does not count as scoped', () => {
|
|
withProbe('ambient', () => {
|
|
for (const homeDir of ['', ' ', '\n', null, undefined, 42, true]) {
|
|
assert.deepEqual(resolveInvocationEnvironment({ homeDir }), { ...process.env }, `homeDir ${JSON.stringify(homeDir)} should fall back to the ambient environment`);
|
|
}
|
|
});
|
|
});
|
|
|
|
test('each call returns a distinct object', () => {
|
|
assert.notEqual(resolveInvocationEnvironment(), resolveInvocationEnvironment());
|
|
assert.notEqual(resolveInvocationEnvironment({ homeDir: '/scoped' }), resolveInvocationEnvironment({ homeDir: '/scoped' }));
|
|
});
|