mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-02 15:13:28 +08:00
test: add Round 120 tests for replaceInFile empty search, setAlias length boundary, and notes extraction
- replaceInFile: empty string search — replace prepends at pos 0, replaceAll inserts between every char - setAlias: 128-char alias accepted (boundary), 129-char rejected (> 128 check) - parseSessionMetadata: "Notes for Next Session" extraction — last section, empty, ### boundary, markdown Total tests: 920
This commit is contained in:
@@ -1647,6 +1647,37 @@ function runTests() {
|
||||
assert.strictEqual(validResult.success, true, 'Non-reserved name should succeed');
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ── Round 120: setAlias max length boundary — 128 accepted, 129 rejected ──
|
||||
console.log('\nRound 120: setAlias (max alias length boundary — 128 ok, 129 rejected):');
|
||||
if (test('setAlias accepts exactly 128-char alias name but rejects 129 chars (> 128 boundary)', () => {
|
||||
resetAliases();
|
||||
|
||||
// 128 characters — exactly at limit (alias.length > 128 is false)
|
||||
const name128 = 'a'.repeat(128);
|
||||
const result128 = aliases.setAlias(name128, '/path/to/session');
|
||||
assert.strictEqual(result128.success, true,
|
||||
'128-char alias should be accepted (128 > 128 is false)');
|
||||
|
||||
// 129 characters — just over limit
|
||||
const name129 = 'a'.repeat(129);
|
||||
const result129 = aliases.setAlias(name129, '/path/to/session');
|
||||
assert.strictEqual(result129.success, false,
|
||||
'129-char alias should be rejected (129 > 128 is true)');
|
||||
assert.ok(result129.error.includes('128'),
|
||||
'Error should mention the 128 character limit');
|
||||
|
||||
// 1 character — minimum valid
|
||||
const name1 = 'x';
|
||||
const result1 = aliases.setAlias(name1, '/path/to/session');
|
||||
assert.strictEqual(result1.success, true,
|
||||
'Single character alias should be accepted');
|
||||
|
||||
// Verify the 128-char alias was actually stored
|
||||
const resolved = aliases.resolveAlias(name128);
|
||||
assert.ok(resolved, '128-char alias should be resolvable');
|
||||
assert.strictEqual(resolved.sessionPath, '/path/to/session');
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Summary
|
||||
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
|
||||
@@ -2246,6 +2246,44 @@ file.ts
|
||||
'Empty code block should result in empty context (trim of empty)');
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ── Round 120: parseSessionMetadata "Notes for Next Session" extraction edge cases ──
|
||||
console.log('\nRound 120: parseSessionMetadata ("Notes for Next Session" — extraction edge cases):');
|
||||
if (test('parseSessionMetadata extracts notes section — last section, empty, followed by ###', () => {
|
||||
// Notes as the last section (no ### or \n\n after)
|
||||
const lastSection = '# Session\n\n### Notes for Next Session\nRemember to review PR #42\nAlso check CI status';
|
||||
const lastMeta = sessionManager.parseSessionMetadata(lastSection);
|
||||
assert.strictEqual(lastMeta.notes, 'Remember to review PR #42\nAlso check CI status',
|
||||
'Notes as last section should capture everything to end of string via $ anchor');
|
||||
assert.strictEqual(lastMeta.hasNotes, undefined,
|
||||
'hasNotes is not a direct property of parseSessionMetadata result');
|
||||
|
||||
// Notes followed by another ### section
|
||||
const withNext = '# Session\n\n### Notes for Next Session\nImportant note\n### Context to Load\n```\nfiles\n```';
|
||||
const nextMeta = sessionManager.parseSessionMetadata(withNext);
|
||||
assert.strictEqual(nextMeta.notes, 'Important note',
|
||||
'Notes should stop at next ### header');
|
||||
|
||||
// Notes followed by \n\n (double newline)
|
||||
const withDoubleNewline = '# Session\n\n### Notes for Next Session\nNote here\n\nSome other text';
|
||||
const dblMeta = sessionManager.parseSessionMetadata(withDoubleNewline);
|
||||
assert.strictEqual(dblMeta.notes, 'Note here',
|
||||
'Notes should stop at \\n\\n boundary');
|
||||
|
||||
// Empty notes section (header only, followed by \n\n)
|
||||
const emptyNotes = '# Session\n\n### Notes for Next Session\n\n### Other Section';
|
||||
const emptyMeta = sessionManager.parseSessionMetadata(emptyNotes);
|
||||
assert.strictEqual(emptyMeta.notes, '',
|
||||
'Empty notes section should result in empty string after trim');
|
||||
|
||||
// Notes with markdown formatting
|
||||
const markdownNotes = '# Session\n\n### Notes for Next Session\n- [ ] Review **important** PR\n- [x] Check `config.js`\n\n### Done';
|
||||
const mdMeta = sessionManager.parseSessionMetadata(markdownNotes);
|
||||
assert.ok(mdMeta.notes.includes('**important**'),
|
||||
'Markdown bold should be preserved in notes');
|
||||
assert.ok(mdMeta.notes.includes('`config.js`'),
|
||||
'Markdown code should be preserved in notes');
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Summary
|
||||
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
|
||||
@@ -2017,6 +2017,44 @@ function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ── Round 120: replaceInFile with empty string search — prepend vs insert-between-every-char ──
|
||||
console.log('\nRound 120: replaceInFile (empty string search — replace vs replaceAll dramatic difference):');
|
||||
if (test('replaceInFile with empty search: replace prepends at pos 0; replaceAll inserts between every char', () => {
|
||||
const tmpDir = fs.mkdtempSync(path.join(utils.getTempDir(), 'r120-empty-search-'));
|
||||
const testFile = path.join(tmpDir, 'test.txt');
|
||||
try {
|
||||
// Without options.all: .replace('', 'X') prepends at position 0
|
||||
fs.writeFileSync(testFile, 'hello');
|
||||
utils.replaceInFile(testFile, '', 'X');
|
||||
const prepended = utils.readFile(testFile);
|
||||
assert.strictEqual(prepended, 'Xhello',
|
||||
'replace("", "X") should prepend X at position 0 only');
|
||||
|
||||
// With options.all: .replaceAll('', 'X') inserts between every character
|
||||
fs.writeFileSync(testFile, 'hello');
|
||||
utils.replaceInFile(testFile, '', 'X', { all: true });
|
||||
const insertedAll = utils.readFile(testFile);
|
||||
assert.strictEqual(insertedAll, 'XhXeXlXlXoX',
|
||||
'replaceAll("", "X") inserts X at every position boundary');
|
||||
|
||||
// Empty file + empty search
|
||||
fs.writeFileSync(testFile, '');
|
||||
utils.replaceInFile(testFile, '', 'X');
|
||||
const emptyReplace = utils.readFile(testFile);
|
||||
assert.strictEqual(emptyReplace, 'X',
|
||||
'Empty content + empty search: single insertion at position 0');
|
||||
|
||||
// Empty file + empty search + all
|
||||
fs.writeFileSync(testFile, '');
|
||||
utils.replaceInFile(testFile, '', 'X', { all: true });
|
||||
const emptyAll = utils.readFile(testFile);
|
||||
assert.strictEqual(emptyAll, 'X',
|
||||
'Empty content + replaceAll("", "X"): single position boundary → "X"');
|
||||
} 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