From e50b05384a338e7f11017e6e706b894665c755ed Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Fri, 13 Feb 2026 18:25:56 -0800 Subject: [PATCH] test: add Round 121 tests for findFiles ? glob, setAlias path validation, and time metadata extraction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - findFiles: ? glob pattern matches single character only (converted to . regex) - setAlias: rejects null, empty, whitespace-only, and non-string sessionPath values - parseSessionMetadata: Started/Last Updated time extraction — present, missing, loose regex Total tests: 923 --- tests/lib/session-aliases.test.js | 35 +++++++++++++++++++++++++++ tests/lib/session-manager.test.js | 40 +++++++++++++++++++++++++++++++ tests/lib/utils.test.js | 31 ++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/tests/lib/session-aliases.test.js b/tests/lib/session-aliases.test.js index bc4de4b4..f7cbfb7e 100644 --- a/tests/lib/session-aliases.test.js +++ b/tests/lib/session-aliases.test.js @@ -1678,6 +1678,41 @@ function runTests() { assert.strictEqual(resolved.sessionPath, '/path/to/session'); })) passed++; else failed++; + // ── Round 121: setAlias sessionPath validation — null, empty, whitespace, non-string ── + console.log('\nRound 121: setAlias (sessionPath validation — null, empty, whitespace, non-string):'); + if (test('setAlias rejects invalid sessionPath: null, empty, whitespace-only, and non-string types', () => { + resetAliases(); + + // null sessionPath → falsy → rejected + const nullResult = aliases.setAlias('test-alias', null); + assert.strictEqual(nullResult.success, false, 'null path should fail'); + assert.ok(nullResult.error.includes('empty'), 'Error should mention empty'); + + // undefined sessionPath → falsy → rejected + const undefResult = aliases.setAlias('test-alias', undefined); + assert.strictEqual(undefResult.success, false, 'undefined path should fail'); + + // empty string → falsy → rejected + const emptyResult = aliases.setAlias('test-alias', ''); + assert.strictEqual(emptyResult.success, false, 'Empty string path should fail'); + + // whitespace-only → passes falsy check but trim().length === 0 → rejected + const wsResult = aliases.setAlias('test-alias', ' '); + assert.strictEqual(wsResult.success, false, 'Whitespace-only path should fail'); + + // number → typeof !== 'string' → rejected + const numResult = aliases.setAlias('test-alias', 42); + assert.strictEqual(numResult.success, false, 'Number path should fail'); + + // boolean → typeof !== 'string' → rejected + const boolResult = aliases.setAlias('test-alias', true); + assert.strictEqual(boolResult.success, false, 'Boolean path should fail'); + + // Valid path works + const validResult = aliases.setAlias('test-alias', '/valid/path'); + assert.strictEqual(validResult.success, true, 'Valid string path should succeed'); + })) 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 551a794c..72657bd5 100644 --- a/tests/lib/session-manager.test.js +++ b/tests/lib/session-manager.test.js @@ -2284,6 +2284,46 @@ file.ts 'Markdown code should be preserved in notes'); })) passed++; else failed++; + // ── Round 121: parseSessionMetadata Started/Last Updated time extraction ── + console.log('\nRound 121: parseSessionMetadata (Started/Last Updated time extraction):'); + if (test('parseSessionMetadata extracts Started and Last Updated times from markdown', () => { + // Standard format + const standard = '# Session\n\n**Date:** 2026-01-15\n**Started:** 14:30\n**Last Updated:** 16:45'; + const stdMeta = sessionManager.parseSessionMetadata(standard); + assert.strictEqual(stdMeta.started, '14:30', 'Should extract started time'); + assert.strictEqual(stdMeta.lastUpdated, '16:45', 'Should extract last updated time'); + + // With seconds in time + const withSec = '# Session\n\n**Started:** 14:30:00\n**Last Updated:** 16:45:59'; + const secMeta = sessionManager.parseSessionMetadata(withSec); + assert.strictEqual(secMeta.started, '14:30:00', 'Should capture seconds too ([\\d:]+)'); + assert.strictEqual(secMeta.lastUpdated, '16:45:59'); + + // Missing Started but has Last Updated + const noStarted = '# Session\n\n**Last Updated:** 09:00'; + const noStartMeta = sessionManager.parseSessionMetadata(noStarted); + assert.strictEqual(noStartMeta.started, null, 'Missing Started should be null'); + assert.strictEqual(noStartMeta.lastUpdated, '09:00', 'Last Updated should still be extracted'); + + // Missing Last Updated but has Started + const noUpdated = '# Session\n\n**Started:** 08:15'; + const noUpdMeta = sessionManager.parseSessionMetadata(noUpdated); + assert.strictEqual(noUpdMeta.started, '08:15', 'Started should be extracted'); + assert.strictEqual(noUpdMeta.lastUpdated, null, 'Missing Last Updated should be null'); + + // Neither present + const neither = '# Session\n\nJust some text'; + const neitherMeta = sessionManager.parseSessionMetadata(neither); + assert.strictEqual(neitherMeta.started, null, 'No Started in content → null'); + assert.strictEqual(neitherMeta.lastUpdated, null, 'No Last Updated in content → null'); + + // Loose regex: edge case with extra colons ([\d:]+ matches any digit-colon combo) + const loose = '# Session\n\n**Started:** 1:2:3:4'; + const looseMeta = sessionManager.parseSessionMetadata(loose); + assert.strictEqual(looseMeta.started, '1:2:3:4', + 'Loose [\\d:]+ regex captures any digits-and-colons combination'); + })) 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 cdeb6104..d017b46e 100644 --- a/tests/lib/utils.test.js +++ b/tests/lib/utils.test.js @@ -2055,6 +2055,37 @@ function runTests() { } })) passed++; else failed++; + // ── Round 121: findFiles with ? glob pattern — single character wildcard ── + console.log('\nRound 121: findFiles (? glob pattern — converted to . regex for single char match):'); + if (test('findFiles with ? glob matches single character only — test?.txt matches test1 but not test12', () => { + const tmpDir = fs.mkdtempSync(path.join(utils.getTempDir(), 'r121-glob-question-')); + try { + // Create test files + fs.writeFileSync(path.join(tmpDir, 'test1.txt'), 'a'); + fs.writeFileSync(path.join(tmpDir, 'testA.txt'), 'b'); + fs.writeFileSync(path.join(tmpDir, 'test12.txt'), 'c'); + fs.writeFileSync(path.join(tmpDir, 'test.txt'), 'd'); + + // ? matches exactly one character + const results = utils.findFiles(tmpDir, 'test?.txt'); + const names = results.map(r => path.basename(r.path)).sort(); + assert.ok(names.includes('test1.txt'), 'Should match test1.txt (? = single digit)'); + assert.ok(names.includes('testA.txt'), 'Should match testA.txt (? = single letter)'); + assert.ok(!names.includes('test12.txt'), 'Should NOT match test12.txt (12 is two chars)'); + assert.ok(!names.includes('test.txt'), 'Should NOT match test.txt (no char for ?)'); + + // Multiple ? marks + fs.writeFileSync(path.join(tmpDir, 'ab.txt'), 'e'); + fs.writeFileSync(path.join(tmpDir, 'abc.txt'), 'f'); + const multiResults = utils.findFiles(tmpDir, '??.txt'); + const multiNames = multiResults.map(r => path.basename(r.path)); + assert.ok(multiNames.includes('ab.txt'), '?? should match 2-char filename'); + assert.ok(!multiNames.includes('abc.txt'), '?? should NOT match 3-char filename'); + } finally { + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + })) passed++; else failed++; + // Summary console.log('\n=== Test Results ==='); console.log(`Passed: ${passed}`);