mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 13:43:26 +08:00
test: add edge-case tests for countInFile empty pattern, parseSessionMetadata CRLF, and updateAliasTitle empty string coercion (round 115)
This commit is contained in:
@@ -1483,6 +1483,40 @@ function runTests() {
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ── Round 115: updateAliasTitle with empty string — stored as null via || but returned as "" ──
|
||||
console.log('\nRound 115: updateAliasTitle (empty string title — stored null, returned ""):');
|
||||
if (test('updateAliasTitle with empty string stores null but returns empty string (|| coercion mismatch)', () => {
|
||||
resetAliases();
|
||||
|
||||
// Create alias with a title
|
||||
aliases.setAlias('r115-alias', '/path/to/session', 'Original Title');
|
||||
const before = aliases.resolveAlias('r115-alias');
|
||||
assert.strictEqual(before.title, 'Original Title', 'Baseline: title should be set');
|
||||
|
||||
// Update title with empty string
|
||||
// Line 383: typeof "" === 'string' → passes validation
|
||||
// Line 393: "" || null → null (empty string is falsy in JS)
|
||||
// Line 400: returns { title: "" } (original parameter, not stored value)
|
||||
const result = aliases.updateAliasTitle('r115-alias', '');
|
||||
assert.strictEqual(result.success, true, 'Should succeed (empty string passes validation)');
|
||||
assert.strictEqual(result.title, '', 'Return value reflects the input parameter (empty string)');
|
||||
|
||||
// But what's actually stored?
|
||||
const after = aliases.resolveAlias('r115-alias');
|
||||
assert.strictEqual(after.title, null,
|
||||
'Stored title should be null because "" || null evaluates to null');
|
||||
|
||||
// Contrast: non-empty string is stored as-is
|
||||
aliases.updateAliasTitle('r115-alias', 'New Title');
|
||||
const withTitle = aliases.resolveAlias('r115-alias');
|
||||
assert.strictEqual(withTitle.title, 'New Title', 'Non-empty string stored as-is');
|
||||
|
||||
// null explicitly clears title
|
||||
aliases.updateAliasTitle('r115-alias', null);
|
||||
const cleared = aliases.resolveAlias('r115-alias');
|
||||
assert.strictEqual(cleared.title, null, 'null clears title');
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Summary
|
||||
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
|
||||
@@ -2055,6 +2055,62 @@ file.ts
|
||||
'Trailing whitespace should be trimmed');
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ── Round 115: parseSessionMetadata with CRLF line endings — section boundaries differ ──
|
||||
console.log('\nRound 115: parseSessionMetadata (CRLF line endings — \\r\\n vs \\n in section regexes):');
|
||||
if (test('parseSessionMetadata handles CRLF content — title trimmed, sections may over-capture', () => {
|
||||
// Title regex /^#\s+(.+)$/m: . matches \r, trim() removes it
|
||||
const crlfTitle = '# My Session\r\n\r\n**Date:** 2026-01-15';
|
||||
const titleMeta = sessionManager.parseSessionMetadata(crlfTitle);
|
||||
assert.strictEqual(titleMeta.title, 'My Session',
|
||||
'Title should be trimmed (\\r removed by .trim())');
|
||||
assert.strictEqual(titleMeta.date, '2026-01-15',
|
||||
'Date extraction unaffected by CRLF');
|
||||
|
||||
// Completed section with CRLF: regex ### Completed\s*\n works because \s* matches \r
|
||||
// But the boundary (?=###|\n\n|$) — \n\n won't match \r\n\r\n
|
||||
const crlfSections = [
|
||||
'# Session\r\n',
|
||||
'\r\n',
|
||||
'### Completed\r\n',
|
||||
'- [x] Task A\r\n',
|
||||
'- [x] Task B\r\n',
|
||||
'\r\n',
|
||||
'### In Progress\r\n',
|
||||
'- [ ] Task C\r\n'
|
||||
].join('');
|
||||
|
||||
const sectionMeta = sessionManager.parseSessionMetadata(crlfSections);
|
||||
|
||||
// \s* in "### Completed\s*\n" matches the \r before \n, so section header matches
|
||||
assert.ok(sectionMeta.completed.length >= 2,
|
||||
'Should find at least 2 completed items (\\s* consumes \\r before \\n)');
|
||||
assert.ok(sectionMeta.completed.includes('Task A'), 'Should find Task A');
|
||||
assert.ok(sectionMeta.completed.includes('Task B'), 'Should find Task B');
|
||||
|
||||
// In Progress section: \n\n boundary fails on \r\n\r\n, so the lazy [\s\S]*?
|
||||
// stops at ### instead — this still works because ### is present
|
||||
assert.ok(sectionMeta.inProgress.length >= 1,
|
||||
'Should find at least 1 in-progress item');
|
||||
assert.ok(sectionMeta.inProgress.includes('Task C'), 'Should find Task C');
|
||||
|
||||
// Edge case: CRLF content with NO section headers after Completed —
|
||||
// \n\n boundary fails, so [\s\S]*? falls through to $ (end of string)
|
||||
const crlfNoNextSection = [
|
||||
'# Session\r\n',
|
||||
'\r\n',
|
||||
'### Completed\r\n',
|
||||
'- [x] Only task\r\n',
|
||||
'\r\n',
|
||||
'Some trailing text\r\n'
|
||||
].join('');
|
||||
|
||||
const noNextMeta = sessionManager.parseSessionMetadata(crlfNoNextSection);
|
||||
// Without a ### boundary, the \n\n lookahead fails on \r\n\r\n,
|
||||
// so [\s\S]*? extends to $ and captures everything including trailing text
|
||||
assert.ok(noNextMeta.completed.length >= 1,
|
||||
'Should find at least 1 completed item in CRLF-only content');
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Summary
|
||||
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
|
||||
@@ -1799,6 +1799,40 @@ function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ── Round 115: countInFile with empty string pattern — matches at every position boundary ──
|
||||
console.log('\nRound 115: countInFile (empty string pattern — matches at every zero-width position):');
|
||||
if (test('countInFile with empty string pattern returns content.length + 1 (matches between every char)', () => {
|
||||
const tmpDir = fs.mkdtempSync(path.join(utils.getTempDir(), 'r115-empty-pattern-'));
|
||||
const testFile = path.join(tmpDir, 'test.txt');
|
||||
try {
|
||||
// "hello" is 5 chars → 6 zero-width positions: |h|e|l|l|o|
|
||||
fs.writeFileSync(testFile, 'hello');
|
||||
const count = utils.countInFile(testFile, '');
|
||||
assert.strictEqual(count, 6,
|
||||
'Empty string pattern creates /(?:)/g which matches at 6 position boundaries in "hello"');
|
||||
|
||||
// Empty file → "" has 1 zero-width position (the empty string itself)
|
||||
fs.writeFileSync(testFile, '');
|
||||
const emptyCount = utils.countInFile(testFile, '');
|
||||
assert.strictEqual(emptyCount, 1,
|
||||
'Empty file still has 1 zero-width position boundary');
|
||||
|
||||
// Single char → 2 positions: |a|
|
||||
fs.writeFileSync(testFile, 'a');
|
||||
const singleCount = utils.countInFile(testFile, '');
|
||||
assert.strictEqual(singleCount, 2,
|
||||
'Single character file has 2 position boundaries');
|
||||
|
||||
// Newlines count as characters too
|
||||
fs.writeFileSync(testFile, 'a\nb');
|
||||
const newlineCount = utils.countInFile(testFile, '');
|
||||
assert.strictEqual(newlineCount, 4,
|
||||
'"a\\nb" is 3 chars → 4 position boundaries');
|
||||
} finally {
|
||||
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Summary
|
||||
console.log('\n=== Test Results ===');
|
||||
console.log(`Passed: ${passed}`);
|
||||
|
||||
Reference in New Issue
Block a user