// Test setup file
// This file runs before all tests
import { execSync } from 'child_process';
// Global test utilities
declare global {
var testProjectName: string;
var isDdevAvailable: boolean;
var mysqlProject: {
name: string;
path: string;
ready: boolean;
};
var postgresProject: {
name: string;
path: string;
ready: boolean;
};
}
// Check if DDEV is available
function checkDdevAvailable(): boolean {
try {
console.log('π Checking DDEV availability...');
// Check DDEV command exists
const version = execSync('ddev version', { stdio: 'pipe', encoding: 'utf8', timeout: 10000 });
// Extract just the version number from the output
const versionMatch = version.match(/DDEV version\s+v?([0-9]+\.[0-9]+\.[0-9]+)/);
const versionNumber = versionMatch ? versionMatch[1] : version.split('\n')[0].trim();
console.log(` β
DDEV version: v${versionNumber}`);
// Check Docker is running
try {
execSync('docker ps', { stdio: 'pipe', timeout: 10000 });
console.log(' β
Docker is running');
} catch (dockerError) {
console.log(' β οΈ Docker check failed, but continuing...');
}
// Try a simple DDEV command
try {
execSync('ddev list', { stdio: 'pipe', timeout: 15000 });
console.log(' β
DDEV list command works');
} catch (listError) {
console.log(' β οΈ DDEV list failed, but DDEV is available');
}
return true;
} catch (error) {
console.log(` β DDEV not available: ${error instanceof Error ? error.message : String(error)}`);
return false;
}
}
// Check if we're in CI environment
function isCI(): boolean {
return Boolean(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI);
}
// Set up test environment
beforeAll(async () => {
console.log('π§ Setting up test environment...');
if (isCI()) {
console.log('π€ Running in CI environment');
} else {
console.log('π» Running in local environment');
}
(global as any).isDdevAvailable = checkDdevAvailable();
// Use timestamp to ensure unique project names
const timestamp = Date.now();
(global as any).testProjectName = `ddev-mcp-test-${timestamp}`;
if (global.isDdevAvailable) {
console.log('β
DDEV available - running integration tests');
console.log(`π Test project name: ${global.testProjectName}`);
// Clean up any existing test projects (broad cleanup)
console.log('π§Ή Cleaning up any existing test projects...');
try {
console.log(' π Attempting to list DDEV projects...');
const result = execSync('ddev list --json-output', { encoding: 'utf8', stdio: 'pipe', timeout: 30000 });
const jsonData = JSON.parse(result || '{"raw":[]}');
const projects = jsonData.raw || [];
console.log(` π Found ${projects.length} DDEV projects`);
// Clean up any old test projects
let cleanedCount = 0;
for (const project of projects) {
if (project.name && project.name.includes('ddev-mcp-test')) {
try {
console.log(` ποΈ Removing old test project: ${project.name}`);
execSync(`ddev delete -Oy ${project.name}`, { stdio: 'pipe', timeout: 30000 });
cleanedCount++;
} catch (error) {
console.log(` β οΈ Failed to remove ${project.name}: ${error instanceof Error ? error.message : String(error)}`);
}
}
}
console.log(`β
Cleaned up ${cleanedCount} old test projects`);
} catch (error) {
// If we can't list projects, try specific cleanup and diagnose
console.log('β οΈ Could not list projects, diagnosing DDEV status...');
// Check DDEV version and status
try {
const version = execSync('ddev version', { encoding: 'utf8', stdio: 'pipe', timeout: 10000 });
const versionMatch = version.match(/DDEV version\s+v?([0-9]+\.[0-9]+\.[0-9]+)/);
const versionNumber = versionMatch ? `v${versionMatch[1]}` : 'unknown';
console.log(` βΉοΈ DDEV version: ${versionNumber}`);
} catch (versionError) {
console.log(` β DDEV version check failed: ${versionError instanceof Error ? versionError.message : String(versionError)}`);
}
// Check Docker status
try {
const dockerStatus = execSync('docker ps', { encoding: 'utf8', stdio: 'pipe', timeout: 10000 });
console.log(` βΉοΈ Docker is running (${dockerStatus.split('\n').length - 1} containers)`);
} catch (dockerError) {
console.log(` β Docker check failed: ${dockerError instanceof Error ? dockerError.message : String(dockerError)}`);
}
// Try specific cleanup
console.log(' π§Ή Attempting specific project cleanup...');
const cleanupProjects = ['ddev-mcp-test', 'ddev-mcp-test-tools', 'mysql-fail-project', 'postgres-fail-project', 'server-failure-test'];
for (const projectName of cleanupProjects) {
try {
execSync(`ddev delete -Oy ${projectName}`, { stdio: 'pipe', timeout: 30000 });
console.log(` β
Removed ${projectName}`);
} catch (cleanupError) {
// Projects might not exist, that's fine
console.log(` βΉοΈ ${projectName} not found (OK)`);
}
}
}
} else {
console.log('β οΈ DDEV not available - running unit tests only');
}
console.log('π Test environment setup complete');
});
// Clean up after all tests
afterAll(async () => {
if (global.isDdevAvailable && global.testProjectName) {
console.log('π§Ή Cleaning up test environment...');
try {
// Clean up the specific test projects
console.log(` ποΈ Removing test project: ${global.testProjectName}`);
execSync(`ddev delete -Oy ${global.testProjectName}`, { stdio: 'pipe' });
console.log(` ποΈ Removing test project: ${global.testProjectName}-tools`);
execSync(`ddev delete -Oy ${global.testProjectName}-tools`, { stdio: 'pipe' });
// Also clean up any orphaned containers
console.log(' π³ Powering off DDEV containers...');
execSync('ddev poweroff', { stdio: 'pipe' });
console.log('β
Test cleanup complete');
} catch (error) {
console.log('β οΈ Best effort cleanup completed');
}
}
});