mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 13:43:26 +08:00
test: add 3 tests for scoped pkg detection, empty env var, and tools-without-files (Round 94)
- detectFromPackageJson with scoped package name (@scope/pkg@version)
returns null because split('@')[0] yields empty string
- getPackageManager skips empty string CLAUDE_PACKAGE_MANAGER via
falsy short-circuit (distinct from unknown PM name test)
- session-end buildSummarySection includes Tools Used but omits
Files Modified when transcript has only Read/Grep tools
Total tests: 842
This commit is contained in:
@@ -3621,6 +3621,49 @@ Some random content without the expected ### Context to Load section
|
||||
});
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ── Round 94: session-end.js tools used but no files modified ──
|
||||
console.log('\nRound 94: session-end.js (tools used without files modified):');
|
||||
|
||||
if (await asyncTest('session file includes Tools Used but omits Files Modified when only Read/Grep used', async () => {
|
||||
// session-end.js buildSummarySection (lines 217-228):
|
||||
// filesModified.length > 0 → include "### Files Modified" section
|
||||
// toolsUsed.length > 0 → include "### Tools Used" section
|
||||
// Previously tested: BOTH present (Round ~10) and NEITHER present (Round ~10).
|
||||
// Untested combination: toolsUsed present, filesModified empty.
|
||||
// Transcript with Read/Grep tools (don't add to filesModified) and user messages.
|
||||
const testDir = createTestDir();
|
||||
const transcriptPath = path.join(testDir, 'transcript.jsonl');
|
||||
|
||||
const lines = [
|
||||
'{"type":"user","content":"Search the codebase for auth handlers"}',
|
||||
'{"type":"tool_use","tool_name":"Read","tool_input":{"file_path":"/src/auth.ts"}}',
|
||||
'{"type":"tool_use","tool_name":"Grep","tool_input":{"pattern":"handler"}}',
|
||||
'{"type":"user","content":"Check the test file too"}',
|
||||
'{"type":"tool_use","tool_name":"Read","tool_input":{"file_path":"/tests/auth.test.ts"}}',
|
||||
];
|
||||
fs.writeFileSync(transcriptPath, lines.join('\n'));
|
||||
|
||||
const stdinJson = JSON.stringify({ transcript_path: transcriptPath });
|
||||
const result = await runScript(path.join(scriptsDir, 'session-end.js'), stdinJson, {
|
||||
HOME: testDir
|
||||
});
|
||||
assert.strictEqual(result.code, 0, 'Should exit 0');
|
||||
|
||||
const claudeDir = path.join(testDir, '.claude', 'sessions');
|
||||
if (fs.existsSync(claudeDir)) {
|
||||
const files = fs.readdirSync(claudeDir).filter(f => f.endsWith('.tmp'));
|
||||
if (files.length > 0) {
|
||||
const content = fs.readFileSync(path.join(claudeDir, files[0]), 'utf8');
|
||||
assert.ok(content.includes('### Tools Used'), 'Should include Tools Used section');
|
||||
assert.ok(content.includes('Read'), 'Should list Read tool');
|
||||
assert.ok(content.includes('Grep'), 'Should list Grep tool');
|
||||
assert.ok(!content.includes('### Files Modified'),
|
||||
'Should NOT include Files Modified section (Read/Grep do not modify files)');
|
||||
}
|
||||
}
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Summary
|
||||
console.log('\n=== Test Results ===');
|
||||
console.log(`Passed: ${passed}`);
|
||||
|
||||
@@ -1412,6 +1412,49 @@ function runTests() {
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ── Round 94: detectFromPackageJson with scoped package name ──
|
||||
console.log('\nRound 94: detectFromPackageJson (scoped package name @scope/pkg@version):');
|
||||
|
||||
if (test('detectFromPackageJson returns null for scoped package name (@scope/pkg@version)', () => {
|
||||
// package-manager.js line 116: pmName = pkg.packageManager.split('@')[0]
|
||||
// For "@pnpm/exe@8.0.0", split('@') → ['', 'pnpm/exe', '8.0.0'], so [0] = ''
|
||||
// PACKAGE_MANAGERS[''] is undefined → returns null.
|
||||
// Scoped npm packages like @pnpm/exe are a real-world pattern but the
|
||||
// packageManager field spec uses unscoped names (e.g., "pnpm@8"), so returning
|
||||
// null is the correct defensive behaviour for this edge case.
|
||||
const testDir = createTestDir();
|
||||
fs.writeFileSync(
|
||||
path.join(testDir, 'package.json'),
|
||||
JSON.stringify({ name: 'test', packageManager: '@pnpm/exe@8.0.0' }));
|
||||
const result = pm.detectFromPackageJson(testDir);
|
||||
assert.strictEqual(result, null,
|
||||
'Scoped package name should return null (split("@")[0] is empty string)');
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ── Round 94: getPackageManager with empty string CLAUDE_PACKAGE_MANAGER ──
|
||||
console.log('\nRound 94: getPackageManager (empty string CLAUDE_PACKAGE_MANAGER env var):');
|
||||
|
||||
if (test('getPackageManager skips empty string CLAUDE_PACKAGE_MANAGER (falsy short-circuit)', () => {
|
||||
// package-manager.js line 168: if (envPm && PACKAGE_MANAGERS[envPm])
|
||||
// Empty string '' is falsy — the && short-circuits before checking PACKAGE_MANAGERS.
|
||||
// This is distinct from the 'totally-fake-pm' test (truthy but unknown PM).
|
||||
const originalEnv = process.env.CLAUDE_PACKAGE_MANAGER;
|
||||
try {
|
||||
process.env.CLAUDE_PACKAGE_MANAGER = '';
|
||||
const result = pm.getPackageManager();
|
||||
assert.notStrictEqual(result.source, 'environment',
|
||||
'Empty string env var should NOT be treated as environment source');
|
||||
assert.ok(result.name, 'Should still return a valid package manager name');
|
||||
} finally {
|
||||
if (originalEnv !== undefined) {
|
||||
process.env.CLAUDE_PACKAGE_MANAGER = originalEnv;
|
||||
} else {
|
||||
delete process.env.CLAUDE_PACKAGE_MANAGER;
|
||||
}
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Summary
|
||||
console.log('\n=== Test Results ===');
|
||||
console.log(`Passed: ${passed}`);
|
||||
|
||||
Reference in New Issue
Block a user