Skip to main content
Glama

MCP DuckDuckGo Search Plugin

test_tools.py7.21 kB
""" Tests for the DuckDuckGo search tools. These tests verify that the MCP tools for DuckDuckGo search work correctly. """ import pytest from unittest.mock import AsyncMock, patch, MagicMock import json # Import the tools module containing the MCP tools from mcp_duckduckgo.tools import duckduckgo_web_search, duckduckgo_get_details, duckduckgo_related_searches from mcp_duckduckgo.models import SearchResponse, DetailedResult @pytest.mark.asyncio async def test_duckduckgo_web_search(mock_context, mock_search_function): """Test the duckduckgo_web_search tool.""" # Mock the search function with patch('mcp_duckduckgo.tools.duckduckgo_search', mock_search_function): # Call the tool result = await duckduckgo_web_search( query="test query", count=5, page=1, site=None, time_period=None, ctx=mock_context ) # Verify the result assert isinstance(result, SearchResponse) assert len(result.results) == 2 # Based on the sample data in conftest.py assert result.total_results == 2 assert result.page == 1 # Check the first result first_result = result.results[0] assert first_result.title == "Example Page 1" assert first_result.url == "https://example.com/page1" assert first_result.description == "This is a description for Example Page 1" # Domain is included in result dict but not as a property in SearchResult model # assert first_result.domain == "example.com" @pytest.mark.asyncio async def test_duckduckgo_web_search_with_site_filter(mock_context, mock_search_function): """Test the duckduckgo_web_search tool with site filter.""" # Mock the search function to capture params mock_search_params = None async def capture_params(params, ctx): nonlocal mock_search_params mock_search_params = params return await mock_search_function(params, ctx) with patch('mcp_duckduckgo.tools.duckduckgo_search', capture_params): # Call the tool with site filter await duckduckgo_web_search( query="test query", count=5, page=1, site="example.com", time_period=None, ctx=mock_context ) # Verify that site filter was correctly applied to the query assert mock_search_params is not None assert mock_search_params["query"] == "test query site:example.com" @pytest.mark.asyncio async def test_duckduckgo_web_search_with_time_filter(mock_context, mock_search_function): """Test the duckduckgo_web_search tool with time filter.""" # Mock the search function to capture params mock_search_params = None async def capture_params(params, ctx): nonlocal mock_search_params mock_search_params = params return await mock_search_function(params, ctx) with patch('mcp_duckduckgo.tools.duckduckgo_search', capture_params): # Call the tool with time filter await duckduckgo_web_search( query="test query", count=5, page=1, site=None, time_period="week", ctx=mock_context ) # Verify that time filter was correctly applied assert mock_search_params is not None assert "date:w" in mock_search_params["query"] @pytest.mark.asyncio async def test_duckduckgo_web_search_pagination(mock_context, mock_search_function): """Test the duckduckgo_web_search tool with pagination.""" # Mock the search function to capture params mock_search_params = None async def capture_params(params, ctx): nonlocal mock_search_params mock_search_params = params return await mock_search_function(params, ctx) with patch('mcp_duckduckgo.tools.duckduckgo_search', capture_params): # Call the tool with pagination await duckduckgo_web_search( query="test query", count=5, page=3, # Page 3 site=None, time_period=None, ctx=mock_context ) # Verify that pagination was correctly applied assert mock_search_params is not None assert mock_search_params["offset"] == 10 # (page-1) * count @pytest.mark.asyncio async def test_duckduckgo_web_search_error_handling(mock_context): """Test error handling in the duckduckgo_web_search tool.""" # Mock the search function to raise an exception async def mock_error(*args, **kwargs): raise ValueError("Test error") # Mock the error reporting method mock_context.error = AsyncMock() with patch('mcp_duckduckgo.tools.duckduckgo_search', mock_error): # In the actual implementation, errors are caught and an empty result is returned # with error logging, not raising the exception result = await duckduckgo_web_search( query="test query", count=5, page=1, site=None, time_period=None, ctx=mock_context ) # Verify error was reported assert mock_context.error.called # Check that we got a fallback empty result assert isinstance(result, SearchResponse) assert len(result.results) == 0 @pytest.mark.asyncio async def test_duckduckgo_get_details(mock_context): """Test the duckduckgo_get_details tool.""" # The implementation doesn't actually make HTTP requests, it just creates a # placeholder DetailedResult with the domain extracted from the URL # Call the tool url = "https://example.com/page" result = await duckduckgo_get_details( url=url, ctx=mock_context ) # Verify the result assert isinstance(result, DetailedResult) assert result.url == url assert result.domain == "example.com" assert result.content_snippet == "Content not available" # Default placeholder @pytest.mark.asyncio async def test_duckduckgo_related_searches(mock_context): """Test the duckduckgo_related_searches tool.""" # The implementation doesn't make HTTP requests, it generates placeholder related searches # Call the tool query = "test query" count = 5 result = await duckduckgo_related_searches( query=query, count=count, ctx=mock_context ) # Verify the result assert isinstance(result, list) assert len(result) == count # Check that the related searches are based on the query for related_search in result: assert query in related_search.lower() @pytest.mark.asyncio async def test_duckduckgo_related_searches_count(mock_context): """Test the duckduckgo_related_searches tool with different counts.""" # Test with different counts for count in [1, 3, 7, 10]: result = await duckduckgo_related_searches( query="test query", count=count, ctx=mock_context ) # Verify the count assert len(result) == count

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gianlucamazza/mcp-duckduckgo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server