mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-08 10:23:30 +08:00
fix: fold session manager blockers into one candidate
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { spawnSync } = require('child_process');
|
||||
|
||||
// Import the module
|
||||
const utils = require('../../scripts/lib/utils');
|
||||
@@ -68,7 +69,13 @@ function runTests() {
|
||||
const sessionsDir = utils.getSessionsDir();
|
||||
const claudeDir = utils.getClaudeDir();
|
||||
assert.ok(sessionsDir.startsWith(claudeDir), 'Sessions should be under Claude dir');
|
||||
assert.ok(sessionsDir.includes('sessions'), 'Should contain sessions');
|
||||
assert.ok(sessionsDir.endsWith(path.join('.claude', 'session-data')) || sessionsDir.endsWith('/.claude/session-data'), 'Should use canonical session-data directory');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('getSessionSearchDirs includes canonical and legacy paths', () => {
|
||||
const searchDirs = utils.getSessionSearchDirs();
|
||||
assert.ok(searchDirs.includes(utils.getSessionsDir()), 'Should include canonical session dir');
|
||||
assert.ok(searchDirs.includes(utils.getLegacySessionsDir()), 'Should include legacy session dir');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('getTempDir returns valid temp directory', () => {
|
||||
@@ -118,17 +125,77 @@ function runTests() {
|
||||
assert.ok(name && name.length > 0);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// sanitizeSessionId tests
|
||||
console.log('\nsanitizeSessionId:');
|
||||
|
||||
if (test('sanitizeSessionId strips leading dots', () => {
|
||||
assert.strictEqual(utils.sanitizeSessionId('.claude'), 'claude');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('sanitizeSessionId replaces dots and spaces', () => {
|
||||
assert.strictEqual(utils.sanitizeSessionId('my.project'), 'my-project');
|
||||
assert.strictEqual(utils.sanitizeSessionId('my project'), 'my-project');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('sanitizeSessionId replaces special chars and collapses runs', () => {
|
||||
assert.strictEqual(utils.sanitizeSessionId('project@v2'), 'project-v2');
|
||||
assert.strictEqual(utils.sanitizeSessionId('a...b'), 'a-b');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('sanitizeSessionId preserves valid chars', () => {
|
||||
assert.strictEqual(utils.sanitizeSessionId('my-project_123'), 'my-project_123');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('sanitizeSessionId returns null for empty or punctuation-only values', () => {
|
||||
assert.strictEqual(utils.sanitizeSessionId(''), null);
|
||||
assert.strictEqual(utils.sanitizeSessionId(null), null);
|
||||
assert.strictEqual(utils.sanitizeSessionId(undefined), null);
|
||||
assert.strictEqual(utils.sanitizeSessionId('...'), null);
|
||||
assert.strictEqual(utils.sanitizeSessionId('…'), null);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('sanitizeSessionId returns stable hashes for non-ASCII values', () => {
|
||||
const chinese = utils.sanitizeSessionId('我的项目');
|
||||
const cyrillic = utils.sanitizeSessionId('проект');
|
||||
const emoji = utils.sanitizeSessionId('🚀🎉');
|
||||
assert.ok(/^[a-f0-9]{8}$/.test(chinese), `Expected 8-char hash, got: ${chinese}`);
|
||||
assert.ok(/^[a-f0-9]{8}$/.test(cyrillic), `Expected 8-char hash, got: ${cyrillic}`);
|
||||
assert.ok(/^[a-f0-9]{8}$/.test(emoji), `Expected 8-char hash, got: ${emoji}`);
|
||||
assert.notStrictEqual(chinese, cyrillic);
|
||||
assert.notStrictEqual(chinese, emoji);
|
||||
assert.strictEqual(utils.sanitizeSessionId('日本語プロジェクト'), utils.sanitizeSessionId('日本語プロジェクト'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('sanitizeSessionId disambiguates mixed-script names from pure ASCII', () => {
|
||||
const mixed = utils.sanitizeSessionId('我的app');
|
||||
const mixedTwo = utils.sanitizeSessionId('他的app');
|
||||
const pure = utils.sanitizeSessionId('app');
|
||||
assert.strictEqual(pure, 'app');
|
||||
assert.ok(mixed.startsWith('app-'), `Expected mixed-script prefix, got: ${mixed}`);
|
||||
assert.notStrictEqual(mixed, pure);
|
||||
assert.notStrictEqual(mixed, mixedTwo);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('sanitizeSessionId is idempotent', () => {
|
||||
for (const input of ['.claude', 'my.project', 'project@v2', 'a...b', 'my-project_123']) {
|
||||
const once = utils.sanitizeSessionId(input);
|
||||
const twice = utils.sanitizeSessionId(once);
|
||||
assert.strictEqual(once, twice, `Expected idempotent result for ${input}`);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Session ID tests
|
||||
console.log('\nSession ID Functions:');
|
||||
|
||||
if (test('getSessionIdShort falls back to project name', () => {
|
||||
if (test('getSessionIdShort falls back to sanitized project name', () => {
|
||||
const original = process.env.CLAUDE_SESSION_ID;
|
||||
delete process.env.CLAUDE_SESSION_ID;
|
||||
try {
|
||||
const shortId = utils.getSessionIdShort();
|
||||
assert.strictEqual(shortId, utils.getProjectName());
|
||||
assert.strictEqual(shortId, utils.sanitizeSessionId(utils.getProjectName()));
|
||||
} finally {
|
||||
if (original) process.env.CLAUDE_SESSION_ID = original;
|
||||
if (original !== undefined) process.env.CLAUDE_SESSION_ID = original;
|
||||
else delete process.env.CLAUDE_SESSION_ID;
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
@@ -154,6 +221,28 @@ function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('getSessionIdShort sanitizes explicit fallback parameter', () => {
|
||||
if (process.platform === 'win32') {
|
||||
console.log(' (skipped — root CWD differs on Windows)');
|
||||
return true;
|
||||
}
|
||||
|
||||
const utilsPath = path.join(__dirname, '..', '..', 'scripts', 'lib', 'utils.js');
|
||||
const script = `
|
||||
const utils = require('${utilsPath.replace(/'/g, "\\'")}');
|
||||
process.stdout.write(utils.getSessionIdShort('my.fallback'));
|
||||
`;
|
||||
const result = spawnSync('node', ['-e', script], {
|
||||
encoding: 'utf8',
|
||||
cwd: '/',
|
||||
env: { ...process.env, CLAUDE_SESSION_ID: '' },
|
||||
timeout: 10000
|
||||
});
|
||||
|
||||
assert.strictEqual(result.status, 0, `Expected exit 0, got ${result.status}. stderr: ${result.stderr}`);
|
||||
assert.strictEqual(result.stdout, 'my-fallback');
|
||||
})) passed++; else failed++;
|
||||
|
||||
// File operations tests
|
||||
console.log('\nFile Operations:');
|
||||
|
||||
@@ -1415,25 +1504,26 @@ function runTests() {
|
||||
// ── Round 97: getSessionIdShort with whitespace-only CLAUDE_SESSION_ID ──
|
||||
console.log('\nRound 97: getSessionIdShort (whitespace-only session ID):');
|
||||
|
||||
if (test('getSessionIdShort returns whitespace when CLAUDE_SESSION_ID is all spaces', () => {
|
||||
// utils.js line 116: if (sessionId && sessionId.length > 0) — ' ' is truthy
|
||||
// and has length > 0, so it passes the check instead of falling back.
|
||||
const original = process.env.CLAUDE_SESSION_ID;
|
||||
try {
|
||||
process.env.CLAUDE_SESSION_ID = ' '; // 10 spaces
|
||||
const result = utils.getSessionIdShort('fallback');
|
||||
// slice(-8) on 10 spaces returns 8 spaces — not the expected fallback
|
||||
assert.strictEqual(result, ' ',
|
||||
'Whitespace-only ID should return 8 trailing spaces (no trim check)');
|
||||
assert.strictEqual(result.trim().length, 0,
|
||||
'Result should be entirely whitespace (demonstrating the missing trim)');
|
||||
} finally {
|
||||
if (original !== undefined) {
|
||||
process.env.CLAUDE_SESSION_ID = original;
|
||||
} else {
|
||||
delete process.env.CLAUDE_SESSION_ID;
|
||||
}
|
||||
if (test('getSessionIdShort sanitizes whitespace-only CLAUDE_SESSION_ID to fallback', () => {
|
||||
if (process.platform === 'win32') {
|
||||
console.log(' (skipped — root CWD differs on Windows)');
|
||||
return true;
|
||||
}
|
||||
|
||||
const utilsPath = path.join(__dirname, '..', '..', 'scripts', 'lib', 'utils.js');
|
||||
const script = `
|
||||
const utils = require('${utilsPath.replace(/'/g, "\\'")}');
|
||||
process.stdout.write(utils.getSessionIdShort('fallback'));
|
||||
`;
|
||||
const result = spawnSync('node', ['-e', script], {
|
||||
encoding: 'utf8',
|
||||
cwd: '/',
|
||||
env: { ...process.env, CLAUDE_SESSION_ID: ' ' },
|
||||
timeout: 10000
|
||||
});
|
||||
|
||||
assert.strictEqual(result.status, 0, `Expected exit 0, got ${result.status}. stderr: ${result.stderr}`);
|
||||
assert.strictEqual(result.stdout, 'fallback');
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ── Round 97: countInFile with same RegExp object called twice (lastIndex reuse) ──
|
||||
|
||||
Reference in New Issue
Block a user