feat: Add testing framework and initial test cases for various tools and database operations

This commit is contained in:
ethan.chen
2026-01-07 10:05:04 +08:00
parent 372b52b214
commit 47ecc40186
23 changed files with 1781 additions and 40 deletions

View File

@@ -0,0 +1,29 @@
/**
* Database test helper - creates isolated database instances for testing
*/
import { database } from "../../src/storage/database.js";
import { join } from "path";
import { mkdirSync } from "fs";
import type { TestContext } from "./test-utils.js";
/**
* Setup test database with isolated data directory
*/
export function setupTestDatabase(testContext: TestContext): () => void {
const testDataDir = join(testContext.tempDir, "data");
mkdirSync(testDataDir, { recursive: true });
// Set environment variable for test data directory
const originalDataDir = process.env.MCP_TEST_DATA_DIR;
process.env.MCP_TEST_DATA_DIR = testDataDir;
// Return cleanup function
return () => {
if (originalDataDir) {
process.env.MCP_TEST_DATA_DIR = originalDataDir;
} else {
delete process.env.MCP_TEST_DATA_DIR;
}
};
}

View File

@@ -0,0 +1,68 @@
/**
* Test utilities and helpers
*/
import { mkdtempSync, rmSync, existsSync } from "fs";
import { join } from "path";
import { tmpdir } from "os";
export interface TestContext {
tempDir: string;
cleanup: () => void;
}
/**
* Create a temporary directory for testing
*/
export function createTempDir(prefix = "mcp-test-"): TestContext {
const tempDir = mkdtempSync(join(tmpdir(), prefix));
return {
tempDir,
cleanup: () => {
if (existsSync(tempDir)) {
rmSync(tempDir, { recursive: true, force: true });
}
},
};
}
/**
* Set test environment variables
*/
export function setTestEnv(env: Record<string, string>): () => void {
const originalEnv: Record<string, string | undefined> = {};
for (const [key, value] of Object.entries(env)) {
originalEnv[key] = process.env[key];
process.env[key] = value;
}
return () => {
for (const [key, originalValue] of Object.entries(originalEnv)) {
if (originalValue === undefined) {
delete process.env[key];
} else {
process.env[key] = originalValue;
}
}
};
}
/**
* Wait for a specified time (for async operations)
*/
export function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Mock HTTP response helper
*/
export function createMockResponse(data: unknown, status = 200) {
return {
status,
data,
headers: {},
};
}

View File

@@ -0,0 +1,35 @@
/**
* Tool testing helper - helps test MCP tools
*/
import { mcpServer } from "../../src/server.js";
import type { ToolHandler } from "../../src/server.js";
/**
* Call a tool by name with arguments
*/
export async function callTool(
toolName: string,
args: Record<string, unknown>
): Promise<{
content: Array<{ type: string; text: string }>;
isError?: boolean;
}> {
// Get the tool handler from the server
const tools = mcpServer.getTools();
const toolEntry = tools.get(toolName);
if (!toolEntry) {
throw new Error(`Tool ${toolName} not found`);
}
return await toolEntry.handler(args);
}
/**
* Get all registered tools
*/
export function getRegisteredTools(): string[] {
const tools = mcpServer.getTools();
return Array.from(tools.keys());
}