mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 21:53:28 +08:00
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:
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user