run-all.jsโข6.19 kB
#!/usr/bin/env node
import { spawn } from 'child_process';
import { readdir, stat } from 'fs/promises';
import { join } from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const TESTS_TO_SKIP = ['run-all.js', 'run-comprehensive-tests.js', 'README.md', 'in-memoria.db'];
async function runTest(testFile, testPath) {
  console.log(`\n${'='.repeat(60)}`);
  console.log(`๐งช Running: ${testFile}`);
  console.log(`${'='.repeat(60)}\n`);
  return new Promise((resolve) => {
    const child = spawn('node', [testPath], {
      stdio: 'inherit',
      cwd: process.cwd(),
      timeout: 60000 // 60 second timeout
    });
    child.on('close', (code) => {
      if (code === 0) {
        console.log(`\nโ
 ${testFile} completed successfully`);
      } else {
        console.log(`\nโ ${testFile} failed with code ${code}`);
      }
      resolve(code);
    });
    child.on('error', (error) => {
      console.error(`\n๐ฅ ${testFile} error:`, error.message);
      resolve(1);
    });
  });
}
async function getTestFiles(directory, filter = null) {
  const entries = await readdir(directory);
  const testFiles = [];
  for (const entry of entries) {
    const fullPath = join(directory, entry);
    const stats = await stat(fullPath);
    if (stats.isDirectory() && entry === 'integration' && (!filter || filter === 'integration')) {
      // Get integration tests
      const integrationFiles = await readdir(fullPath);
      for (const file of integrationFiles) {
        if (file.endsWith('.js') && !TESTS_TO_SKIP.includes(file)) {
          testFiles.push({
            name: `integration/${file}`,
            path: join(fullPath, file),
            category: 'integration'
          });
        }
      }
    } else if (stats.isFile() &&
      entry.startsWith('test-') &&
      entry.endsWith('.js') &&
      !TESTS_TO_SKIP.includes(entry)) {
      // Skip if filter is set to integration only
      if (filter === 'integration') continue;
      testFiles.push({
        name: entry,
        path: fullPath,
        category: 'manual'
      });
    }
  }
  return testFiles;
}
async function runAllTests(filter = null) {
  const filterText = filter ? ` (${filter} only)` : '';
  console.log(`๐ Running manual & integration tests${filterText}...\n`);
  console.log('โน๏ธ  Make sure to run "npm run build" first!\n');
  try {
    const testFiles = await getTestFiles(__dirname, filter);
    if (testFiles.length === 0) {
      console.log(`No test files found${filterText}!`);
      process.exit(1);
    }
    // Group by category
    const byCategory = testFiles.reduce((acc, test) => {
      if (!acc[test.category]) acc[test.category] = [];
      acc[test.category].push(test);
      return acc;
    }, {});
    console.log(`Found ${testFiles.length} test files:\n`);
    for (const [category, tests] of Object.entries(byCategory)) {
      console.log(`  ${category.toUpperCase()}:`);
      tests.forEach(test => console.log(`    - ${test.name}`));
    }
    console.log();
    let passed = 0;
    let failed = 0;
    const failedTests = [];
    // Run integration tests first
    if (byCategory.integration) {
      console.log(`\n${'='.repeat(60)}`);
      console.log(`๐ฆ INTEGRATION TESTS`);
      console.log(`${'='.repeat(60)}\n`);
      for (const test of byCategory.integration) {
        const result = await runTest(test.name, test.path);
        if (result === 0) {
          passed++;
        } else {
          failed++;
          failedTests.push(test.name);
        }
      }
    }
    // Then run manual tests
    if (byCategory.manual) {
      console.log(`\n${'='.repeat(60)}`);
      console.log(`๐ง MANUAL TESTS`);
      console.log(`${'='.repeat(60)}\n`);
      for (const test of byCategory.manual) {
        const result = await runTest(test.name, test.path);
        if (result === 0) {
          passed++;
        } else {
          failed++;
          failedTests.push(test.name);
        }
      }
    }
    console.log(`\n${'='.repeat(60)}`);
    console.log(`๐ TEST SUMMARY`);
    console.log(`${'='.repeat(60)}`);
    console.log(`โ
 Passed: ${passed}`);
    console.log(`โ Failed: ${failed}`);
    console.log(`๐ Total:  ${passed + failed}`);
    if (failed > 0) {
      console.log(`\nโ ๏ธ  Failed tests:`);
      failedTests.forEach(test => console.log(`   - ${test}`));
      console.log(`\nโ ๏ธ  Some tests failed. Check output above for details.`);
      process.exit(1);
    } else {
      console.log(`\n๐ All tests passed!`);
      process.exit(0);
    }
  } catch (error) {
    console.error('Error running tests:', error);
    process.exit(1);
  }
}
// Handle command line arguments
const args = process.argv.slice(2);
if (args.length > 0) {
  const firstArg = args[0];
  // Check if it's a filter argument
  if (firstArg === 'integration' || firstArg === 'manual') {
    console.log(`๐ฏ Filtering tests: ${firstArg}\n`);
    runAllTests(firstArg);
  } else if (firstArg.startsWith('test-') && firstArg.endsWith('.js')) {
    // Run specific test file
    console.log(`๐งช Running specific test: ${firstArg}\n`);
    runTest(firstArg, join(__dirname, firstArg)).then(code => process.exit(code));
  } else if (firstArg.includes('/')) {
    // Run specific test with path (e.g., integration/test-mcp-client.js)
    const testPath = join(__dirname, firstArg);
    console.log(`๐งช Running specific test: ${firstArg}\n`);
    runTest(firstArg, testPath).then(code => process.exit(code));
  } else {
    console.error('Invalid argument. Usage:');
    console.error('  node run-all.js                          # Run all tests');
    console.error('  node run-all.js integration              # Run integration tests only');
    console.error('  node run-all.js manual                   # Run manual tests only');
    console.error('  node run-all.js test-simple.js           # Run specific test');
    console.error('  node run-all.js integration/test-mcp.js  # Run specific integration test');
    process.exit(1);
  }
} else {
  // Run all tests
  runAllTests();
}