serper-search-scrape-mcp-server
Version:
Serper MCP Server supporting search and webpage scraping
165 lines (164 loc) • 6.68 kB
JavaScript
import { SerperSearchTools } from '../search-tool.js';
import { SerperClient } from '../../services/serper-client.js';
// Mock SerperClient
jest.mock('../../services/serper-client.js');
describe('SerperSearchTools', () => {
let mockSerperClient;
let searchTools;
beforeEach(() => {
mockSerperClient = new SerperClient('mock-key');
searchTools = new SerperSearchTools(mockSerperClient);
});
describe('search', () => {
const mockSearchParams = {
q: 'test query',
gl: 'us',
hl: 'en'
};
const mockSearchResult = {
searchParameters: {
q: 'test query',
gl: 'us',
hl: 'en'
},
organic: [
{
title: 'Test Result',
link: 'https://test.com',
snippet: 'Test snippet',
position: 1
}
]
};
it('should call SerperClient.search with correct parameters', async () => {
mockSerperClient.search.mockResolvedValueOnce(mockSearchResult);
const result = await searchTools.search(mockSearchParams);
expect(mockSerperClient.search).toHaveBeenCalledWith(mockSearchParams);
expect(result).toEqual(mockSearchResult);
});
it('should handle optional parameters correctly', async () => {
const paramsWithOptional = {
...mockSearchParams,
num: 5,
tbs: 'qdr:d',
location: 'New York',
autocorrect: true
};
mockSerperClient.search.mockResolvedValueOnce({
...mockSearchResult,
searchParameters: paramsWithOptional
});
const result = await searchTools.search(paramsWithOptional);
expect(mockSerperClient.search).toHaveBeenCalledWith(paramsWithOptional);
expect(result.searchParameters).toEqual(paramsWithOptional);
});
it('should handle errors from SerperClient', async () => {
const error = new Error('API Error');
mockSerperClient.search.mockRejectedValueOnce(error);
await expect(searchTools.search(mockSearchParams))
.rejects
.toThrow(error);
});
});
describe('batchSearch', () => {
const mockBatchParams = [
{
q: 'query1',
gl: 'us',
hl: 'en'
},
{
q: 'query2',
gl: 'uk',
hl: 'en'
}
];
const mockBatchResult = [
{
searchParameters: { q: 'query1', gl: 'us', hl: 'en' },
organic: [{
title: 'Result 1',
link: 'https://test1.com',
position: 1,
snippet: 'Test snippet 1'
}]
},
{
searchParameters: { q: 'query2', gl: 'uk', hl: 'en' },
organic: [{
title: 'Result 2',
link: 'https://test2.com',
position: 1,
snippet: 'Test snippet 2'
}]
}
];
it('should call SerperClient.batchSearch with correct parameters', async () => {
mockSerperClient.batchSearch.mockResolvedValueOnce(mockBatchResult);
const result = await searchTools.batchSearch(mockBatchParams);
expect(mockSerperClient.batchSearch).toHaveBeenCalledWith(mockBatchParams);
expect(result).toEqual(mockBatchResult);
});
it('should handle errors from SerperClient in batch search', async () => {
const error = new Error('Batch API Error');
mockSerperClient.batchSearch.mockRejectedValueOnce(error);
await expect(searchTools.batchSearch(mockBatchParams))
.rejects
.toThrow(error);
});
});
describe('Integration Tests', () => {
// Note: These tests require a valid API key and will make real API calls
// They are disabled by default and should be run manually when needed
const realClient = new SerperClient(process.env.SERPER_API_KEY || '');
const realSearchTools = new SerperSearchTools(realClient);
describe('search', () => {
it.skip('should perform a real search with all optional parameters', async () => {
const params = {
q: 'Latest AI developments',
gl: 'us',
hl: 'en',
num: 5,
tbs: 'qdr:d',
location: 'Silicon Valley',
autocorrect: true
};
const result = await realSearchTools.search(params);
expect(result).toBeDefined();
expect(result.searchParameters).toEqual(params);
expect(Array.isArray(result.organic)).toBe(true);
expect(result.organic.length).toBeLessThanOrEqual(params.num || 10);
}, 10000);
});
describe('batchSearch', () => {
it.skip('should perform a real batch search with varied parameters', async () => {
const batchParams = [
{
q: 'Web Development 2024',
gl: 'us',
hl: 'en',
num: 3,
tbs: 'qdr:m'
},
{
q: 'Cloud Computing Trends',
gl: 'uk',
hl: 'en',
num: 3,
location: 'London'
}
];
const result = await realSearchTools.batchSearch(batchParams);
expect(result).toBeDefined();
expect(Array.isArray(result)).toBe(true);
expect(result.length).toBe(2);
// Check first query results
expect(result[0].searchParameters).toEqual(batchParams[0]);
expect(result[0].organic.length).toBeLessThanOrEqual(batchParams[0].num || 10);
// Check second query results
expect(result[1].searchParameters).toEqual(batchParams[1]);
expect(result[1].organic.length).toBeLessThanOrEqual(batchParams[1].num || 10);
}, 15000);
});
});
});