test: add 15 tests for session-manager and session-aliases edge cases

Cover 30-day month validation (Sep/Nov 31 rejection), getSessionStats
path heuristic with multiline content, combined date+search+pagination
in getAllSessions, ambiguous prefix matching in getSessionById, unclosed
code fence in parseSessionMetadata, empty checklist item behavior,
reserved name case sensitivity (LIST/Help/Set), negative limit in
listAliases, and undefined title in setAlias.
This commit is contained in:
Affaan Mustafa
2026-02-13 02:54:23 -08:00
parent 6bbcbec23d
commit d903053830
2 changed files with 133 additions and 0 deletions

View File

@@ -636,6 +636,52 @@ function runTests() {
assert.strictEqual(result[0].name, 'partial');
})) passed++; else failed++;
// ── Round 26 tests ──
console.log('\nsetAlias (reserved names case sensitivity):');
if (test('rejects uppercase reserved name LIST', () => {
resetAliases();
const result = aliases.setAlias('LIST', '/path');
assert.strictEqual(result.success, false);
assert.ok(result.error.includes('reserved'));
})) passed++; else failed++;
if (test('rejects mixed-case reserved name Help', () => {
resetAliases();
const result = aliases.setAlias('Help', '/path');
assert.strictEqual(result.success, false);
assert.ok(result.error.includes('reserved'));
})) passed++; else failed++;
if (test('rejects mixed-case reserved name Set', () => {
resetAliases();
const result = aliases.setAlias('Set', '/path');
assert.strictEqual(result.success, false);
assert.ok(result.error.includes('reserved'));
})) passed++; else failed++;
console.log('\nlistAliases (negative limit):');
if (test('negative limit does not truncate results', () => {
resetAliases();
aliases.setAlias('one', '/path1');
aliases.setAlias('two', '/path2');
const list = aliases.listAliases({ limit: -5 });
// -5 fails the `limit > 0` check, so no slicing happens
assert.strictEqual(list.length, 2, 'Negative limit should not apply');
})) passed++; else failed++;
console.log('\nsetAlias (undefined title):');
if (test('undefined title becomes null (same as explicit null)', () => {
resetAliases();
const result = aliases.setAlias('undef-title', '/path', undefined);
assert.strictEqual(result.success, true);
const resolved = aliases.resolveAlias('undef-title');
assert.strictEqual(resolved.title, null, 'undefined title should become null');
})) passed++; else failed++;
// Cleanup — restore both HOME and USERPROFILE (Windows)
process.env.HOME = origHome;
if (origUserProfile !== undefined) {

View File

@@ -851,6 +851,93 @@ src/main.ts
assert.strictEqual(stats.hasContext, false);
})) passed++; else failed++;
// ── Round 26 tests ──
console.log('\nparseSessionFilename (30-day month validation):');
if (test('rejects Sep 31 (September has 30 days)', () => {
const result = sessionManager.parseSessionFilename('2026-09-31-abcd1234-session.tmp');
assert.strictEqual(result, null, 'Sep 31 does not exist');
})) passed++; else failed++;
if (test('rejects Nov 31 (November has 30 days)', () => {
const result = sessionManager.parseSessionFilename('2026-11-31-abcd1234-session.tmp');
assert.strictEqual(result, null, 'Nov 31 does not exist');
})) passed++; else failed++;
if (test('accepts Sep 30 (valid 30-day month boundary)', () => {
const result = sessionManager.parseSessionFilename('2026-09-30-abcd1234-session.tmp');
assert.ok(result, 'Sep 30 is valid');
assert.strictEqual(result.date, '2026-09-30');
})) passed++; else failed++;
console.log('\ngetSessionStats (path heuristic edge cases):');
if (test('multiline content ending with .tmp is treated as content', () => {
const content = 'Line 1\nLine 2\nDownload file.tmp';
const stats = sessionManager.getSessionStats(content);
// Has newlines so looksLikePath is false → treated as content
assert.strictEqual(stats.lineCount, 3, 'Should count 3 lines');
})) passed++; else failed++;
if (test('single-line content not starting with / treated as content', () => {
const content = 'some random text.tmp';
const stats = sessionManager.getSessionStats(content);
assert.strictEqual(stats.lineCount, 1, 'Should treat as content, not a path');
})) passed++; else failed++;
console.log('\ngetAllSessions (combined filters):');
if (test('combines date filter + search filter + pagination', () => {
// We have 2026-02-01-ijkl9012 and 2026-02-01-mnop3456 with date 2026-02-01
const result = sessionManager.getAllSessions({
date: '2026-02-01',
search: 'ijkl',
limit: 10
});
assert.strictEqual(result.total, 1, 'Only one session matches both date and search');
assert.strictEqual(result.sessions[0].shortId, 'ijkl9012');
})) passed++; else failed++;
if (test('date filter + offset beyond matches returns empty', () => {
const result = sessionManager.getAllSessions({
date: '2026-02-01',
offset: 100,
limit: 10
});
assert.strictEqual(result.sessions.length, 0);
assert.strictEqual(result.total, 2, 'Two sessions match the date');
assert.strictEqual(result.hasMore, false);
})) passed++; else failed++;
console.log('\ngetSessionById (ambiguous prefix):');
if (test('returns first match when multiple sessions share a prefix', () => {
// Sessions with IDs abcd1234 and efgh5678 exist
// 'e' should match efgh5678 (only match)
const result = sessionManager.getSessionById('efgh');
assert.ok(result, 'Should find session by prefix');
assert.strictEqual(result.shortId, 'efgh5678');
})) passed++; else failed++;
console.log('\nparseSessionMetadata (edge cases):');
if (test('handles unclosed code fence in Context section', () => {
const content = '# Session\n\n### Context to Load\n```\nsrc/index.ts\n';
const meta = sessionManager.parseSessionMetadata(content);
// Regex requires closing ```, so no context should be extracted
assert.strictEqual(meta.context, '', 'Unclosed code fence should not extract context');
})) passed++; else failed++;
if (test('handles empty task text in checklist items', () => {
const content = '# Session\n\n### Completed\n- [x] \n- [x] Real task\n';
const meta = sessionManager.parseSessionMetadata(content);
// \s* in the regex bridges across newlines, collapsing the empty
// task + next task into a single match. This is an edge case —
// real sessions don't have empty checklist items.
assert.strictEqual(meta.completed.length, 1);
})) passed++; else failed++;
// Cleanup — restore both HOME and USERPROFILE (Windows)
process.env.HOME = origHome;
if (origUserProfile !== undefined) {