blob: 59668778d35a71f6a33b6ff8cddd3efcb50d11b0 [file] [log] [blame]
package tools
import (
"context"
"testing"
"github.com/korap/korap-mcp/service"
"github.com/mark3labs/mcp-go/mcp"
"github.com/stretchr/testify/assert"
)
func TestSearchTool_Name(t *testing.T) {
client := &service.Client{}
tool := NewSearchTool(client)
assert.Equal(t, "korap_search", tool.Name())
}
func TestSearchTool_Description(t *testing.T) {
client := &service.Client{}
tool := NewSearchTool(client)
expected := "Search for words or phrases in KorAP corpora using various query languages"
assert.Equal(t, expected, tool.Description())
}
func TestSearchTool_InputSchema(t *testing.T) {
client := &service.Client{}
tool := NewSearchTool(client)
schema := tool.InputSchema()
// Verify it's an object type
assert.Equal(t, "object", schema["type"])
// Verify properties exist
properties, ok := schema["properties"].(map[string]interface{})
assert.True(t, ok)
assert.Contains(t, properties, "query")
assert.Contains(t, properties, "query_language")
assert.Contains(t, properties, "corpus")
assert.Contains(t, properties, "count")
// Note: offset and context will be added in future iterations
// Verify required fields
required, ok := schema["required"].([]string)
assert.True(t, ok)
assert.Contains(t, required, "query")
}
func TestNewSearchTool(t *testing.T) {
client := &service.Client{}
tool := NewSearchTool(client)
assert.NotNil(t, tool)
assert.Equal(t, client, tool.client)
}
func TestSearchTool_Execute_MissingQuery(t *testing.T) {
client := &service.Client{}
tool := NewSearchTool(client)
// Create request without query parameter
request := mcp.CallToolRequest{
Params: mcp.CallToolParams{
Arguments: map[string]interface{}{},
},
}
_, err := tool.Execute(context.Background(), request)
assert.Error(t, err)
assert.Contains(t, err.Error(), "query parameter is required")
}
func TestSearchTool_Execute_NilClient(t *testing.T) {
tool := NewSearchTool(nil)
request := mcp.CallToolRequest{
Params: mcp.CallToolParams{
Arguments: map[string]interface{}{
"query": "test",
},
},
}
_, err := tool.Execute(context.Background(), request)
assert.Error(t, err)
assert.Contains(t, err.Error(), "KorAP client not configured")
}
func TestSearchTool_Execute_ParameterExtraction(t *testing.T) {
// This test verifies that parameters are extracted correctly
// It should fail with authentication error since we don't have a mock server
// but we can verify the parameters were parsed correctly by checking the log messages
client := &service.Client{}
tool := NewSearchTool(client)
tests := []struct {
name string
arguments map[string]interface{}
expectErr bool
}{
{
name: "minimal_query",
arguments: map[string]interface{}{
"query": "test",
},
expectErr: true, // Will fail at authentication
},
{
name: "full_parameters",
arguments: map[string]interface{}{
"query": "word",
"query_language": "cosmas2",
"corpus": "test-corpus",
"count": 10,
},
expectErr: true, // Will fail at authentication
},
{
name: "invalid_count_type",
arguments: map[string]interface{}{
"query": "test",
"count": "invalid", // Should use default
},
expectErr: true, // Will fail at authentication
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
request := mcp.CallToolRequest{
Params: mcp.CallToolParams{
Arguments: tt.arguments,
},
}
_, err := tool.Execute(context.Background(), request)
if tt.expectErr {
assert.Error(t, err)
}
})
}
}
func TestSearchTool_formatSearchResults(t *testing.T) {
client := &service.Client{}
tool := NewSearchTool(client)
// Test empty response
emptyResponse := &service.SearchResponse{
Query: service.SearchQuery{
Query: "test",
QueryLang: "poliqarp",
},
Meta: service.SearchMeta{
TotalResults: 0,
Count: 0,
StartIndex: 0,
},
Matches: []service.SearchMatch{},
}
result := tool.formatSearchResults(emptyResponse)
assert.Contains(t, result, "KorAP Search Results")
assert.Contains(t, result, "Query: test")
assert.Contains(t, result, "Query Language: poliqarp")
assert.Contains(t, result, "Total Results: 0")
assert.Contains(t, result, "No matches found")
// Test response with matches
responseWithMatches := &service.SearchResponse{
Query: service.SearchQuery{
Query: "word",
QueryLang: "poliqarp",
Collection: "test-corpus",
},
Meta: service.SearchMeta{
TotalResults: 5,
Count: 2,
StartIndex: 0,
SearchTime: 0.123,
},
Matches: []service.SearchMatch{
{
TextSigle: "text1",
Snippet: "This is a test snippet",
PubPlace: "Berlin",
MatchID: "match1",
Position: 10,
},
{
TextSigle: "text2",
Snippet: "Another test snippet",
Position: 25,
},
},
}
result = tool.formatSearchResults(responseWithMatches)
assert.Contains(t, result, "Query: word")
assert.Contains(t, result, "Query Language: poliqarp")
assert.Contains(t, result, "Corpus: test-corpus")
assert.Contains(t, result, "Total Results: 5")
assert.Contains(t, result, "Shown: 1-2")
assert.Contains(t, result, "Search Time: 0.123 seconds")
assert.Contains(t, result, "1. Text: text1")
assert.Contains(t, result, "Snippet: This is a test snippet")
assert.Contains(t, result, "Publication: Berlin")
assert.Contains(t, result, "2. Text: text2")
assert.Contains(t, result, "Position: 25")
// Test response with warnings
responseWithWarnings := &service.SearchResponse{
Query: service.SearchQuery{
Query: "test",
CutOff: true,
TimeExceeded: true,
},
Meta: service.SearchMeta{},
Matches: []service.SearchMatch{},
}
result = tool.formatSearchResults(responseWithWarnings)
assert.Contains(t, result, "Results were cut off due to limits")
assert.Contains(t, result, "Search time limit was exceeded")
}