Files
msd-core/tests/bug-2957-claude-global-postinstall-message.test.cjs
Tom Boucher c5dfdbe42e fix(#2957): claude+global post-install instructs restart and skill fallback (#2960)
* fix(#2957): claude+global post-install instructs restart and skill fallback

`npx get-shit-done-cc --claude --global` writes skills to
`~/.claude/skills/gsd-*/SKILL.md` (CC 2.1.88+ format) and removes the
legacy `~/.claude/commands/gsd/`. The post-install message still told
users to type `/gsd-new-project` without mentioning the required Claude
Code restart or the skill-name fallback. On configurations where CC
does not auto-surface skills in the slash menu, users hit "no commands
appear" and assumed the install failed.

Split the post-install message: the existing single-line instruction
stays for every non-Claude runtime and for `--claude --local`. For
`--claude --global` it now reads:

  Restart Claude Code, then in any directory either type
  /gsd-new-project or ask Claude to run the gsd-new-project skill.

This covers both invocation paths and surfaces the restart requirement.

Add tests/bug-2957-claude-global-postinstall-message.test.cjs as a
regression guard: captures the printed message for claude+global,
claude+local, and opencode+global; asserts content for each. Verified
the test fails on main (pre-fix) and passes after the fix.

Closes #2957

* test(#2957): assert legacy generic instruction is replaced not extended

CodeRabbit flagged that the test would still pass if the new restart/
fallback copy were printed *alongside* the old 'open a blank directory'
instruction. Adding a doesNotMatch assertion proves the claude+global
branch replaces the legacy line rather than appending to it.
2026-05-01 13:04:39 -04:00

71 lines
2.6 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 ROOT = path.join(__dirname, '..');
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(
'/tmp/gsd-test-settings.json',
{},
null,
false,
runtime,
isGlobal,
null,
);
} finally {
console.log = original;
}
// Strip ANSI color escapes so message-content assertions don't couple to colors.
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');
});
});