1+ import pytest
2+ import json
3+ from pathlib import Path
4+ from unittest .mock import patch , mock_open , MagicMock
5+ from fastapi_mcp .documentation_tools import (
6+ _get_file_priority ,
7+ _prioritize_files ,
8+ _collect_documentation_files ,
9+ _read_documentation_files ,
10+ ContentItem ,
11+ DocumentationResponse ,
12+ create_documentation_tools ,
13+ )
14+ from mcp .server .fastmcp import FastMCP
15+
16+
17+ def test_get_file_priority ():
18+ """Test the file priority system"""
19+ llms_file = Path ("llms.txt" )
20+ readme_file = Path ("README.md" )
21+ other_file = Path ("documentation.md" )
22+
23+ assert _get_file_priority (llms_file ) == 0 # Highest priority
24+ assert _get_file_priority (readme_file ) == 1 # Second priority
25+ assert _get_file_priority (other_file ) == 2 # Lowest priority
26+
27+
28+ def test_prioritize_files ():
29+ """Test the file prioritization logic"""
30+ llms_file = Path ("llms.txt" )
31+ readme_file = Path ("README.md" )
32+ other_file = Path ("documentation.md" )
33+
34+ # Test with mixed priority files
35+ files = [other_file , readme_file , llms_file ]
36+ prioritized = _prioritize_files (files )
37+ assert len (prioritized ) == 1
38+ assert prioritized [0 ] == llms_file
39+
40+ # Test with only readme and other files
41+ files = [other_file , readme_file ]
42+ prioritized = _prioritize_files (files )
43+ assert len (prioritized ) == 1
44+ assert prioritized [0 ] == readme_file
45+
46+ # Test with only other files
47+ files = [other_file ]
48+ prioritized = _prioritize_files (files )
49+ assert len (prioritized ) == 1
50+ assert prioritized [0 ] == other_file
51+
52+ # Test with empty list
53+ assert _prioritize_files ([]) == []
54+
55+
56+ def test_collect_documentation_files (tmp_path ):
57+ """Test documentation file collection using a real temporary filesystem"""
58+ # Create a docs directory with test files
59+ docs_dir = tmp_path / "docs"
60+ docs_dir .mkdir ()
61+
62+ # Create test files
63+ (docs_dir / "llms.txt" ).write_text ("LLM documentation" )
64+ (docs_dir / "README.md" ).write_text ("README content" )
65+ (docs_dir / "other.md" ).write_text ("Other documentation" )
66+
67+ # Test directory path - should return only llms.txt due to priority
68+ files = _collect_documentation_files (str (docs_dir ))
69+ assert len (files ) == 1
70+ assert files [0 ].name == "llms.txt"
71+
72+ # Test single file path
73+ single_file = docs_dir / "README.md"
74+ files = _collect_documentation_files (str (single_file ))
75+ assert len (files ) == 1
76+ assert files [0 ].name == "README.md"
77+
78+ # Test list of files
79+ file_list = [
80+ str (docs_dir / "README.md" ),
81+ str (docs_dir / "other.md" )
82+ ]
83+ files = _collect_documentation_files (file_list )
84+ assert len (files ) == 2
85+ assert {f .name for f in files } == {"README.md" , "other.md" }
86+
87+
88+ def test_read_documentation_files (tmp_path ):
89+ """Test reading documentation files from filesystem"""
90+ # Create test files with content
91+ file1 = tmp_path / "test1.md"
92+ file2 = tmp_path / "test2.md"
93+
94+ file1 .write_text ("Content 1" )
95+ file2 .write_text ("Content 2" )
96+
97+ files = [file1 , file2 ]
98+ content = _read_documentation_files (files )
99+
100+ assert len (content ) == 2
101+ assert content [0 ][0 ] == "Content 1"
102+ assert content [1 ][0 ] == "Content 2"
103+ assert content [0 ][1 ] == str (file1 )
104+ assert content [1 ][1 ] == str (file2 )
105+
106+
107+ @pytest .mark .asyncio
108+ async def test_fetch_documentation (tmp_path ):
109+ """Test the fetch_documentation tool with real files"""
110+ # Create test documentation
111+ docs_dir = tmp_path / "docs"
112+ docs_dir .mkdir ()
113+ test_content = "Test documentation content"
114+ (docs_dir / "llms.txt" ).write_text (test_content )
115+
116+ # Create and test the tool
117+ mcp = FastMCP ()
118+ create_documentation_tools (mcp , str (docs_dir ))
119+
120+ # Test the tool
121+ result = await mcp .call_tool ("fetch_documentation" , {})
122+ assert len (result ) == 1
123+ result_dict = json .loads (result [0 ].text )
124+ assert "docs" in result_dict
125+ docs = result_dict ["docs" ]
126+ assert len (docs ) == 1
127+ assert docs [0 ]["text" ] == test_content
128+ assert docs [0 ]["source" ] == str (docs_dir / "llms.txt" )
129+
130+
131+
132+ def test_documentation_response ():
133+ """Test DocumentationResponse class"""
134+ # Test normal response
135+ docs = [ContentItem (text = "test" , source = "test.md" )]
136+ response = DocumentationResponse (docs = docs )
137+ assert response .docs == docs
138+
139+ # Test error response
140+ error_response = DocumentationResponse .error ()
141+ assert len (error_response .docs ) == 1
142+ assert error_response .docs [0 ].text == "Error getting documentation"
143+
144+ # Test to_dict
145+ response_dict = response .to_dict ()
146+ assert isinstance (response_dict , dict )
147+ assert 'docs' in response_dict
0 commit comments