test: add Round 119 tests for appendFile type safety, renameAlias reserved names, and context extraction

- appendFile: null/undefined/number content throws TypeError (no try/catch like writeFile)
- renameAlias: reserved names rejected for newAlias (parallel check to setAlias, case-insensitive)
- parseSessionMetadata: "Context to Load" code block extraction — missing close, nested blocks, empty

Total tests: 917
This commit is contained in:
Affaan Mustafa
2026-02-13 18:21:39 -08:00
parent 25c5d58c44
commit df2d3a6d54
3 changed files with 133 additions and 0 deletions

View File

@@ -1617,6 +1617,36 @@ function runTests() {
'Non-reserved name should succeed');
})) passed++; else failed++;
// ── Round 119: renameAlias with reserved newAlias name — parallel reserved check ──
console.log('\nRound 119: renameAlias (reserved newAlias name — parallel check to setAlias):');
if (test('renameAlias rejects reserved names for newAlias (same reserved list as setAlias)', () => {
resetAliases();
aliases.setAlias('my-alias', '/path/to/session');
// Rename to reserved name 'list' — should fail
const listResult = aliases.renameAlias('my-alias', 'list');
assert.strictEqual(listResult.success, false, '"list" should be rejected');
assert.ok(listResult.error.includes('reserved'),
'Error should mention "reserved"');
// Rename to reserved name 'help' (uppercase) — should fail
const helpResult = aliases.renameAlias('my-alias', 'Help');
assert.strictEqual(helpResult.success, false, '"Help" should be rejected');
// Rename to reserved name 'delete' — should fail
const deleteResult = aliases.renameAlias('my-alias', 'DELETE');
assert.strictEqual(deleteResult.success, false, '"DELETE" should be rejected');
// Verify alias is unchanged
const resolved = aliases.resolveAlias('my-alias');
assert.ok(resolved, 'Original alias should still exist after failed renames');
assert.strictEqual(resolved.sessionPath, '/path/to/session');
// Valid rename works
const validResult = aliases.renameAlias('my-alias', 'new-valid-name');
assert.strictEqual(validResult.success, true, 'Non-reserved name should succeed');
})) passed++; else failed++;
// Summary
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
process.exit(failed > 0 ? 1 : 0);

View File

@@ -2186,6 +2186,66 @@ file.ts
assert.strictEqual(hexLower.shortId, 'a1b2c3d4');
})) passed++; else failed++;
// ── Round 119: parseSessionMetadata "Context to Load" code block extraction ──
console.log('\nRound 119: parseSessionMetadata ("Context to Load" — code block extraction edge cases):');
if (test('parseSessionMetadata extracts Context to Load from code block, handles missing/nested blocks', () => {
// Valid context extraction
const validContent = [
'# Session\n\n',
'### Context to Load\n',
'```\n',
'file1.js\n',
'file2.ts\n',
'```\n'
].join('');
const validMeta = sessionManager.parseSessionMetadata(validContent);
assert.strictEqual(validMeta.context, 'file1.js\nfile2.ts',
'Should extract content between ``` markers and trim');
// Missing closing backticks — regex doesn't match, context stays empty
const noClose = [
'# Session\n\n',
'### Context to Load\n',
'```\n',
'file1.js\n',
'file2.ts\n'
].join('');
const noCloseMeta = sessionManager.parseSessionMetadata(noClose);
assert.strictEqual(noCloseMeta.context, '',
'Missing closing ``` should result in empty context (regex no match)');
// No code block after header — just plain text
const noBlock = [
'# Session\n\n',
'### Context to Load\n',
'file1.js\n',
'file2.ts\n'
].join('');
const noBlockMeta = sessionManager.parseSessionMetadata(noBlock);
assert.strictEqual(noBlockMeta.context, '',
'Plain text without ``` should not be captured as context');
// Nested code block — lazy [\s\S]*? stops at first ```
const nested = [
'# Session\n\n',
'### Context to Load\n',
'```\n',
'first block\n',
'```\n',
'second block\n',
'```\n'
].join('');
const nestedMeta = sessionManager.parseSessionMetadata(nested);
assert.strictEqual(nestedMeta.context, 'first block',
'Lazy quantifier should stop at first closing ``` (not greedy)');
// Empty code block
const emptyBlock = '# Session\n\n### Context to Load\n```\n```\n';
const emptyMeta = sessionManager.parseSessionMetadata(emptyBlock);
assert.strictEqual(emptyMeta.context, '',
'Empty code block should result in empty context (trim of empty)');
})) passed++; else failed++;
// Summary
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
process.exit(failed > 0 ? 1 : 0);

View File

@@ -1974,6 +1974,49 @@ function runTests() {
}
})) passed++; else failed++;
// ── Round 119: appendFile with non-string content — TypeError propagates (no try/catch) ──
console.log('\nRound 119: appendFile (non-string content — TypeError propagates like writeFile):');
if (test('appendFile with null/number content throws TypeError (no try/catch wrapper)', () => {
const tmpDir = fs.mkdtempSync(path.join(utils.getTempDir(), 'r119-appendfile-type-'));
const testFile = path.join(tmpDir, 'test.txt');
try {
// Create file with initial content
fs.writeFileSync(testFile, 'initial');
// null content → TypeError from fs.appendFileSync
assert.throws(
() => utils.appendFile(testFile, null),
(err) => err instanceof TypeError,
'appendFile(path, null) should throw TypeError'
);
// undefined content → TypeError
assert.throws(
() => utils.appendFile(testFile, undefined),
(err) => err instanceof TypeError,
'appendFile(path, undefined) should throw TypeError'
);
// number content → TypeError
assert.throws(
() => utils.appendFile(testFile, 42),
(err) => err instanceof TypeError,
'appendFile(path, 42) should throw TypeError'
);
// Verify original content is unchanged after failed appends
assert.strictEqual(utils.readFile(testFile), 'initial',
'File content should be unchanged after failed appends');
// Contrast: string append works
utils.appendFile(testFile, ' appended');
assert.strictEqual(utils.readFile(testFile), 'initial appended',
'String append should work correctly');
} finally {
fs.rmSync(tmpDir, { recursive: true, force: true });
}
})) passed++; else failed++;
// Summary
console.log('\n=== Test Results ===');
console.log(`Passed: ${passed}`);