mirror of
https://github.com/affaan-m/ECC.git
synced 2026-08-17 21:15:40 +02:00
* feat(install): add guided Claude plugin setup * fix: support Claude command shims on Windows * feat: support safe Claude plugin scope migration * fix(install): preserve interactive setup terminal * fix(install): auto-migrate setup scope changes * feat(install): add guided multi-harness installer * fix(install): sync Yarn binary metadata * fix(install): handle wizard EOF on Node 18 * ci: allow installer matrix tests to finish * test(install): allow slower PowerShell delegation * fix(install): harden guided provider reconciliation * test(install): harden packaged and local compatibility * chore: prepare guided installer release 2.2.0 * fix(install): report refreshed Codex marketplace state * fix(install): verify managed content provenance * test(install): allow empty Yarn smoke fixture * test(install): invoke Windows package shims safely * fix(install): close cross-platform release gaps * fix(install): require trusted GitHub origins * fix(install): preserve hook profile precedence * refactor(install): centralize trusted GitHub origins * ci: retrigger workflow run after merge of main Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
120 lines
3.8 KiB
JavaScript
120 lines
3.8 KiB
JavaScript
'use strict';
|
|
|
|
const assert = require('assert');
|
|
const path = require('path');
|
|
const { spawnSync } = require('child_process');
|
|
const { version } = require('../../package.json');
|
|
|
|
const repoRoot = path.resolve(__dirname, '..', '..');
|
|
const eccScript = path.join(repoRoot, 'scripts', 'ecc.js');
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
|
|
function test(name, fn) {
|
|
try {
|
|
fn();
|
|
console.log(` ✓ ${name}`);
|
|
passed += 1;
|
|
} catch (error) {
|
|
console.log(` ✗ ${name}`);
|
|
console.log(` Error: ${error.message}`);
|
|
failed += 1;
|
|
}
|
|
}
|
|
|
|
function runEcc(args, env = {}) {
|
|
return spawnSync(process.execPath, [eccScript, ...args], {
|
|
cwd: repoRoot,
|
|
encoding: 'utf8',
|
|
env: { ...process.env, NO_COLOR: '1', ...env },
|
|
});
|
|
}
|
|
|
|
function containsTerminalControlBytes(value) {
|
|
return Array.from(value).some(character => {
|
|
const codePoint = character.codePointAt(0);
|
|
return codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f);
|
|
});
|
|
}
|
|
|
|
console.log('\n=== ECC welcome command tests ===\n');
|
|
|
|
test('ecc welcome renders the install artwork for captured agent output', () => {
|
|
const result = runEcc(['welcome']);
|
|
|
|
assert.strictEqual(result.status, 0, result.stderr);
|
|
assert.match(result.stdout, /Welcome to ECC!/);
|
|
assert.ok(result.stdout.includes(`v${version}`));
|
|
assert.match(result.stdout, /GitHub:\s+https:\/\/github\.com\/affaan-m\/ECC/);
|
|
assert.match(result.stdout, /Discord:\s+https:\/\/discord\.gg\/36yGMHGFbR/);
|
|
assert.strictEqual(result.stderr, '');
|
|
});
|
|
|
|
test('ecc welcome disables ANSI color when stdout is redirected', () => {
|
|
const env = { ...process.env, TERM: 'xterm-256color' };
|
|
delete env.NO_COLOR;
|
|
const result = spawnSync(process.execPath, [eccScript, 'welcome'], {
|
|
cwd: repoRoot,
|
|
encoding: 'utf8',
|
|
env,
|
|
});
|
|
|
|
assert.strictEqual(result.status, 0, result.stderr);
|
|
assert.strictEqual(result.stdout.includes('\u001b['), false);
|
|
});
|
|
|
|
test('ecc welcome supports explicit update and configured outcomes', () => {
|
|
const cases = [
|
|
['updated', /ECC is updated/],
|
|
['configured', /ECC is configured/],
|
|
['migrated', /ECC is configured/],
|
|
['resumed', /ECC is configured/],
|
|
['already-migrated', /ECC is configured/],
|
|
];
|
|
|
|
for (const [action, expected] of cases) {
|
|
const result = runEcc(['welcome', '--action', action]);
|
|
assert.strictEqual(result.status, 0, result.stderr);
|
|
assert.match(result.stdout, expected);
|
|
}
|
|
});
|
|
|
|
test('ecc welcome renders a provider-verified installed version', () => {
|
|
const result = runEcc(['welcome', '--version', '2.1.0']);
|
|
|
|
assert.strictEqual(result.status, 0, result.stderr);
|
|
assert.match(result.stdout, /v2\.1\.0/);
|
|
});
|
|
|
|
test('ecc welcome rejects unsafe version text', () => {
|
|
const result = runEcc(['welcome', '--version', '2.1.0\u001b[31m']);
|
|
|
|
assert.strictEqual(result.status, 1);
|
|
assert.match(result.stderr, /Invalid --version value/);
|
|
assert.strictEqual(containsTerminalControlBytes(result.stderr.trimEnd()), false);
|
|
assert.strictEqual(result.stdout, '');
|
|
});
|
|
|
|
test('ecc welcome keeps parser error output free of terminal control bytes', () => {
|
|
const actionResult = runEcc(['welcome', '--action', 'broken\u001b[31m']);
|
|
const argumentResult = runEcc(['welcome', '--bad\u001b[31m']);
|
|
|
|
for (const result of [actionResult, argumentResult]) {
|
|
assert.strictEqual(result.status, 1);
|
|
assert.strictEqual(containsTerminalControlBytes(result.stderr.trimEnd()), false);
|
|
assert.strictEqual(result.stdout, '');
|
|
}
|
|
});
|
|
|
|
test('ecc welcome rejects unknown actions before rendering', () => {
|
|
const result = runEcc(['welcome', '--action', 'broken']);
|
|
|
|
assert.strictEqual(result.status, 1);
|
|
assert.match(result.stderr, /Invalid --action value/);
|
|
assert.strictEqual(result.stdout, '');
|
|
});
|
|
|
|
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}\n`);
|
|
if (failed > 0) process.exit(1);
|