From 2753db3a480fcc946ecb14fbc8ad06202b728665 Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Fri, 13 Feb 2026 18:30:42 -0800 Subject: [PATCH] test: add 3 edge-case tests for findFiles dot escaping, listAliases limit falsy values, getSessionById old format Round 122: Tests for findFiles glob dot escaping (*.txt must not match filetxt), listAliases limit=0/negative/NaN returning all due to JS falsy check, and getSessionById matching old YYYY-MM-DD-session.tmp filenames via noIdMatch path. Total: 926 tests, all passing. --- tests/lib/session-aliases.test.js | 39 +++++++++++++++++++++++++++ tests/lib/session-manager.test.js | 44 +++++++++++++++++++++++++++++++ tests/lib/utils.test.js | 24 +++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/tests/lib/session-aliases.test.js b/tests/lib/session-aliases.test.js index f7cbfb7e..7a4dc126 100644 --- a/tests/lib/session-aliases.test.js +++ b/tests/lib/session-aliases.test.js @@ -1713,6 +1713,45 @@ function runTests() { assert.strictEqual(validResult.success, true, 'Valid string path should succeed'); })) passed++; else failed++; + // ── Round 122: listAliases limit edge cases — limit=0, negative, NaN bypassed (JS falsy) ── + console.log('\nRound 122: listAliases (limit edge cases — 0/negative/NaN are falsy, return all):'); + if (test('listAliases limit=0 returns all aliases because 0 is falsy in JS (no slicing)', () => { + resetAliases(); + aliases.setAlias('alias-a', '/path/a'); + aliases.setAlias('alias-b', '/path/b'); + aliases.setAlias('alias-c', '/path/c'); + + // limit=0: 0 is falsy → `if (0 && 0 > 0)` short-circuits → no slicing → ALL returned + const zeroResult = aliases.listAliases({ limit: 0 }); + assert.strictEqual(zeroResult.length, 3, + 'limit=0 should return ALL aliases (0 is falsy in JS)'); + + // limit=-1: -1 is truthy but -1 > 0 is false → no slicing → ALL returned + const negResult = aliases.listAliases({ limit: -1 }); + assert.strictEqual(negResult.length, 3, + 'limit=-1 should return ALL aliases (-1 > 0 is false)'); + + // limit=NaN: NaN is falsy → no slicing → ALL returned + const nanResult = aliases.listAliases({ limit: NaN }); + assert.strictEqual(nanResult.length, 3, + 'limit=NaN should return ALL aliases (NaN is falsy)'); + + // limit=1: normal case — returns exactly 1 + const oneResult = aliases.listAliases({ limit: 1 }); + assert.strictEqual(oneResult.length, 1, + 'limit=1 should return exactly 1 alias'); + + // limit=2: returns exactly 2 + const twoResult = aliases.listAliases({ limit: 2 }); + assert.strictEqual(twoResult.length, 2, + 'limit=2 should return exactly 2 aliases'); + + // limit=100 (more than total): returns all 3 + const bigResult = aliases.listAliases({ limit: 100 }); + assert.strictEqual(bigResult.length, 3, + 'limit > total should return all aliases'); + })) passed++; else failed++; + // Summary console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`); process.exit(failed > 0 ? 1 : 0); diff --git a/tests/lib/session-manager.test.js b/tests/lib/session-manager.test.js index 72657bd5..ea468f16 100644 --- a/tests/lib/session-manager.test.js +++ b/tests/lib/session-manager.test.js @@ -2324,6 +2324,50 @@ file.ts 'Loose [\\d:]+ regex captures any digits-and-colons combination'); })) passed++; else failed++; + // ── Round 122: getSessionById old format (no-id) — noIdMatch path ── + console.log('\nRound 122: getSessionById (old format no-id — date-only filename match):'); + if (test('getSessionById matches old format YYYY-MM-DD-session.tmp via noIdMatch path', () => { + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'r122-old-format-')); + const origHome = process.env.HOME; + const origDir = process.env.CLAUDE_DIR; + try { + // Set up isolated environment + const claudeDir = path.join(tmpDir, '.claude'); + const sessionsDir = path.join(claudeDir, 'sessions'); + fs.mkdirSync(sessionsDir, { recursive: true }); + process.env.HOME = tmpDir; + delete process.env.CLAUDE_DIR; + + // Clear require cache for fresh module with new HOME + delete require.cache[require.resolve('../../scripts/lib/utils')]; + delete require.cache[require.resolve('../../scripts/lib/session-manager')]; + const freshSM = require('../../scripts/lib/session-manager'); + + // Create old-format session file (no short ID) + const oldFile = path.join(sessionsDir, '2026-01-15-session.tmp'); + fs.writeFileSync(oldFile, '# Old Format Session\n\n**Date:** 2026-01-15\n'); + + // Search by date — triggers noIdMatch path + const result = freshSM.getSessionById('2026-01-15'); + assert.ok(result, 'Should find old-format session by date string'); + assert.strictEqual(result.shortId, 'no-id', + 'Old format should have shortId "no-id"'); + assert.strictEqual(result.date, '2026-01-15'); + assert.strictEqual(result.filename, '2026-01-15-session.tmp'); + + // Search by non-matching date — should not find + const noResult = freshSM.getSessionById('2026-01-16'); + assert.strictEqual(noResult, null, + 'Non-matching date should return null'); + } finally { + process.env.HOME = origHome; + if (origDir) process.env.CLAUDE_DIR = origDir; + delete require.cache[require.resolve('../../scripts/lib/utils')]; + delete require.cache[require.resolve('../../scripts/lib/session-manager')]; + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + })) passed++; else failed++; + // Summary console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`); process.exit(failed > 0 ? 1 : 0); diff --git a/tests/lib/utils.test.js b/tests/lib/utils.test.js index d017b46e..91ec8069 100644 --- a/tests/lib/utils.test.js +++ b/tests/lib/utils.test.js @@ -2086,6 +2086,30 @@ function runTests() { } })) passed++; else failed++; + // ── Round 122: findFiles dot extension escaping — *.txt must not match filetxt ── + console.log('\nRound 122: findFiles (dot escaping — *.txt matches file.txt but not filetxt):'); + if (test('findFiles escapes dots in glob pattern so *.txt only matches literal .txt extension', () => { + const tmpDir = fs.mkdtempSync(path.join(utils.getTempDir(), 'r122-dot-escape-')); + try { + fs.writeFileSync(path.join(tmpDir, 'file.txt'), 'a'); + fs.writeFileSync(path.join(tmpDir, 'filetxt'), 'b'); + fs.writeFileSync(path.join(tmpDir, 'file.txtx'), 'c'); + fs.writeFileSync(path.join(tmpDir, 'notes.txt'), 'd'); + + const results = utils.findFiles(tmpDir, '*.txt'); + const names = results.map(r => path.basename(r.path)).sort(); + + assert.ok(names.includes('file.txt'), 'Should match file.txt'); + assert.ok(names.includes('notes.txt'), 'Should match notes.txt'); + assert.ok(!names.includes('filetxt'), + 'Should NOT match filetxt (dot is escaped to literal, not wildcard)'); + assert.ok(!names.includes('file.txtx'), + 'Should NOT match file.txtx ($ anchor requires exact end)'); + } finally { + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + })) passed++; else failed++; + // Summary console.log('\n=== Test Results ==='); console.log(`Passed: ${passed}`);