mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-14 12:11:27 +08:00
test: guard broken-symlink tests so the suite passes on Windows (#2176)
* test: guard broken-symlink tests so the suite passes on Windows Four test cases create a dangling symlink with fs.symlinkSync() to exercise statSync catch branches, but did not guard for platforms where symlink creation is not permitted. On Windows without Developer Mode / admin rights, fs.symlinkSync throws EPERM, so these tests fail and `npm test` is red: - tests/ci/validators.test.js (Round 73, validate-commands skill entry) - tests/lib/session-manager.test.js (Round 83, getAllSessions) - tests/lib/session-manager.test.js (Round 84, getSessionById) - tests/lib/utils.test.js (Round 84, findFiles) Wrap each symlinkSync in try/catch and skip cleanly on failure, mirroring the existing convention already used in this repo (validators.test.js Round 57 and hooks/config-protection.test.js). On Linux/macOS and admin Windows the symlink still succeeds and the tests run unchanged; only the unsupported-symlink path now skips instead of failing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: only skip symlink tests on EPERM/EACCES, rethrow other errors Address CodeRabbit review: the catch blocks swallowed every error, which could mask a real test/setup failure as a false skip. Inspect err.code and only take the skip path for EPERM/EACCES (symlink creation blocked, e.g. Windows without Developer Mode); rethrow anything else so genuine failures still surface. Per the repo coding guideline: never silently swallow errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2577,7 +2577,21 @@ function runTests() {
|
|||||||
fs.mkdirSync(validSkill, { recursive: true });
|
fs.mkdirSync(validSkill, { recursive: true });
|
||||||
// Broken symlink: target does not exist — statSync will throw ENOENT
|
// Broken symlink: target does not exist — statSync will throw ENOENT
|
||||||
const brokenLink = path.join(skillsDir, 'broken-skill');
|
const brokenLink = path.join(skillsDir, 'broken-skill');
|
||||||
fs.symlinkSync('/nonexistent/target/path', brokenLink);
|
try {
|
||||||
|
fs.symlinkSync('/nonexistent/target/path', brokenLink);
|
||||||
|
} catch (err) {
|
||||||
|
// Skip only where symlink creation is blocked (e.g. Windows without
|
||||||
|
// Developer Mode / admin rights → EPERM/EACCES); rethrow anything else
|
||||||
|
// so real failures aren't masked.
|
||||||
|
if (err && (err.code === 'EPERM' || err.code === 'EACCES')) {
|
||||||
|
console.log(' (skipped — symlinks not supported)');
|
||||||
|
cleanupTestDir(testDir);
|
||||||
|
cleanupTestDir(agentsDir);
|
||||||
|
fs.rmSync(skillsDir, { recursive: true, force: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
// Command that references the valid skill (should resolve)
|
// Command that references the valid skill (should resolve)
|
||||||
fs.writeFileSync(path.join(testDir, 'cmd.md'),
|
fs.writeFileSync(path.join(testDir, 'cmd.md'),
|
||||||
|
|||||||
@@ -1384,7 +1384,19 @@ src/main.ts
|
|||||||
|
|
||||||
// Create a broken symlink that matches the session filename pattern
|
// Create a broken symlink that matches the session filename pattern
|
||||||
const brokenSymlink = '2026-02-10-deadbeef-session.tmp';
|
const brokenSymlink = '2026-02-10-deadbeef-session.tmp';
|
||||||
fs.symlinkSync('/nonexistent/path/that/does/not/exist', path.join(sessionsDir, brokenSymlink));
|
try {
|
||||||
|
fs.symlinkSync('/nonexistent/path/that/does/not/exist', path.join(sessionsDir, brokenSymlink));
|
||||||
|
} catch (err) {
|
||||||
|
// Skip only where symlink creation is blocked (e.g. Windows without
|
||||||
|
// Developer Mode / admin rights → EPERM/EACCES); rethrow anything else
|
||||||
|
// so real failures aren't masked.
|
||||||
|
if (err && (err.code === 'EPERM' || err.code === 'EACCES')) {
|
||||||
|
console.log(' (skipped — symlinks not supported)');
|
||||||
|
fs.rmSync(isoHome, { recursive: true, force: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
const origHome = process.env.HOME;
|
const origHome = process.env.HOME;
|
||||||
const origUserProfile = process.env.USERPROFILE;
|
const origUserProfile = process.env.USERPROFILE;
|
||||||
@@ -1421,7 +1433,19 @@ src/main.ts
|
|||||||
|
|
||||||
// Create a broken symlink that matches a session ID pattern
|
// Create a broken symlink that matches a session ID pattern
|
||||||
const brokenFile = '2026-02-11-deadbeef-session.tmp';
|
const brokenFile = '2026-02-11-deadbeef-session.tmp';
|
||||||
fs.symlinkSync('/nonexistent/target/that/does/not/exist', path.join(sessionsDir, brokenFile));
|
try {
|
||||||
|
fs.symlinkSync('/nonexistent/target/that/does/not/exist', path.join(sessionsDir, brokenFile));
|
||||||
|
} catch (err) {
|
||||||
|
// Skip only where symlink creation is blocked (e.g. Windows without
|
||||||
|
// Developer Mode / admin rights → EPERM/EACCES); rethrow anything else
|
||||||
|
// so real failures aren't masked.
|
||||||
|
if (err && (err.code === 'EPERM' || err.code === 'EACCES')) {
|
||||||
|
console.log(' (skipped — symlinks not supported)');
|
||||||
|
fs.rmSync(isoHome, { recursive: true, force: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
const origHome = process.env.HOME;
|
const origHome = process.env.HOME;
|
||||||
const origUserProfile = process.env.USERPROFILE;
|
const origUserProfile = process.env.USERPROFILE;
|
||||||
|
|||||||
+13
-1
@@ -1415,7 +1415,19 @@ function runTests() {
|
|||||||
const realFile = path.join(tmpDir, 'real.txt');
|
const realFile = path.join(tmpDir, 'real.txt');
|
||||||
fs.writeFileSync(realFile, 'content');
|
fs.writeFileSync(realFile, 'content');
|
||||||
const brokenLink = path.join(tmpDir, 'broken.txt');
|
const brokenLink = path.join(tmpDir, 'broken.txt');
|
||||||
fs.symlinkSync('/nonexistent/path/does/not/exist', brokenLink);
|
try {
|
||||||
|
fs.symlinkSync('/nonexistent/path/does/not/exist', brokenLink);
|
||||||
|
} catch (err) {
|
||||||
|
// Skip only where symlink creation is blocked (e.g. Windows without
|
||||||
|
// Developer Mode / admin rights → EPERM/EACCES); rethrow anything else
|
||||||
|
// so real failures aren't masked.
|
||||||
|
if (err && (err.code === 'EPERM' || err.code === 'EACCES')) {
|
||||||
|
console.log(' (skipped — symlinks not supported)');
|
||||||
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const results = utils.findFiles(tmpDir, '*.txt');
|
const results = utils.findFiles(tmpDir, '*.txt');
|
||||||
|
|||||||
Reference in New Issue
Block a user