Files
msd-core/tests/retired-artifact-cleanup.test.cjs
𝚌𝚕𝚎𝚣𝚌𝚘𝚍𝚒𝚗𝚐 88f6d9bd1b fix(#2644): deduplicate Cursor slash menu (#2812)
* fix(#2644): deduplicate Cursor slash menu

* fix: preserve installer executable mode

* chore: add changeset for PR #2812

* test(#2644): acknowledge Cursor emission changes

* test(#2644): drop spent emitted drift acknowledgments

* fix(#2644): remove retired Cursor command converter

---------

Co-authored-by: clezcoding <clezcoding@users.noreply.github.com>
Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
2026-08-03 12:05:45 -04:00

156 lines
6.4 KiB
JavaScript

'use strict';
const { test } = require('node:test');
const assert = require('node:assert/strict');
const crypto = require('node:crypto');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const retiredArtifactCleanup = require('../gsd-core/bin/lib/retired-artifact-cleanup.cjs');
const capabilityRegistry = require('../gsd-core/bin/lib/capability-registry.cjs');
const cursorBehaviors = capabilityRegistry.runtimes.cursor.runtime.hostBehaviors;
function createFixture(t) {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-retired-cleanup-'));
const configDir = path.join(root, 'config');
fs.mkdirSync(configDir, { recursive: true });
t.after(() => {
// eslint-disable-next-line local/no-raw-rmsync-in-tests -- isolated temp fixture cleanup
fs.rmSync(root, { recursive: true, force: true });
});
return { root, configDir };
}
function setDeclarations(t, declarations) {
const original = cursorBehaviors.retiredArtifacts;
cursorBehaviors.retiredArtifacts = declarations;
t.after(() => {
cursorBehaviors.retiredArtifacts = original;
});
}
function writeFile(root, relPath, content) {
const filePath = path.join(root, relPath);
fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, content, 'utf8');
return filePath;
}
function sha256(content) {
return crypto.createHash('sha256').update(content).digest('hex');
}
function writeManifest(configDir, files) {
fs.writeFileSync(path.join(configDir, 'gsd-file-manifest.json'), JSON.stringify({
version: '1.8.0',
timestamp: '2026-07-28T00:00:00.000Z',
mode: 'full',
files,
}), 'utf8');
}
test('rejects malformed and escaping retired-artifact declarations', (t) => {
const { root, configDir } = createFixture(t);
const outsideFile = writeFile(root, 'escape/gsd-help.md', '# outside\n');
const localFile = writeFile(configDir, 'commands/gsd-help.md', '# local\n');
setDeclarations(t, [
{ destSubpath: null, prefix: 'gsd-', suffix: '.md' },
{ destSubpath: '../escape', prefix: 'gsd-', suffix: '.md' },
]);
const result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
assert.deepEqual(result, { removed: [], preserved: [] });
assert.ok(fs.existsSync(outsideFile), 'an escaping destination must never be touched');
assert.ok(fs.existsSync(localFile), 'a malformed declaration must not affect valid-looking files');
});
test('refuses a symlinked retired destination directory', (t) => {
const { root, configDir } = createFixture(t);
const targetDir = path.join(root, 'outside-commands');
const targetFile = writeFile(targetDir, 'gsd-help.md', '# outside\n');
const linkType = process.platform === 'win32' ? 'junction' : 'dir';
fs.symlinkSync(targetDir, path.join(configDir, 'commands'), linkType);
setDeclarations(t, [{ destSubpath: 'commands', prefix: 'gsd-', suffix: '.md' }]);
const result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
assert.deepEqual(result, { removed: [], preserved: [] });
assert.ok(fs.existsSync(targetFile), 'cleanup must not follow the destination symlink');
});
test('preserves and reports a user-modified managed file', (t) => {
const { configDir } = createFixture(t);
const relPath = 'commands/gsd-help.md';
const originalContent = '# generated\n';
const modifiedContent = '# user changed this\n';
const filePath = writeFile(configDir, relPath, modifiedContent);
writeManifest(configDir, { [relPath]: sha256(originalContent) });
setDeclarations(t, [{ destSubpath: 'commands', prefix: 'gsd-', suffix: '.md' }]);
const result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
assert.deepEqual(result, { removed: [], preserved: [relPath] });
assert.equal(fs.readFileSync(filePath, 'utf8'), modifiedContent);
assert.ok(fs.existsSync(path.dirname(filePath)), 'directory must remain while a preserved file exists');
});
test('removes and reports a managed-pristine file and then removes the empty directory', (t) => {
const { configDir } = createFixture(t);
const relPath = 'commands/gsd-help.md';
const content = '# generated\n';
const filePath = writeFile(configDir, relPath, content);
const commandsDir = path.dirname(filePath);
writeManifest(configDir, { [relPath]: sha256(content) });
setDeclarations(t, [{ destSubpath: 'commands', prefix: 'gsd-', suffix: '.md' }]);
const result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
assert.deepEqual(result, { removed: [relPath], preserved: [] });
assert.ok(!fs.existsSync(filePath));
assert.ok(!fs.existsSync(commandsDir), 'an empty retired destination should be removed');
});
test('leaves non-matching files untouched and keeps their directory', (t) => {
const { configDir } = createFixture(t);
const managedRelPath = 'commands/gsd-help.md';
const managedContent = '# generated\n';
const managedFile = writeFile(configDir, managedRelPath, managedContent);
const unrelatedFile = writeFile(configDir, 'commands/user-command.md', '# user\n');
writeManifest(configDir, { [managedRelPath]: sha256(managedContent) });
setDeclarations(t, [{ destSubpath: 'commands', prefix: 'gsd-', suffix: '.md' }]);
const result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
assert.deepEqual(result, { removed: [managedRelPath], preserved: [] });
assert.ok(!fs.existsSync(managedFile));
assert.ok(fs.existsSync(unrelatedFile));
assert.ok(fs.existsSync(path.dirname(unrelatedFile)), 'a non-empty destination must remain');
});
test('reports a managed-pristine file as preserved when unlinkSync fails', (t) => {
const { configDir } = createFixture(t);
const relPath = 'commands/gsd-help.md';
const content = '# generated\n';
const filePath = writeFile(configDir, relPath, content);
writeManifest(configDir, { [relPath]: sha256(content) });
setDeclarations(t, [{ destSubpath: 'commands', prefix: 'gsd-', suffix: '.md' }]);
const originalUnlinkSync = fs.unlinkSync;
fs.unlinkSync = (candidate) => {
if (path.resolve(candidate) === path.resolve(filePath)) throw new Error('injected unlink failure');
return originalUnlinkSync(candidate);
};
let result;
try {
result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
} finally {
fs.unlinkSync = originalUnlinkSync;
}
assert.deepEqual(result, { removed: [], preserved: [relPath] });
assert.ok(fs.existsSync(filePath), 'a failed unlink must leave the file in place');
});