// Integration test suite for FluentBoards MCP server
// Run with: npm test or npx ts-node tests/integration.test.ts
import { spawn, ChildProcess } from "child_process";
import { join } from "path";
interface TestResult {
name: string;
passed: boolean;
error?: string;
data?: any;
}
class MCPTester {
private server: ChildProcess | null = null;
private results: TestResult[] = [];
async startServer(): Promise<void> {
return new Promise((resolve, reject) => {
const serverPath = join(__dirname, "../dist/index.js");
this.server = spawn("node", [serverPath], {
stdio: ["pipe", "pipe", "pipe"],
});
this.server.stderr?.on("data", (data) => {
if (data.toString().includes("FluentBoards MCP server running")) {
resolve();
}
});
this.server.on("error", reject);
setTimeout(() => reject(new Error("Server start timeout")), 5000);
});
}
async stopServer(): Promise<void> {
if (this.server) {
this.server.kill();
this.server = null;
}
}
async runTest(
name: string,
toolName: string,
args: any
): Promise<TestResult> {
return new Promise((resolve) => {
if (!this.server) {
resolve({ name, passed: false, error: "Server not started" });
return;
}
const testMessage = {
method: "tools/call",
params: {
name: toolName,
arguments: args,
},
};
let responseReceived = false;
// Set up response handler
const responseHandler = (data: Buffer) => {
if (!responseReceived) {
responseReceived = true;
this.server?.stdout?.removeListener("data", responseHandler);
try {
const response = JSON.parse(data.toString());
resolve({ name, passed: true, data: response });
} catch (error) {
resolve({ name, passed: false, error: `Parse error: ${error}` });
}
}
};
this.server.stdout?.on("data", responseHandler);
// Send test message
this.server.stdin?.write(JSON.stringify(testMessage) + "\n");
// Timeout after 5 seconds
setTimeout(() => {
if (!responseReceived) {
responseReceived = true;
this.server?.stdout?.removeListener("data", responseHandler);
resolve({ name, passed: false, error: "Response timeout" });
}
}, 5000);
});
}
async runAllTests(): Promise<void> {
console.log("🧪 Starting FluentBoards MCP Server Integration Tests\n");
try {
// Start server
console.log("🚀 Starting MCP server...");
await this.startServer();
console.log("✅ Server started successfully\n");
// Test 1: Debug test
console.log("Test 1: Debug connectivity...");
const debugResult = await this.runTest("Debug Test", "debug_test", {
random_string: "test",
});
this.results.push(debugResult);
console.log(
debugResult.passed ? "✅ PASSED" : "❌ FAILED",
debugResult.error || ""
);
// Test 2: List boards
console.log("Test 2: List boards...");
const listResult = await this.runTest("List Boards", "list_boards", {
random_string: "test",
});
this.results.push(listResult);
console.log(
listResult.passed ? "✅ PASSED" : "❌ FAILED",
listResult.error || ""
);
// Test 3: Create board
console.log("Test 3: Create board...");
const createResult = await this.runTest("Create Board", "create_board", {
title: "Test Board from Integration Test",
description: "Created by automated test suite",
type: "to-do",
});
this.results.push(createResult);
console.log(
createResult.passed ? "✅ PASSED" : "❌ FAILED",
createResult.error || ""
);
// Test 4: Get board (if we have a board ID from previous tests)
if (createResult.passed && createResult.data?.board?.id) {
console.log("Test 4: Get board details...");
const getResult = await this.runTest("Get Board", "get_board", {
board_id: createResult.data.board.id,
});
this.results.push(getResult);
console.log(
getResult.passed ? "✅ PASSED" : "❌ FAILED",
getResult.error || ""
);
}
// Test 5: List tasks
console.log("Test 5: List tasks...");
const tasksResult = await this.runTest("List Tasks", "list_tasks", {
board_id: 12,
});
this.results.push(tasksResult);
console.log(
tasksResult.passed ? "✅ PASSED" : "❌ FAILED",
tasksResult.error || ""
);
} catch (error) {
console.error("❌ Test suite failed:", error);
} finally {
// Clean up
await this.stopServer();
console.log("\n🔄 Server stopped");
}
// Print summary
this.printSummary();
}
private printSummary(): void {
const passed = this.results.filter((r) => r.passed).length;
const total = this.results.length;
console.log("\n📊 Test Summary");
console.log("================");
console.log(`Total tests: ${total}`);
console.log(`Passed: ${passed}`);
console.log(`Failed: ${total - passed}`);
console.log(`Success rate: ${((passed / total) * 100).toFixed(1)}%`);
if (total - passed > 0) {
console.log("\n❌ Failed tests:");
this.results
.filter((r) => !r.passed)
.forEach((result) => {
console.log(` - ${result.name}: ${result.error}`);
});
}
console.log(
passed === total ? "\n🎉 All tests passed!" : "\n⚠️ Some tests failed"
);
}
}
// Run tests if this file is executed directly
if (require.main === module) {
const tester = new MCPTester();
tester.runAllTests().catch(console.error);
}