-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathtest_docs_mcp_reference_guide.py
More file actions
337 lines (271 loc) · 13.9 KB
/
Copy pathtest_docs_mcp_reference_guide.py
File metadata and controls
337 lines (271 loc) · 13.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
"""
Comprehensive tests for the get_reference_guide tool in the documentation MCP server.
Tests the get_reference_guide tool functionality and all docstring examples.
"""
import pytest
from fastmcp import Client
from holoviz_mcp.holoviz_mcp.server import mcp
pytestmark = pytest.mark.integration
@pytest.mark.asyncio
async def test_get_reference_guide_button_no_project():
"""Test get_reference_guide for Button component across all projects."""
client = Client(mcp)
async with client:
result = await client.call_tool("get_reference_guide", {"component": "Button"})
assert result.data
assert isinstance(result.data, list)
# Should find Button components from various projects
for document in result.data:
assert "title" in document
assert "url" in document
assert "project" in document
assert "source_path" in document
assert "source_url" in document
assert "content" in document
assert document["relevance_score"] == 1.0
# Should find at least one result
assert len(result.data) > 0
@pytest.mark.asyncio
async def test_get_reference_guide_button_panel_specific():
"""Test get_reference_guide finds the one and only Button reference guide in Panel project specifically."""
client = Client(mcp)
async with client:
result = await client.call_tool("get_reference_guide", {"component": "Button", "project": "panel"})
assert isinstance(result.data, list)
assert len(result.data) == 1, "Should find exactly one Button reference guide"
document = result.data[0]
assert document["source_path"] == "examples/reference/widgets/Button.ipynb"
assert document["source_url"] == "https://github.com/holoviz/panel/blob/main/examples/reference/widgets/Button.ipynb"
assert document["project"] == "panel"
assert document["title"] == "Button"
assert document["url"] == "https://panel.holoviz.org/reference/widgets/Button.html"
assert document["relevance_score"] == 1.0
@pytest.mark.asyncio
async def test_get_reference_guide_button_panel_material_ui_specific():
"""Test get_reference_guide finds the one and only Button reference guide in Panel Material UI project specifically."""
client = Client(mcp)
async with client:
result = await client.call_tool("get_reference_guide", {"component": "Button", "project": "panel-material-ui"})
assert isinstance(result.data, list)
assert len(result.data) == 1, "Should find exactly one Button reference guide"
document = result.data[0]
assert document["source_path"] == "examples/reference/widgets/Button.ipynb"
assert document["source_url"] == "https://github.com/panel-extensions/panel-material-ui/blob/main/examples/reference/widgets/Button.ipynb"
assert document["project"] == "panel-material-ui"
assert document["title"] == "Button"
assert document["url"] == "https://panel-material-ui.holoviz.org/reference/widgets/Button.html"
assert document["relevance_score"] == 1.0
@pytest.mark.asyncio
async def test_get_reference_guide_textinput_material_ui():
"""Test get_reference_guide for TextInput component in Material UI project."""
client = Client(mcp)
async with client:
result = await client.call_tool("get_reference_guide", {"component": "TextInput", "project": "panel-material-ui"})
assert result.data
assert isinstance(result.data, list)
assert len(result.data) == 1
document = result.data[0]
assert document["project"] == "panel-material-ui"
assert document["source_path"] == "examples/reference/widgets/TextInput.ipynb"
assert document["source_url"] == "https://github.com/panel-extensions/panel-material-ui/blob/main/examples/reference/widgets/TextInput.ipynb"
assert document["relevance_score"] == 1.0
@pytest.mark.asyncio
async def test_get_reference_guide_bar_hvplot():
"""Test get_reference_guide for bar chart component in hvPlot project."""
client = Client(mcp)
async with client:
result = await client.call_tool("get_reference_guide", {"component": "bar", "project": "hvplot"})
assert isinstance(result.data, list)
# Skip detailed assertions if no results found (may happen if docs not indexed)
if not result.data:
pytest.skip("hvplot bar reference documentation not found in index")
assert len(result.data) >= 1
# All results should be from hvplot project
for document in result.data:
assert document["project"] == "hvplot"
assert document["source_path"].startswith("doc/reference")
assert document["source_path"].endswith("bar.ipynb")
assert document["source_url"].endswith("bar.ipynb")
assert document["is_reference"] == True
@pytest.mark.asyncio
async def test_get_reference_guide_scatter_hvplot():
"""Test get_reference_guide for scatter plot component in hvPlot project."""
client = Client(mcp)
async with client:
result = await client.call_tool("get_reference_guide", {"component": "scatter", "project": "hvplot"})
assert isinstance(result.data, list)
# Skip detailed assertions if no results found (may happen if docs not indexed)
if not result.data:
pytest.skip("hvplot scatter reference documentation not found in index")
# All results should be from hvplot project
for document in result.data:
assert document["project"] == "hvplot"
# Should find at least one result
assert len(result.data) > 0
@pytest.mark.asyncio
async def test_get_reference_guide_audio_no_content():
"""Test get_reference_guide for Audio component with content=False for faster response."""
client = Client(mcp)
async with client:
result = await client.call_tool("get_reference_guide", {"component": "Audio", "content": False})
assert result.data
assert isinstance(result.data, list)
# Verify each result has metadata but no content
for document in result.data:
assert "title" in document
assert "url" in document
assert "project" in document
assert "source_path" in document
assert "source_url" in document
# Should not include content when content=False
assert document.get("content") is None
# Should find at least one result
assert len(result.data) > 0
@pytest.mark.asyncio
async def test_get_reference_guide_common_widgets():
"""Test get_reference_guide for common Panel widgets."""
client = Client(mcp)
async with client:
# Test various common widget types
widgets = ["DiscreteSlider", "Select", "Checkbox", "Toggle", "DatePicker"]
for widget in widgets:
result = await client.call_tool("get_reference_guide", {"component": widget, "project": "panel"})
assert result.data
assert isinstance(result.data, list)
# Should find relevant documentation for each widget
for document in result.data:
assert document["project"] == "panel"
assert document["is_reference"]
# Should find at least one result
assert len(result.data) == 1
@pytest.mark.asyncio
async def test_get_reference_guide_edge_cases():
"""Test get_reference_guide with edge cases."""
client = Client(mcp)
async with client:
# Test with non-existent component
result = await client.call_tool("get_reference_guide", {"component": "NonExistentWidget123"})
# Should handle gracefully
assert isinstance(result.data, list)
# Test with empty component name
result = await client.call_tool("get_reference_guide", {"component": ""})
# Should handle gracefully
assert isinstance(result.data, list)
# Test with invalid project
result = await client.call_tool("get_reference_guide", {"component": "Button", "project": "nonexistent_project"})
# Should handle gracefully and return empty results
assert isinstance(result.data, list)
assert len(result.data) == 0
@pytest.mark.asyncio
async def test_get_reference_guide_relevance_scoring():
"""Test that get_reference_guide returns results with relevance scores."""
client = Client(mcp)
async with client:
result = await client.call_tool("get_reference_guide", {"component": "Button", "project": "panel"})
assert result.data
assert isinstance(result.data, list)
# Should have relevance scores (can be negative for poor matches)
for document in result.data:
if "relevance_score" in document and document["relevance_score"] is not None:
# Relevance score should be a float
assert isinstance(document["relevance_score"], float)
# Results should be sorted by relevance (highest first)
scores = [document.get("relevance_score", 0) for document in result.data if document.get("relevance_score") is not None]
if len(scores) > 1:
assert scores == sorted(scores, reverse=True)
@pytest.mark.asyncio
async def test_get_reference_guide_return_structure():
"""Test that get_reference_guide returns properly structured Documents."""
client = Client(mcp)
async with client:
result = await client.call_tool("get_reference_guide", {"component": "Button", "project": "panel"})
assert result.data
assert isinstance(result.data, list)
# Verify structure of each returned Document
for document in result.data:
# Required fields
assert "title" in document
assert "url" in document
assert "project" in document
assert "source_path" in document
assert "source_url" in document
# Optional fields
assert "description" in document # Can be None
assert "content" in document # Should be present when content=True (default)
assert "relevance_score" in document # Can be None
# Type checks
assert isinstance(document["title"], str)
assert isinstance(document["url"], str)
assert isinstance(document["project"], str)
assert isinstance(document["source_path"], str)
assert isinstance(document["source_url"], str)
# URL should be valid
assert document["url"].startswith("http")
assert document["source_url"].startswith("http")
# Project should be one of the known projects
known_projects = ["panel", "panel-material-ui", "hvplot", "param", "holoviews"]
assert document["project"] in known_projects
@pytest.mark.asyncio
async def test_get_reference_guide_maximum_results():
"""Test that get_reference_guide returns at most 5 results."""
client = Client(mcp)
async with client:
result = await client.call_tool(
"get_reference_guide",
{
"component": "Button" # Common component that should have many results
},
)
assert result.data
assert isinstance(result.data, list)
# Should return at most 5 results
assert len(result.data) <= 5
@pytest.mark.asyncio
async def test_get_reference_guide_no_duplicates():
"""Test that get_reference_guide doesn't return duplicate results."""
client = Client(mcp)
async with client:
result = await client.call_tool("get_reference_guide", {"component": "Button", "project": "panel"})
assert result.data
assert isinstance(result.data, list)
# Check for duplicate URLs
urls = [document["url"] for document in result.data]
assert len(urls) == len(set(urls)), "Found duplicate URLs in results"
# Check for duplicate paths
paths = [document["source_path"] for document in result.data]
assert len(paths) == len(set(paths)), "Found duplicate paths in results"
# Check for duplicate source urls
source_urls = [document["source_url"] for document in result.data]
assert len(source_urls) == len(set(source_urls)), "Found duplicate source URLs in results"
@pytest.mark.asyncio
async def test_get_reference_guide_multiple_projects():
"""Test that get_reference_guide can find components across multiple projects."""
client = Client(mcp)
async with client:
# Search for Button across all projects
result = await client.call_tool("get_reference_guide", {"component": "Button"})
assert result.data
assert isinstance(result.data, list)
# Should find Button components from different projects
projects_found = set(document["project"] for document in result.data)
assert len(projects_found) >= 1 # Should find at least one project with Button
# Common projects that should have Button components
expected_projects = {"panel", "panel_material_ui"}
assert len(projects_found.intersection(expected_projects)) > 0
@pytest.mark.asyncio
async def test_get_reference_guide_exact_filename_matching():
"""Test that get_reference_guide prioritizes exact filename matches."""
client = Client(mcp)
async with client:
# Test that searching for "Button" finds files with "Button" in the filename
result = await client.call_tool("get_reference_guide", {"component": "ButtonIcon", "project": "panel"})
assert result.data
assert isinstance(result.data, list)
assert len(result.data) == 1
guide = result.data[0]
assert guide["project"] == "panel"
assert guide["source_path"] == "examples/reference/widgets/ButtonIcon.ipynb"
assert guide["url"] == "https://panel.holoviz.org/reference/widgets/ButtonIcon.html"
assert guide["is_reference"]
assert guide["title"] == "Buttonicon"
assert guide["relevance_score"] == 1.0 # Highest priority score