import 'dotenv/config';
import { describe, it, before, after } from 'node:test';
import { strict as assert } from 'node:assert';
import { existsSync } from 'fs';
import { spawn, ChildProcess } from 'child_process';
/**
* End-to-End tests for the Zebrunner MCP Server
* These tests start the actual server and test MCP tool calls
*
* NOTE: These tests require real Zebrunner credentials to run.
* They will be skipped if credentials are not available.
*/
// Check for real credentials
const hasRealCredentials = process.env.ZEBRUNNER_URL &&
process.env.ZEBRUNNER_LOGIN &&
process.env.ZEBRUNNER_TOKEN &&
!process.env.ZEBRUNNER_URL.includes('example.com') &&
!process.env.ZEBRUNNER_TOKEN.includes('test-token');
describe('Zebrunner MCP Server E2E Tests', () => {
describe('Prerequisites Check', () => {
it('should indicate if E2E tests can run with current configuration', () => {
const hasRealCredentials = process.env.ZEBRUNNER_URL &&
process.env.ZEBRUNNER_LOGIN &&
process.env.ZEBRUNNER_TOKEN &&
!process.env.ZEBRUNNER_URL.includes('example.com') &&
!process.env.ZEBRUNNER_TOKEN.includes('test-token');
if (!hasRealCredentials) {
console.log('⚠️ E2E tests require real Zebrunner credentials');
console.log(' Current configuration uses placeholder/test values');
console.log(' To run E2E tests:');
console.log(' 1. Set ZEBRUNNER_URL, ZEBRUNNER_LOGIN, ZEBRUNNER_TOKEN in .env');
console.log(' 2. Run: npm run build');
console.log(' 3. Run: npx tsx --test tests/e2e/server-manual.test.ts');
console.log('');
console.log('✅ E2E infrastructure is available but skipped due to credentials');
} else {
console.log('✅ Real credentials detected - E2E tests could run');
console.log(' Use server-manual.test.ts for comprehensive E2E testing');
}
// Always pass - this is just an informational test
assert.ok(true, 'E2E test infrastructure check completed');
});
it('should verify server build exists', () => {
const serverExists = existsSync('dist/server.js');
if (!serverExists) {
console.log('❌ Server build not found. Run: npm run build');
} else {
console.log('✅ Server build found at dist/server.js');
}
assert.ok(serverExists, 'Server build should exist for E2E tests');
});
it('should provide E2E testing guidance', () => {
console.log('');
console.log('📋 E2E Testing Options:');
console.log(' • Unit tests: npm run test unit (no credentials needed)');
console.log(' • Integration tests: npm run test integration (needs credentials)');
console.log(' • Manual E2E tests: npx tsx --test tests/e2e/server-manual.test.ts');
console.log(' • All tests: npm test (runs all available tests)');
console.log('');
assert.ok(true, 'E2E guidance provided');
});
});
// Conditional E2E tests - run only if credentials are available
let serverProcess: ChildProcess;
let serverReady = false;
before(async function() {
if (!hasRealCredentials) {
console.log('⚠️ Skipping E2E tests - no real credentials available');
this.skip();
return;
}
console.log('🚀 Starting MCP Server for E2E tests...');
// Start the server process
serverProcess = spawn('node', ['dist/server.js'], {
env: {
...process.env,
DEBUG: 'false'
},
stdio: ['pipe', 'pipe', 'pipe']
});
// Wait for server to be ready
return new Promise<void>((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error('Server startup timeout after 10 seconds'));
}, 10000);
const handleOutput = (data: Buffer) => {
const output = data.toString();
if (output.includes('Zebrunner Unified MCP Server started successfully')) {
serverReady = true;
clearTimeout(timeout);
console.log('✅ Server started successfully');
resolve();
}
};
serverProcess.stdout?.on('data', handleOutput);
serverProcess.stderr?.on('data', handleOutput);
serverProcess.on('error', (error) => {
clearTimeout(timeout);
reject(error);
});
});
});
after(() => {
if (serverProcess && !serverProcess.killed) {
console.log('🛑 Shutting down server...');
serverProcess.kill('SIGTERM');
}
});
describe('Server Initialization (requires credentials)', () => {
it('should start server successfully', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready');
});
});
describe('Core Working Tools (requires credentials)', () => {
it('should list test suites for MCP project', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
// This would require MCP protocol implementation
// For now, just verify server is running
assert.ok(serverReady, 'Server should be ready for tool calls');
});
it('should get test case by key MCP-2', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
// This would require MCP protocol implementation
assert.ok(serverReady, 'Server should be ready for tool calls');
});
it('should get test case in markdown format', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
// This would require MCP protocol implementation
assert.ok(serverReady, 'Server should be ready for tool calls');
});
});
describe('Enhanced Features (requires credentials)', () => {
it('should get advanced test cases with pagination', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready for enhanced features');
});
it('should build suite hierarchy', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready for hierarchy building');
});
it('should handle string format output', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready for format handling');
});
});
describe('Error Handling (requires credentials)', () => {
it('should handle invalid project key gracefully', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready for error handling');
});
it('should handle missing required parameters', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready for parameter validation');
});
it('should handle non-existent test case', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready for error scenarios');
});
});
describe('Tool Discovery (requires credentials)', () => {
it('should list available tools', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready for tool discovery');
});
it('should provide tool descriptions and schemas', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready for schema discovery');
});
});
describe('Performance (requires credentials)', () => {
it('should handle multiple concurrent requests', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready for concurrent requests');
});
it('should respond within reasonable time', function() {
if (!hasRealCredentials) {
this.skip();
return;
}
assert.ok(serverReady, 'Server should be ready for performance testing');
});
});
});
console.log('✅ E2E test structure available - use server-manual.test.ts for actual testing');