Skip to main content
Glama
docker-container-test.mjs10.9 kB
#!/usr/bin/env node /** * Docker Container Test Script for MCP Tailwind Gemini * Tests container functionality and MCP server integration */ import { execSync } from 'child_process'; import fs from 'fs'; import path from 'path'; class DockerTestRunner { constructor() { this.results = { total: 0, passed: 0, failed: 0, tests: [] }; this.imageName = 'mcp-tailwind-runtime:latest'; this.containerName = 'mcp-test-container'; } log(message, type = 'info') { const timestamp = new Date().toISOString(); const colors = { info: '\x1b[36m', success: '\x1b[32m', error: '\x1b[31m', warning: '\x1b[33m', reset: '\x1b[0m' }; console.log(`${colors[type]}[${timestamp}] ${message}${colors.reset}`); } async runCommand(command, description) { try { this.log(`Running: ${command}`, 'info'); const output = execSync(command, { encoding: 'utf8', timeout: 30000, stdio: 'pipe' }); this.log(`✓ ${description}`, 'success'); return { success: true, output: output.trim() }; } catch (error) { this.log(`✗ ${description}: ${error.message}`, 'error'); return { success: false, error: error.message, output: error.stdout || '' }; } } async test(name, testFunction) { this.results.total++; this.log(`\n=== Test: ${name} ===`, 'info'); try { const result = await testFunction(); if (result.success) { this.results.passed++; this.log(`✓ PASSED: ${name}`, 'success'); this.results.tests.push({ name, status: 'PASSED', details: result.details || '' }); } else { this.results.failed++; this.log(`✗ FAILED: ${name} - ${result.error}`, 'error'); this.results.tests.push({ name, status: 'FAILED', error: result.error }); } } catch (error) { this.results.failed++; this.log(`✗ ERROR: ${name} - ${error.message}`, 'error'); this.results.tests.push({ name, status: 'ERROR', error: error.message }); } } async cleanup() { this.log('Cleaning up containers...', 'info'); try { execSync(`docker stop ${this.containerName} 2>/dev/null || true`, { stdio: 'pipe' }); execSync(`docker rm ${this.containerName} 2>/dev/null || true`, { stdio: 'pipe' }); } catch (error) { // Ignore cleanup errors } } async testDockerImageExists() { return this.test('Docker Image Exists', async () => { const result = await this.runCommand(`docker images ${this.imageName} --format "table {{.Repository}}:{{.Tag}}"`, 'Check Docker image exists'); if (result.success && result.output.includes(this.imageName)) { return { success: true, details: `Image ${this.imageName} found` }; } return { success: false, error: 'Docker image not found' }; }); } async testContainerStart() { return this.test('Container Start', async () => { await this.cleanup(); // Clean up first const result = await this.runCommand( `docker run -d --name ${this.containerName} ${this.imageName}`, 'Start container in detached mode' ); if (result.success) { // Wait a moment for container to start await new Promise(resolve => setTimeout(resolve, 3000)); const statusResult = await this.runCommand( `docker ps --filter "name=${this.containerName}" --format "{{.Status}}"`, 'Check container status' ); if (statusResult.success && statusResult.output.includes('Up')) { return { success: true, details: 'Container started successfully' }; } return { success: false, error: 'Container failed to start properly' }; } return { success: false, error: result.error }; }); } async testContainerHealth() { return this.test('Container Health Check', async () => { const result = await this.runCommand( `docker exec ${this.containerName} ps aux`, 'Check processes in container' ); if (result.success && result.output.includes('node')) { return { success: true, details: 'Node.js process running in container' }; } return { success: false, error: 'Node.js process not found in container' }; }); } async testMCPServerLogs() { return this.test('MCP Server Logs', async () => { const result = await this.runCommand( `docker logs ${this.containerName}`, 'Check container logs for MCP server startup' ); if (result.success && result.output.includes('MCP Tailwind Gemini Server')) { return { success: true, details: 'MCP server started successfully' }; } return { success: false, error: 'MCP server startup message not found in logs' }; }); } async testFileSystem() { return this.test('Container File System', async () => { const result = await this.runCommand( `docker exec ${this.containerName} ls -la /app/dist/`, 'Check dist directory in container' ); if (result.success && result.output.includes('index.js')) { return { success: true, details: 'Built files present in container' }; } return { success: false, error: 'Built files not found in container' }; }); } async testPackageJson() { return this.test('Package.json Configuration', async () => { const result = await this.runCommand( `docker exec ${this.containerName} cat /app/package.json`, 'Check package.json in container' ); if (result.success) { try { const packageData = JSON.parse(result.output); if (packageData.name === 'mcp-tailwind-gemini') { return { success: true, details: 'Package.json correctly configured' }; } } catch (error) { return { success: false, error: 'Invalid package.json format' }; } } return { success: false, error: 'Could not read package.json' }; }); } async testUserPermissions() { return this.test('User Permissions', async () => { const result = await this.runCommand( `docker exec ${this.containerName} whoami`, 'Check container user' ); if (result.success && result.output.trim() === 'mcp') { return { success: true, details: 'Container running as non-root user (mcp)' }; } return { success: false, error: 'Container not running as expected user' }; }); } async testContainerStop() { return this.test('Container Stop', async () => { const result = await this.runCommand( `docker stop ${this.containerName}`, 'Stop container gracefully' ); if (result.success) { return { success: true, details: 'Container stopped successfully' }; } return { success: false, error: result.error }; }); } async runAllTests() { this.log('🐳 Starting Docker Container Tests for MCP Tailwind Gemini', 'info'); this.log('=' .repeat(60), 'info'); // Run all tests await this.testDockerImageExists(); await this.testContainerStart(); await this.testContainerHealth(); await this.testMCPServerLogs(); await this.testFileSystem(); await this.testPackageJson(); await this.testUserPermissions(); await this.testContainerStop(); // Final cleanup await this.cleanup(); // Print results this.printResults(); } printResults() { this.log('\n' + '=' .repeat(60), 'info'); this.log('🏁 DOCKER TEST RESULTS', 'info'); this.log('=' .repeat(60), 'info'); this.log(`Total Tests: ${this.results.total}`, 'info'); this.log(`Passed: ${this.results.passed}`, 'success'); this.log(`Failed: ${this.results.failed}`, this.results.failed > 0 ? 'error' : 'info'); this.log(`Success Rate: ${((this.results.passed / this.results.total) * 100).toFixed(1)}%`, this.results.failed === 0 ? 'success' : 'warning'); this.log('\n📋 Detailed Results:', 'info'); this.results.tests.forEach((test, index) => { const status = test.status === 'PASSED' ? '✓' : '✗'; const color = test.status === 'PASSED' ? 'success' : 'error'; this.log(`${index + 1}. ${status} ${test.name}`, color); if (test.details) { this.log(` Details: ${test.details}`, 'info'); } if (test.error) { this.log(` Error: ${test.error}`, 'error'); } }); if (this.results.failed === 0) { this.log('\n🎉 All Docker tests passed! Container is ready for deployment.', 'success'); } else { this.log('\n⚠️ Some tests failed. Please review the issues above.', 'warning'); } this.log('\n💡 Container Usage:', 'info'); this.log(' Production: docker run -d --name mcp-server mcp-tailwind-runtime:latest', 'info'); this.log(' With port: docker run -d -p 3000:3000 --name mcp-server mcp-tailwind-runtime:latest', 'info'); this.log(' With env: docker run -d -e GEMINI_API_KEY=your_key --name mcp-server mcp-tailwind-runtime:latest', 'info'); } } // Main execution async function main() { const tester = new DockerTestRunner(); try { await tester.runAllTests(); process.exit(tester.results.failed === 0 ? 0 : 1); } catch (error) { console.error('Test runner failed:', error.message); process.exit(1); } } if (import.meta.url === `file://${process.argv[1]}`) { main().catch(console.error); } export default DockerTestRunner;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Tai-DT/mcp-tailwind-gemini'

If you have feedback or need assistance with the MCP directory API, please join our Discord server