UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

328 lines (323 loc) 11.3 kB
import * as fs from 'fs'; import * as path from 'path'; import { execSync } from 'child_process'; import chalk from 'chalk'; export class TestDetector { projectRoot; constructor(projectRoot = process.cwd()) { this.projectRoot = projectRoot; } /** * Detect all available test configurations in the project */ async detectTests() { const configs = []; // Check for custom test hook first (highest priority) const customHook = this.checkCustomHook(); if (customHook) { configs.push(customHook); } // Check for various test frameworks const dockerCompose = this.checkDockerCompose(); if (dockerCompose) configs.push(dockerCompose); const npm = this.checkNpm(); if (npm) configs.push(npm); const python = this.checkPython(); if (python) configs.push(python); const playwright = this.checkPlaywright(); if (playwright) configs.push(playwright); const rust = this.checkRust(); if (rust) configs.push(rust); const go = this.checkGo(); if (go) configs.push(go); const make = this.checkMake(); if (make) configs.push(make); const gradle = this.checkGradle(); if (gradle) configs.push(gradle); const maven = this.checkMaven(); if (maven) configs.push(maven); // Sort by priority (lower number = higher priority) return configs.sort((a, b) => a.priority - b.priority); } /** * Run the detected tests */ async runTests(configs) { if (!configs) { configs = await this.detectTests(); } if (configs.length === 0) { console.log(chalk.yellow('⚠️ No test configurations detected')); console.log(chalk.gray('Create .mira-test-hook.sh to define custom test commands')); return false; } console.log(chalk.blue(`\n🧪 Running tests (${configs.length} configurations detected)\n`)); let allPassed = true; for (const config of configs) { console.log(chalk.cyan(`Running ${config.type} tests: ${config.description}`)); try { // Run setup command if needed if (config.setupCommand) { console.log(chalk.gray(`Setup: ${config.setupCommand}`)); execSync(config.setupCommand, { cwd: this.projectRoot, stdio: 'inherit' }); } // Run test command console.log(chalk.gray(`Command: ${config.command}`)); execSync(config.command, { cwd: this.projectRoot, stdio: 'inherit' }); console.log(chalk.green(`✅ ${config.type} tests passed\n`)); } catch (error) { console.log(chalk.red(`❌ ${config.type} tests failed\n`)); allPassed = false; // Continue with other test suites even if one fails if (configs.length > 1) { console.log(chalk.yellow('Continuing with remaining test suites...\n')); } } } return allPassed; } checkCustomHook() { const hookPath = path.join(this.projectRoot, '.mira-test-hook.sh'); if (fs.existsSync(hookPath)) { // Make sure it's executable try { fs.chmodSync(hookPath, '755'); } catch (e) { // Ignore chmod errors on Windows } return { type: 'Custom Hook', command: 'bash .mira-test-hook.sh', description: 'User-defined test script', priority: 0 // Highest priority }; } return null; } checkDockerCompose() { const composePath = path.join(this.projectRoot, 'docker-compose.yml'); const composeYamlPath = path.join(this.projectRoot, 'docker-compose.yaml'); if (fs.existsSync(composePath) || fs.existsSync(composeYamlPath)) { return { type: 'Docker Compose', setupCommand: 'docker-compose up -d', command: 'docker-compose ps', description: 'Ensure Docker services are running', priority: 1 }; } return null; } checkNpm() { const packagePath = path.join(this.projectRoot, 'package.json'); if (fs.existsSync(packagePath)) { try { const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf-8')); if (packageJson.scripts?.test) { // Check if using yarn const yarnLock = path.join(this.projectRoot, 'yarn.lock'); const command = fs.existsSync(yarnLock) ? 'yarn test' : 'npm test'; return { type: 'Node.js', command, description: 'Run npm/yarn test scripts', priority: 2 }; } } catch (e) { // Invalid package.json } } return null; } checkPython() { const pytestIni = path.join(this.projectRoot, 'pytest.ini'); const setupPy = path.join(this.projectRoot, 'setup.py'); const toxIni = path.join(this.projectRoot, 'tox.ini'); const requirements = path.join(this.projectRoot, 'requirements.txt'); if (fs.existsSync(pytestIni)) { return { type: 'Python (pytest)', command: 'pytest', description: 'Run pytest test suite', priority: 3 }; } else if (fs.existsSync(toxIni)) { return { type: 'Python (tox)', command: 'tox', description: 'Run tox test environments', priority: 3 }; } else if (fs.existsSync(setupPy) || fs.existsSync(requirements)) { // Check if there's a test directory const testDir = path.join(this.projectRoot, 'test'); const testsDir = path.join(this.projectRoot, 'tests'); if (fs.existsSync(testDir) || fs.existsSync(testsDir)) { return { type: 'Python (unittest)', command: 'python -m unittest discover', description: 'Run Python unittest discovery', priority: 3 }; } } return null; } checkPlaywright() { const playwrightConfigs = [ 'playwright.config.js', 'playwright.config.ts', 'playwright.config.mjs' ]; for (const config of playwrightConfigs) { if (fs.existsSync(path.join(this.projectRoot, config))) { return { type: 'Playwright', command: 'npx playwright test', description: 'Run Playwright E2E tests', priority: 4 }; } } return null; } checkRust() { const cargoToml = path.join(this.projectRoot, 'Cargo.toml'); if (fs.existsSync(cargoToml)) { return { type: 'Rust', command: 'cargo test', description: 'Run Rust test suite', priority: 5 }; } return null; } checkGo() { const goMod = path.join(this.projectRoot, 'go.mod'); if (fs.existsSync(goMod)) { return { type: 'Go', command: 'go test ./...', description: 'Run Go test suite', priority: 5 }; } return null; } checkMake() { const makefile = path.join(this.projectRoot, 'Makefile'); if (fs.existsSync(makefile)) { // Check if makefile has a test target try { const content = fs.readFileSync(makefile, 'utf-8'); if (content.includes('test:')) { return { type: 'Make', command: 'make test', description: 'Run Makefile test target', priority: 6 }; } } catch (e) { // Unable to read Makefile } } return null; } checkGradle() { const buildGradle = path.join(this.projectRoot, 'build.gradle'); const buildGradleKts = path.join(this.projectRoot, 'build.gradle.kts'); const gradlew = path.join(this.projectRoot, 'gradlew'); if (fs.existsSync(buildGradle) || fs.existsSync(buildGradleKts)) { const command = fs.existsSync(gradlew) ? './gradlew test' : 'gradle test'; return { type: 'Gradle', command, description: 'Run Gradle test task', priority: 7 }; } return null; } checkMaven() { const pomXml = path.join(this.projectRoot, 'pom.xml'); const mvnw = path.join(this.projectRoot, 'mvnw'); if (fs.existsSync(pomXml)) { const command = fs.existsSync(mvnw) ? './mvnw test' : 'mvn test'; return { type: 'Maven', command, description: 'Run Maven test phase', priority: 8 }; } return null; } /** * Create a sample test hook file */ createSampleTestHook() { const hookPath = path.join(this.projectRoot, '.mira-test-hook.sh'); if (!fs.existsSync(hookPath)) { const content = `#!/bin/bash # MIRA Custom Test Hook # This script is executed when running tests through MIRA # Customize it to match your project's testing needs echo "🧪 Running custom test suite..." # Example: Run multiple test commands # npm test # npm run e2e # npm run lint # Example: Run tests in specific order # echo "Running unit tests..." # npm run test:unit # # echo "Running integration tests..." # npm run test:integration # # echo "Running E2E tests..." # npm run test:e2e # Example: Check test coverage # npm run test:coverage echo "✅ Custom test suite completed" `; fs.writeFileSync(hookPath, content); // Make executable on Unix-like systems try { fs.chmodSync(hookPath, '755'); } catch (e) { // Ignore on Windows } console.log(chalk.green('✅ Created .mira-test-hook.sh')); console.log(chalk.gray('Customize this file to define your test commands')); } else { console.log(chalk.yellow('⚠️ .mira-test-hook.sh already exists')); } } } //# sourceMappingURL=TestDetector.js.map