The 5 no-control-regex warnings are all the same intentional ANSI-color-strip pattern /\x1b\[[0-9;]*m/g across 5 test files. The \x1b (ESC) control char is the required leading byte of an ANSI SGR sequence, so matching it is the whole point of stripping color codes from captured CLI/console output. Add an inline eslint-disable-next-line with justification at each site (not a refactor — the control char is essential, not accidental), then flip no-control-regex from warn to error so the debt can't regrow. Refs #736 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
74 lines
2.9 KiB
JavaScript
74 lines
2.9 KiB
JavaScript
'use strict';
|
|
|
|
process.env.GSD_TEST_MODE = '1';
|
|
|
|
/**
|
|
* Bug #2957: post-install message for `--claude --global` must instruct
|
|
* users to restart Claude Code and offer the skill-name fallback, since
|
|
* the skills-only install layout (CC 2.1.88+) leaves nothing in
|
|
* commands/gsd/ for the slash menu to read on older configurations.
|
|
*
|
|
* Captures the call to finishInstall(runtime='claude', isGlobal=true) and
|
|
* asserts the printed message contains both invocation paths.
|
|
*/
|
|
|
|
const { test, describe } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const path = require('node:path');
|
|
const os = require('node:os');
|
|
|
|
const ROOT = path.join(__dirname, '..');
|
|
const SETTINGS_PATH = path.join(os.tmpdir(), `gsd-test-settings-${process.pid}.json`);
|
|
const installModule = require(path.join(ROOT, 'bin', 'install.js'));
|
|
|
|
function captureFinishInstallOutput(runtime, isGlobal) {
|
|
const original = console.log;
|
|
const lines = [];
|
|
console.log = (...args) => { lines.push(args.join(' ')); };
|
|
try {
|
|
installModule.finishInstall(
|
|
SETTINGS_PATH,
|
|
{},
|
|
null,
|
|
false,
|
|
runtime,
|
|
isGlobal,
|
|
null,
|
|
);
|
|
} finally {
|
|
console.log = original;
|
|
}
|
|
// Strip ANSI color escapes so message-content assertions don't couple to colors.
|
|
// eslint-disable-next-line no-control-regex -- \x1b (ESC) is the required leading byte of ANSI SGR color sequences; matching it is the purpose of stripping ANSI codes from captured CLI/console output
|
|
return lines.join('\n').replace(/\x1B\[[0-9;]*m/g, '');
|
|
}
|
|
|
|
describe('Bug #2957: claude+global post-install message', () => {
|
|
test('claude+global message tells the user to restart and offers skill-name fallback', () => {
|
|
const output = captureFinishInstallOutput('claude', true);
|
|
|
|
assert.match(output, /restart claude code/i, 'should mention restart');
|
|
assert.match(output, /\/gsd-new-project/, 'should still mention /gsd-new-project');
|
|
assert.match(output, /gsd-new-project skill/i, 'should mention the skill name fallback');
|
|
assert.doesNotMatch(
|
|
output,
|
|
/open a blank directory/i,
|
|
'global claude install should replace, not extend, the legacy generic instruction',
|
|
);
|
|
});
|
|
|
|
test('claude+local message keeps the original /gsd-new-project instruction', () => {
|
|
const output = captureFinishInstallOutput('claude', false);
|
|
|
|
assert.match(output, /\/gsd-new-project/, 'should still mention /gsd-new-project');
|
|
assert.doesNotMatch(output, /restart claude code/i, 'local install does not require the skills restart note');
|
|
});
|
|
|
|
test('non-claude runtimes keep their original message format', () => {
|
|
const output = captureFinishInstallOutput('opencode', true);
|
|
|
|
assert.match(output, /Open a blank directory/, 'opencode message should be unchanged');
|
|
assert.doesNotMatch(output, /restart/i, 'opencode message should not have the claude-specific restart note');
|
|
});
|
|
});
|