@endlessblink/like-i-said-v2
Version:
Task Management & Memory for Claude - Track tasks, remember context, and maintain continuity across sessions with 27 powerful tools. Works with Claude Desktop and Claude Code.
266 lines (234 loc) โข 7.78 kB
JavaScript
/**
* Comprehensive error testing script for path configuration functionality
* Tests various error scenarios to ensure robust error handling
*/
const fs = require('fs');
const path = require('path');
const http = require('http');
const { execSync } = require('child_process');
console.log('๐งช Like-I-Said Path Configuration Error Testing Suite\n');
// Test configuration
const API_BASE = 'http://localhost:3001';
const TEST_SCENARIOS = [
{
name: 'Non-existent directories',
memoryPath: '/completely/fake/path/that/does/not/exist/memories',
taskPath: '/another/fake/path/tasks',
expectError: false, // Should accept but show as non-existent
},
{
name: 'Invalid characters in path (Windows)',
memoryPath: 'C:\\invalid<>path|with*chars\\memories',
taskPath: 'C:\\bad?path"name\\tasks',
expectError: true,
},
{
name: 'Relative paths',
memoryPath: './memories',
taskPath: '../tasks',
expectError: false, // Should work but resolve to absolute
},
{
name: 'Empty paths',
memoryPath: '',
taskPath: '',
expectError: true,
},
{
name: 'Null/undefined paths',
memoryPath: null,
taskPath: undefined,
expectError: true,
},
{
name: 'Very long paths',
memoryPath: 'C:\\' + 'a'.repeat(300) + '\\memories',
taskPath: 'C:\\' + 'b'.repeat(300) + '\\tasks',
expectError: true,
},
{
name: 'Paths with special characters',
memoryPath: '/home/user/like-i-said (special)/memories',
taskPath: '/home/user/like-i-said [test]/tasks',
expectError: false,
},
{
name: 'Network paths (Windows UNC)',
memoryPath: '\\\\server\\share\\memories',
taskPath: '\\\\server\\share\\tasks',
expectError: false,
},
{
name: 'Paths with environment variables',
memoryPath: '$HOME/memories',
taskPath: '%USERPROFILE%\\tasks',
expectError: false, // Should be resolved
},
{
name: 'File instead of directory',
memoryPath: __filename, // This script file
taskPath: __filename,
expectError: true,
},
];
// Helper function to make API requests
function makeRequest(method, path, data = null) {
return new Promise((resolve, reject) => {
const options = {
hostname: 'localhost',
port: 3001,
path: path,
method: method,
headers: {
'Content-Type': 'application/json',
},
};
const req = http.request(options, (res) => {
let body = '';
res.on('data', (chunk) => body += chunk);
res.on('end', () => {
try {
const result = {
status: res.statusCode,
data: body ? JSON.parse(body) : null,
};
resolve(result);
} catch (e) {
resolve({
status: res.statusCode,
data: body,
error: e.message,
});
}
});
});
req.on('error', reject);
if (data) {
req.write(JSON.stringify(data));
}
req.end();
});
}
// Test each scenario
async function runTests() {
console.log('๐ Testing path configuration error scenarios...\n');
// First, check if API server is running
try {
await makeRequest('GET', '/api/paths');
} catch (error) {
console.error('โ API server is not running on port 3001');
console.error(' Please start the dashboard with: npm run dev:full');
process.exit(1);
}
let passed = 0;
let failed = 0;
for (const scenario of TEST_SCENARIOS) {
console.log(`๐ Test: ${scenario.name}`);
console.log(` Memory Path: ${scenario.memoryPath}`);
console.log(` Task Path: ${scenario.taskPath}`);
try {
const result = await makeRequest('POST', '/api/paths', {
memoryPath: scenario.memoryPath,
taskPath: scenario.taskPath,
});
if (scenario.expectError) {
if (result.status >= 400) {
console.log(` โ
Expected error received: ${result.data.error || result.data}`);
passed++;
} else {
console.log(` โ Expected error but got success`);
failed++;
}
} else {
if (result.status === 200) {
console.log(` โ
Success as expected`);
passed++;
} else {
console.log(` โ Expected success but got error: ${result.data.error || result.data}`);
failed++;
}
}
} catch (error) {
console.log(` โ Request failed: ${error.message}`);
failed++;
}
console.log('');
}
// Test concurrent access
console.log('๐ Test: Concurrent path updates');
try {
const promises = [];
for (let i = 0; i < 5; i++) {
promises.push(
makeRequest('POST', '/api/paths', {
memoryPath: `/test/concurrent/${i}/memories`,
taskPath: `/test/concurrent/${i}/tasks`,
})
);
}
const results = await Promise.all(promises);
const allSuccessful = results.every(r => r.status === 200);
if (allSuccessful) {
console.log(' โ
All concurrent requests succeeded');
passed++;
} else {
console.log(' โ Some concurrent requests failed');
failed++;
}
} catch (error) {
console.log(` โ Concurrent test failed: ${error.message}`);
failed++;
}
console.log('\n๐ Test Results:');
console.log(` โ
Passed: ${passed}`);
console.log(` โ Failed: ${failed}`);
console.log(` ๐ Total: ${passed + failed}`);
// Test permission scenarios (if running as root/admin)
console.log('\n๐ Permission Tests:');
console.log(' Note: Some permission tests require admin/root access');
// Test read-only directory
if (process.platform !== 'win32') {
try {
const readOnlyDir = '/tmp/like-i-said-readonly-test';
if (fs.existsSync(readOnlyDir)) {
fs.rmSync(readOnlyDir, { recursive: true });
}
fs.mkdirSync(readOnlyDir);
fs.chmodSync(readOnlyDir, 0o444); // Read-only
const result = await makeRequest('POST', '/api/paths', {
memoryPath: path.join(readOnlyDir, 'memories'),
taskPath: path.join(readOnlyDir, 'tasks'),
});
console.log(' Read-only directory test:', result.status === 200 ? 'โ
Handled' : 'โ Failed');
// Cleanup
fs.chmodSync(readOnlyDir, 0o755);
fs.rmSync(readOnlyDir, { recursive: true });
} catch (error) {
console.log(' Read-only directory test: โ ๏ธ Skipped (permission error)');
}
}
// Test symlink handling
console.log('\n๐ Symlink Tests:');
try {
const realDir = '/tmp/like-i-said-real';
const symlinkDir = '/tmp/like-i-said-symlink';
if (fs.existsSync(realDir)) fs.rmSync(realDir, { recursive: true });
if (fs.existsSync(symlinkDir)) fs.unlinkSync(symlinkDir);
fs.mkdirSync(realDir, { recursive: true });
fs.symlinkSync(realDir, symlinkDir);
const result = await makeRequest('POST', '/api/paths', {
memoryPath: path.join(symlinkDir, 'memories'),
taskPath: path.join(symlinkDir, 'tasks'),
});
console.log(' Symlink directory test:', result.status === 200 ? 'โ
Handled' : 'โ Failed');
// Cleanup
fs.unlinkSync(symlinkDir);
fs.rmSync(realDir, { recursive: true });
} catch (error) {
console.log(' Symlink directory test: โ ๏ธ Skipped (not supported on this system)');
}
console.log('\nโจ Testing complete!');
}
// Run the tests
runTests().catch(console.error);