import { describe, it, expect, beforeAll, afterAll } from '@jest/globals'
import { spawn, ChildProcess } from 'child_process'
type MCPResponse = {
jsonrpc: string
id: number
result?: any
error?: any
}
describe('MCP Server Integration', () => {
let server: ChildProcess
let requestId = 1
beforeAll(() => {
server = spawn('node', ['dist/index.js'], {
stdio: ['pipe', 'pipe', 'pipe']
})
})
afterAll(() => {
if (server) {
server.kill()
}
})
const sendRequest = (method: string, params: any = {}): Promise<MCPResponse> => {
return new Promise((resolve, reject) => {
const request = {
jsonrpc: '2.0',
id: requestId++,
method,
params
}
if (!server.stdin) {
reject(new Error('Server stdin is null'))
return
}
server.stdin.write(JSON.stringify(request) + '\n')
const timeout = setTimeout(() => {
reject(new Error('Request timeout'))
}, 5000)
if (!server.stdout) {
reject(new Error('Server stdout is null'))
return
}
server.stdout.once('data', (data) => {
clearTimeout(timeout)
try {
const response = JSON.parse(data.toString().trim()) as MCPResponse
resolve(response)
} catch (error) {
reject(new Error(`Failed to parse response: ${data.toString()}`))
}
})
})
}
it('should initialize successfully', async () => {
const response = await sendRequest('initialize', {
protocolVersion: '2024-11-05',
capabilities: {
tools: {}
},
clientInfo: {
name: 'test-client',
version: '1.0.0'
}
})
expect(response).toHaveProperty('result')
if (response.result) {
expect(response.result).toHaveProperty('protocolVersion')
}
})
it('should list available tools', async () => {
const response = await sendRequest('tools/list', {})
expect(response).toHaveProperty('result')
if (response.result) {
expect(response.result).toHaveProperty('tools')
expect(Array.isArray(response.result.tools)).toBe(true)
expect(response.result.tools.length).toBeGreaterThan(0)
const toolNames = response.result.tools.map((tool: any) => tool.name)
expect(toolNames).toContain('compare_texts')
expect(toolNames).toContain('get_detailed_diff')
}
})
it('should execute compare_texts tool', async () => {
const response = await sendRequest('tools/call', {
name: 'compare_texts',
arguments: {
text1: 'Hello World',
text2: 'Hello World'
}
})
expect(response).toHaveProperty('result')
expect(response.result).toHaveProperty('content')
expect(response.result.content).toHaveLength(1)
expect(response.result.content[0]).toHaveProperty('type', 'text')
const result = JSON.parse(response.result.content[0].text)
expect(result).toHaveProperty('identical', true)
})
it('should execute get_detailed_diff tool', async () => {
const response = await sendRequest('tools/call', {
name: 'get_detailed_diff',
arguments: {
text1: 'Line 1\nLine 2\nLine 3',
text2: 'Line 1\nLine 2 Modified\nLine 3',
includeFormattedOutput: true
}
})
expect(response).toHaveProperty('result')
expect(response.result).toHaveProperty('content')
expect(response.result.content).toHaveLength(1)
expect(response.result.content[0]).toHaveProperty('type', 'text')
const result = JSON.parse(response.result.content[0].text)
expect(result).toHaveProperty('identical', false)
expect(result).toHaveProperty('differences')
expect(result).toHaveProperty('statistics')
expect(result).toHaveProperty('formattedDiff')
expect(result.formattedDiff).toContain('```diff')
})
it('should handle identical texts in detailed diff', async () => {
const response = await sendRequest('tools/call', {
name: 'get_detailed_diff',
arguments: {
text1: 'Hello World',
text2: 'Hello World'
}
})
const result = JSON.parse(response.result.content[0].text)
expect(result).toHaveProperty('identical', true)
expect(result).toHaveProperty('summary', 'Texts are identical')
expect(result.statistics.similarityPercentage).toBe(100)
})
it('should handle normalization options', async () => {
const response = await sendRequest('tools/call', {
name: 'get_detailed_diff',
arguments: {
text1: ' Hello World ',
text2: 'Hello World',
ignoreWhitespace: true
}
})
const result = JSON.parse(response.result.content[0].text)
expect(result).toHaveProperty('identical', true)
})
it('should handle case sensitivity', async () => {
const response = await sendRequest('tools/call', {
name: 'get_detailed_diff',
arguments: {
text1: 'HELLO WORLD',
text2: 'hello world',
ignoreCase: true
}
})
const result = JSON.parse(response.result.content[0].text)
expect(result).toHaveProperty('identical', true)
})
it('should handle line ending normalization', async () => {
const response = await sendRequest('tools/call', {
name: 'get_detailed_diff',
arguments: {
text1: 'Hello\r\nWorld\r\n',
text2: 'Hello\nWorld\n',
ignoreLineEndings: true
}
})
const result = JSON.parse(response.result.content[0].text)
expect(result).toHaveProperty('identical', true)
})
it('should reject unknown tools', async () => {
try {
await sendRequest('tools/call', {
name: 'unknown_tool',
arguments: {}
})
throw new Error('Expected error but got success')
} catch (error) {
expect(error).toBeDefined()
}
})
it('should reject invalid requests', async () => {
try {
await sendRequest('tools/call', {
name: 'compare_texts',
arguments: {
text1: 'Hello'
// missing text2
}
})
throw new Error('Expected error but got success')
} catch (error) {
expect(error).toBeDefined()
}
})
it('should handle empty strings', async () => {
const response = await sendRequest('tools/call', {
name: 'compare_texts',
arguments: {
text1: '',
text2: ''
}
})
const result = JSON.parse(response.result.content[0].text)
expect(result).toHaveProperty('identical', true)
})
it('should handle large texts', async () => {
const largeText = 'Hello World\n'.repeat(1000)
const response = await sendRequest('tools/call', {
name: 'get_detailed_diff',
arguments: {
text1: largeText,
text2: largeText + '!'
}
})
const result = JSON.parse(response.result.content[0].text)
expect(result).toHaveProperty('identical', false)
expect(result.statistics.addedLines).toBe(1)
})
})