- Create tests/ directory for integration/manual test scripts - Move test-mcp.mjs, test-real-video.mjs, test-bilibili.mjs to tests/ - Keep unit tests in src/__tests__/ (Jest convention) - Update CHANGELOG.md
216 lines
6.6 KiB
JavaScript
Executable File
216 lines
6.6 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
||
/**
|
||
* Real-world MCP server test with actual YouTube video
|
||
* Tests multiple tools with https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
||
*/
|
||
|
||
import { spawn } from 'child_process';
|
||
import { fileURLToPath } from 'url';
|
||
import { dirname, join } from 'path';
|
||
|
||
const __filename = fileURLToPath(import.meta.url);
|
||
const __dirname = dirname(__filename);
|
||
|
||
const serverPath = join(__dirname, 'lib', 'index.mjs');
|
||
const TEST_VIDEO = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
|
||
|
||
console.log('🎬 Testing yt-dlp MCP Server with Real Video\n');
|
||
console.log('Video:', TEST_VIDEO);
|
||
console.log('Starting server from:', serverPath, '\n');
|
||
|
||
const server = spawn('node', [serverPath]);
|
||
|
||
let testsPassed = 0;
|
||
let testsFailed = 0;
|
||
let responseBuffer = '';
|
||
let requestId = 0;
|
||
let currentTest = '';
|
||
|
||
// Timeout to ensure tests complete
|
||
const timeout = setTimeout(() => {
|
||
console.log('\n⏱️ Test timeout - killing server');
|
||
server.kill();
|
||
printResults();
|
||
}, 60000); // 60 seconds for real API calls
|
||
|
||
function printResults() {
|
||
clearTimeout(timeout);
|
||
console.log(`\n${'='.repeat(60)}`);
|
||
console.log(`📊 Final Test Results:`);
|
||
console.log(` ✅ Passed: ${testsPassed}`);
|
||
console.log(` ❌ Failed: ${testsFailed}`);
|
||
console.log(`${'='.repeat(60)}`);
|
||
process.exit(testsFailed > 0 ? 1 : 0);
|
||
}
|
||
|
||
server.stdout.on('data', (data) => {
|
||
responseBuffer += data.toString();
|
||
|
||
// Try to parse JSON-RPC responses
|
||
const lines = responseBuffer.split('\n');
|
||
responseBuffer = lines.pop() || '';
|
||
|
||
lines.forEach(line => {
|
||
if (line.trim()) {
|
||
try {
|
||
const response = JSON.parse(line);
|
||
|
||
if (response.error) {
|
||
console.log(`❌ ${currentTest} - ERROR`);
|
||
console.log(' Error:', response.error.message);
|
||
testsFailed++;
|
||
} else if (response.result) {
|
||
handleTestResult(response);
|
||
}
|
||
} catch (e) {
|
||
// Not JSON, might be regular output
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
server.stderr.on('data', (data) => {
|
||
const output = data.toString().trim();
|
||
if (output && !output.includes('ExperimentalWarning')) {
|
||
console.log('🔧 Server:', output);
|
||
}
|
||
});
|
||
|
||
server.on('close', (code) => {
|
||
printResults();
|
||
});
|
||
|
||
function handleTestResult(response) {
|
||
const content = response.result.content?.[0]?.text || JSON.stringify(response.result);
|
||
|
||
if (currentTest === 'Initialize') {
|
||
console.log('✅ Initialize - PASSED');
|
||
console.log(` Protocol: ${response.result.protocolVersion}`);
|
||
console.log(` Server: ${response.result.serverInfo.name} v${response.result.serverInfo.version}\n`);
|
||
testsPassed++;
|
||
}
|
||
else if (currentTest === 'Get Metadata Summary') {
|
||
if (content.includes('Rick Astley') || content.includes('Never Gonna Give You Up')) {
|
||
console.log('✅ Get Metadata Summary - PASSED');
|
||
console.log(' Response preview:');
|
||
const lines = content.split('\n').slice(0, 5);
|
||
lines.forEach(line => console.log(` ${line}`));
|
||
console.log(' ...\n');
|
||
testsPassed++;
|
||
} else {
|
||
console.log('❌ Get Metadata Summary - FAILED');
|
||
console.log(' Expected Rick Astley content, got:', content.substring(0, 100));
|
||
testsFailed++;
|
||
}
|
||
}
|
||
else if (currentTest === 'List Subtitle Languages') {
|
||
if (content.includes('en') || content.includes('English')) {
|
||
console.log('✅ List Subtitle Languages - PASSED');
|
||
console.log(' Found subtitle languages\n');
|
||
testsPassed++;
|
||
} else {
|
||
console.log('❌ List Subtitle Languages - FAILED');
|
||
console.log(' Response:', content.substring(0, 200));
|
||
testsFailed++;
|
||
}
|
||
}
|
||
else if (currentTest === 'Get Metadata (Filtered)') {
|
||
try {
|
||
const metadata = JSON.parse(content);
|
||
if (metadata.title && metadata.channel) {
|
||
console.log('✅ Get Metadata (Filtered) - PASSED');
|
||
console.log(` Title: ${metadata.title}`);
|
||
console.log(` Channel: ${metadata.channel}`);
|
||
console.log(` Duration: ${metadata.duration || 'N/A'}\n`);
|
||
testsPassed++;
|
||
} else {
|
||
console.log('❌ Get Metadata (Filtered) - FAILED');
|
||
console.log(' Missing expected fields');
|
||
testsFailed++;
|
||
}
|
||
} catch (e) {
|
||
console.log('❌ Get Metadata (Filtered) - FAILED');
|
||
console.log(' Invalid JSON response');
|
||
testsFailed++;
|
||
}
|
||
}
|
||
else if (currentTest === 'Download Transcript (first 500 chars)') {
|
||
if (content.length > 100) {
|
||
console.log('✅ Download Transcript - PASSED');
|
||
console.log(' Transcript length:', content.length, 'characters');
|
||
console.log(' Preview:', content.substring(0, 150).replace(/\n/g, ' ') + '...\n');
|
||
testsPassed++;
|
||
} else {
|
||
console.log('❌ Download Transcript - FAILED');
|
||
console.log(' Response too short:', content.substring(0, 100));
|
||
testsFailed++;
|
||
}
|
||
}
|
||
}
|
||
|
||
function sendRequest(method, params, testName) {
|
||
requestId++;
|
||
currentTest = testName;
|
||
console.log(`🔍 Test ${requestId}: ${testName}`);
|
||
|
||
const request = {
|
||
jsonrpc: '2.0',
|
||
id: requestId,
|
||
method: method,
|
||
params: params
|
||
};
|
||
|
||
server.stdin.write(JSON.stringify(request) + '\n');
|
||
}
|
||
|
||
// Run tests sequentially with delays
|
||
setTimeout(() => {
|
||
// Test 1: Initialize
|
||
sendRequest('initialize', {
|
||
protocolVersion: '2024-11-05',
|
||
capabilities: {},
|
||
clientInfo: { name: 'test-client', version: '1.0.0' }
|
||
}, 'Initialize');
|
||
|
||
setTimeout(() => {
|
||
// Test 2: Get video metadata summary
|
||
sendRequest('tools/call', {
|
||
name: 'ytdlp_get_video_metadata_summary',
|
||
arguments: { url: TEST_VIDEO }
|
||
}, 'Get Metadata Summary');
|
||
|
||
setTimeout(() => {
|
||
// Test 3: List subtitle languages
|
||
sendRequest('tools/call', {
|
||
name: 'ytdlp_list_subtitle_languages',
|
||
arguments: { url: TEST_VIDEO }
|
||
}, 'List Subtitle Languages');
|
||
|
||
setTimeout(() => {
|
||
// Test 4: Get specific metadata fields
|
||
sendRequest('tools/call', {
|
||
name: 'ytdlp_get_video_metadata',
|
||
arguments: {
|
||
url: TEST_VIDEO,
|
||
fields: ['id', 'title', 'channel', 'duration', 'view_count']
|
||
}
|
||
}, 'Get Metadata (Filtered)');
|
||
|
||
setTimeout(() => {
|
||
// Test 5: Download transcript (might take longer)
|
||
console.log(' (This may take 10-20 seconds...)\n');
|
||
sendRequest('tools/call', {
|
||
name: 'ytdlp_download_transcript',
|
||
arguments: { url: TEST_VIDEO, language: 'en' }
|
||
}, 'Download Transcript (first 500 chars)');
|
||
|
||
setTimeout(() => {
|
||
console.log('\n✅ All tests completed!');
|
||
server.kill();
|
||
}, 25000); // Wait 25 seconds for transcript
|
||
}, 3000);
|
||
}, 5000);
|
||
}, 5000);
|
||
}, 2000);
|
||
}, 1000);
|