Jatin Mehra commited on
Commit
ff040f1
·
1 Parent(s): 21e6037

Add pytest-based test suite for RAG API endpoints

Browse files
test/test_api_endpoints.py ADDED
@@ -0,0 +1,433 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Test script for FastAPI endpoints in the RAG Chat API.
3
+ This script tests all available endpoints with various scenarios.
4
+ """
5
+
6
+ import requests
7
+ import json
8
+ import os
9
+ import sys
10
+ import tempfile
11
+ from typing import Dict, Any
12
+ import time
13
+
14
+ # Add backend to path for imports
15
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'backend'))
16
+
17
+ class RAGAPITester:
18
+ def __init__(self, base_url: str = "http://localhost:7860"):
19
+ self.base_url = base_url
20
+ self.session = requests.Session()
21
+ self.api_key = None
22
+
23
+ def test_connection(self) -> bool:
24
+ """Test if the API server is running."""
25
+ try:
26
+ response = self.session.get(f"{self.base_url}/")
27
+ return response.status_code in [200, 404] # 404 is OK if no frontend file
28
+ except requests.ConnectionError:
29
+ return False
30
+
31
+ def set_api_key(self, api_key: str) -> Dict[str, Any]:
32
+ """Test setting the GROQ API key."""
33
+ print("Testing API key setting...")
34
+ url = f"{self.base_url}/set-api-key"
35
+ payload = {"api_key": api_key}
36
+
37
+ response = self.session.post(url, json=payload)
38
+ result = {
39
+ "endpoint": "/set-api-key",
40
+ "status_code": response.status_code,
41
+ "response": response.json() if response.status_code != 500 else response.text,
42
+ "success": response.status_code == 200
43
+ }
44
+
45
+ if result["success"]:
46
+ self.api_key = api_key
47
+ print("✓ API key set successfully")
48
+ else:
49
+ print(f"✗ Failed to set API key: {result['response']}")
50
+
51
+ return result
52
+
53
+ def test_get_stats(self) -> Dict[str, Any]:
54
+ """Test getting processing statistics."""
55
+ print("Testing stats endpoint...")
56
+ url = f"{self.base_url}/stats"
57
+
58
+ response = self.session.get(url)
59
+ result = {
60
+ "endpoint": "/stats",
61
+ "status_code": response.status_code,
62
+ "response": response.json() if response.status_code == 200 else response.text,
63
+ "success": response.status_code == 200
64
+ }
65
+
66
+ if result["success"]:
67
+ print("✓ Stats retrieved successfully")
68
+ else:
69
+ print(f"✗ Failed to get stats: {result['response']}")
70
+
71
+ return result
72
+
73
+ def test_get_chat_history(self) -> Dict[str, Any]:
74
+ """Test getting chat history."""
75
+ print("Testing chat history endpoint...")
76
+ url = f"{self.base_url}/chat-history"
77
+
78
+ response = self.session.get(url)
79
+ result = {
80
+ "endpoint": "/chat-history",
81
+ "status_code": response.status_code,
82
+ "response": response.json() if response.status_code == 200 else response.text,
83
+ "success": response.status_code == 200
84
+ }
85
+
86
+ if result["success"]:
87
+ print("✓ Chat history retrieved successfully")
88
+ else:
89
+ print(f"✗ Failed to get chat history: {result['response']}")
90
+
91
+ return result
92
+
93
+ def test_upload_files(self, file_paths: list = None) -> Dict[str, Any]:
94
+ """Test file upload endpoint."""
95
+ print("Testing file upload endpoint...")
96
+ url = f"{self.base_url}/upload-files"
97
+
98
+ # Create test files if none provided
99
+ if not file_paths:
100
+ test_files = self._create_test_files()
101
+ file_paths = test_files
102
+
103
+ files = []
104
+ try:
105
+ for file_path in file_paths:
106
+ files.append(('files', (os.path.basename(file_path), open(file_path, 'rb'))))
107
+
108
+ response = self.session.post(url, files=files)
109
+ result = {
110
+ "endpoint": "/upload-files",
111
+ "status_code": response.status_code,
112
+ "response": response.json() if response.status_code in [200, 400] else response.text,
113
+ "success": response.status_code == 200
114
+ }
115
+
116
+ if result["success"]:
117
+ print("✓ Files uploaded and processed successfully")
118
+ else:
119
+ print(f"✗ Failed to upload files: {result['response']}")
120
+
121
+ finally:
122
+ # Close file handles
123
+ for _, (_, file_handle) in files:
124
+ file_handle.close()
125
+
126
+ # Clean up test files if we created them
127
+ if not file_paths or file_paths == getattr(self, '_test_files', []):
128
+ self._cleanup_test_files()
129
+
130
+ return result
131
+
132
+ def test_process_directory(self, directory_path: str = None) -> Dict[str, Any]:
133
+ """Test directory processing endpoint."""
134
+ print("Testing directory processing endpoint...")
135
+ url = f"{self.base_url}/process-directory"
136
+
137
+ # Use a test directory if none provided
138
+ if not directory_path:
139
+ directory_path = self._create_test_directory()
140
+
141
+ payload = {"directory_path": directory_path}
142
+
143
+ response = self.session.post(url, data=payload)
144
+ result = {
145
+ "endpoint": "/process-directory",
146
+ "status_code": response.status_code,
147
+ "response": response.json() if response.status_code in [200, 400] else response.text,
148
+ "success": response.status_code == 200
149
+ }
150
+
151
+ if result["success"]:
152
+ print("✓ Directory processed successfully")
153
+ else:
154
+ print(f"✗ Failed to process directory: {result['response']}")
155
+
156
+ return result
157
+
158
+ def test_chat(self, message: str = "What is the main topic of the documents?") -> Dict[str, Any]:
159
+ """Test chat endpoint."""
160
+ print("Testing chat endpoint...")
161
+ url = f"{self.base_url}/chat"
162
+ payload = {"message": message}
163
+
164
+ response = self.session.post(url, json=payload)
165
+ result = {
166
+ "endpoint": "/chat",
167
+ "status_code": response.status_code,
168
+ "response": response.json() if response.status_code in [200, 400] else response.text,
169
+ "success": response.status_code == 200
170
+ }
171
+
172
+ if result["success"]:
173
+ print("✓ Chat response received successfully")
174
+ else:
175
+ print(f"✗ Chat failed: {result['response']}")
176
+
177
+ return result
178
+
179
+ def test_save_vector_store(self) -> Dict[str, Any]:
180
+ """Test saving vector store."""
181
+ print("Testing save vector store endpoint...")
182
+ url = f"{self.base_url}/save-vector-store"
183
+
184
+ response = self.session.post(url)
185
+ result = {
186
+ "endpoint": "/save-vector-store",
187
+ "status_code": response.status_code,
188
+ "response": response.json() if response.status_code in [200, 400] else response.text,
189
+ "success": response.status_code == 200
190
+ }
191
+
192
+ if result["success"]:
193
+ print("✓ Vector store saved successfully")
194
+ else:
195
+ print(f"✗ Failed to save vector store: {result['response']}")
196
+
197
+ return result
198
+
199
+ def test_load_vector_store(self) -> Dict[str, Any]:
200
+ """Test loading vector store."""
201
+ print("Testing load vector store endpoint...")
202
+ url = f"{self.base_url}/load-vector-store"
203
+
204
+ response = self.session.post(url)
205
+ result = {
206
+ "endpoint": "/load-vector-store",
207
+ "status_code": response.status_code,
208
+ "response": response.json() if response.status_code in [200, 400] else response.text,
209
+ "success": response.status_code == 200
210
+ }
211
+
212
+ if result["success"]:
213
+ print("✓ Vector store loaded successfully")
214
+ else:
215
+ print(f"✗ Failed to load vector store: {result['response']}")
216
+
217
+ return result
218
+
219
+ def test_clear_chat(self) -> Dict[str, Any]:
220
+ """Test clearing chat history."""
221
+ print("Testing clear chat endpoint...")
222
+ url = f"{self.base_url}/clear-chat"
223
+
224
+ response = self.session.delete(url)
225
+ result = {
226
+ "endpoint": "/clear-chat",
227
+ "status_code": response.status_code,
228
+ "response": response.json() if response.status_code == 200 else response.text,
229
+ "success": response.status_code == 200
230
+ }
231
+
232
+ if result["success"]:
233
+ print("✓ Chat history cleared successfully")
234
+ else:
235
+ print(f"✗ Failed to clear chat: {result['response']}")
236
+
237
+ return result
238
+
239
+ def _create_test_files(self) -> list:
240
+ """Create temporary test files for upload testing."""
241
+ temp_dir = tempfile.mkdtemp()
242
+ self._temp_dir = temp_dir
243
+ test_files = []
244
+
245
+ # Create a text file
246
+ txt_file = os.path.join(temp_dir, "test_document.txt")
247
+ with open(txt_file, 'w') as f:
248
+ f.write("""
249
+ This is a test document for the RAG system.
250
+ It contains information about artificial intelligence and machine learning.
251
+
252
+ Machine learning is a subset of artificial intelligence that focuses on
253
+ algorithms that can learn and improve from experience without being
254
+ explicitly programmed.
255
+
256
+ Key concepts in machine learning include:
257
+ - Supervised learning
258
+ - Unsupervised learning
259
+ - Reinforcement learning
260
+ - Neural networks
261
+ - Deep learning
262
+ """)
263
+ test_files.append(txt_file)
264
+
265
+ # Create a markdown file
266
+ md_file = os.path.join(temp_dir, "test_readme.md")
267
+ with open(md_file, 'w') as f:
268
+ f.write("""
269
+ # Test README
270
+
271
+ This is a test markdown document for testing the RAG system.
272
+
273
+ ## About AI
274
+
275
+ Artificial Intelligence (AI) is the simulation of human intelligence
276
+ processes by machines, especially computer systems.
277
+
278
+ ## Applications
279
+
280
+ - Natural Language Processing
281
+ - Computer Vision
282
+ - Robotics
283
+ - Expert Systems
284
+ """)
285
+ test_files.append(md_file)
286
+
287
+ self._test_files = test_files
288
+ return test_files
289
+
290
+ def _create_test_directory(self) -> str:
291
+ """Create a test directory with files."""
292
+ if not hasattr(self, '_temp_dir'):
293
+ self._create_test_files()
294
+ return self._temp_dir
295
+
296
+ def _cleanup_test_files(self):
297
+ """Clean up temporary test files."""
298
+ if hasattr(self, '_temp_dir') and os.path.exists(self._temp_dir):
299
+ import shutil
300
+ shutil.rmtree(self._temp_dir)
301
+
302
+ def run_all_tests(self, api_key: str = None) -> Dict[str, Any]:
303
+ """Run all available tests."""
304
+ print("="*60)
305
+ print("Starting RAG API Endpoint Tests")
306
+ print("="*60)
307
+
308
+ results = {}
309
+
310
+ # Test connection
311
+ if not self.test_connection():
312
+ print("✗ Server is not running! Please start the FastAPI server first.")
313
+ return {"error": "Server not available"}
314
+
315
+ print("✓ Server is running")
316
+ print("-"*40)
317
+
318
+ # Set API key if provided
319
+ if api_key:
320
+ results["set_api_key"] = self.set_api_key(api_key)
321
+ print("-"*40)
322
+
323
+ # Test basic endpoints
324
+ results["stats"] = self.test_get_stats()
325
+ print("-"*40)
326
+
327
+ results["chat_history"] = self.test_get_chat_history()
328
+ print("-"*40)
329
+
330
+ # Test file upload (this will also process documents)
331
+ results["upload_files"] = self.test_upload_files()
332
+ print("-"*40)
333
+
334
+ # Test chat (only if upload was successful)
335
+ if results["upload_files"]["success"]:
336
+ results["chat"] = self.test_chat()
337
+ print("-"*40)
338
+
339
+ # Test vector store operations
340
+ results["save_vector_store"] = self.test_save_vector_store()
341
+ print("-"*40)
342
+
343
+ # Test loading vector store
344
+ results["load_vector_store"] = self.test_load_vector_store()
345
+ print("-"*40)
346
+
347
+ # Test clearing chat
348
+ results["clear_chat"] = self.test_clear_chat()
349
+ print("-"*40)
350
+
351
+ # Test directory processing
352
+ results["process_directory"] = self.test_process_directory()
353
+ print("-"*40)
354
+
355
+ # Summary
356
+ print("="*60)
357
+ print("Test Summary:")
358
+ print("="*60)
359
+
360
+ total_tests = 0
361
+ passed_tests = 0
362
+
363
+ for test_name, result in results.items():
364
+ if isinstance(result, dict) and "success" in result:
365
+ total_tests += 1
366
+ if result["success"]:
367
+ passed_tests += 1
368
+ print(f"✓ {test_name}: PASSED")
369
+ else:
370
+ print(f"✗ {test_name}: FAILED")
371
+
372
+ print(f"\nTotal: {passed_tests}/{total_tests} tests passed")
373
+
374
+ return results
375
+
376
+
377
+ def main():
378
+ """Main function to run the tests."""
379
+ import argparse
380
+
381
+ parser = argparse.ArgumentParser(description="Test RAG API endpoints")
382
+ parser.add_argument("--url", default="http://localhost:7860",
383
+ help="Base URL of the API server")
384
+ parser.add_argument("--api-key",
385
+ help="GROQ API key for testing")
386
+ parser.add_argument("--test", choices=[
387
+ "all", "connection", "api-key", "stats", "chat-history",
388
+ "upload", "chat", "save-store", "load-store", "clear-chat", "directory"
389
+ ], default="all", help="Specific test to run")
390
+
391
+ args = parser.parse_args()
392
+
393
+ tester = RAGAPITester(args.url)
394
+
395
+ if args.test == "all":
396
+ results = tester.run_all_tests(args.api_key)
397
+ elif args.test == "connection":
398
+ success = tester.test_connection()
399
+ print(f"Connection test: {'✓ PASSED' if success else '✗ FAILED'}")
400
+ elif args.test == "api-key":
401
+ if not args.api_key:
402
+ print("Please provide --api-key for this test")
403
+ return
404
+ result = tester.set_api_key(args.api_key)
405
+ print(f"API key test: {'✓ PASSED' if result['success'] else '✗ FAILED'}")
406
+ elif args.test == "stats":
407
+ result = tester.test_get_stats()
408
+ print(f"Stats test: {'✓ PASSED' if result['success'] else '✗ FAILED'}")
409
+ elif args.test == "chat-history":
410
+ result = tester.test_get_chat_history()
411
+ print(f"Chat history test: {'✓ PASSED' if result['success'] else '✗ FAILED'}")
412
+ elif args.test == "upload":
413
+ result = tester.test_upload_files()
414
+ print(f"Upload test: {'✓ PASSED' if result['success'] else '✗ FAILED'}")
415
+ elif args.test == "chat":
416
+ result = tester.test_chat()
417
+ print(f"Chat test: {'✓ PASSED' if result['success'] else '✗ FAILED'}")
418
+ elif args.test == "save-store":
419
+ result = tester.test_save_vector_store()
420
+ print(f"Save store test: {'✓ PASSED' if result['success'] else '✗ FAILED'}")
421
+ elif args.test == "load-store":
422
+ result = tester.test_load_vector_store()
423
+ print(f"Load store test: {'✓ PASSED' if result['success'] else '✗ FAILED'}")
424
+ elif args.test == "clear-chat":
425
+ result = tester.test_clear_chat()
426
+ print(f"Clear chat test: {'✓ PASSED' if result['success'] else '✗ FAILED'}")
427
+ elif args.test == "directory":
428
+ result = tester.test_process_directory()
429
+ print(f"Directory test: {'✓ PASSED' if result['success'] else '✗ FAILED'}")
430
+
431
+
432
+ if __name__ == "__main__":
433
+ main()
test/test_endpoints_pytest.py ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Pytest-based test suite for RAG API endpoints.
3
+ Run with: pytest test_endpoints_pytest.py -v
4
+ """
5
+
6
+ import pytest
7
+ import requests
8
+ import tempfile
9
+ import os
10
+ import json
11
+ from typing import Dict, Any
12
+
13
+
14
+ class TestRAGAPI:
15
+ """Test class for RAG API endpoints."""
16
+
17
+ BASE_URL = "http://localhost:7860"
18
+
19
+ @pytest.fixture(autouse=True)
20
+ def setup(self):
21
+ """Setup for each test."""
22
+ self.session = requests.Session()
23
+
24
+ def test_server_running(self):
25
+ """Test if the server is running."""
26
+ try:
27
+ response = self.session.get(f"{self.BASE_URL}/")
28
+ assert response.status_code in [200, 404], "Server should be running"
29
+ except requests.ConnectionError:
30
+ pytest.fail("Server is not running. Please start the FastAPI server.")
31
+
32
+ def test_get_stats(self):
33
+ """Test the stats endpoint."""
34
+ response = self.session.get(f"{self.BASE_URL}/stats")
35
+ assert response.status_code == 200
36
+ data = response.json()
37
+ assert "stats" in data
38
+ assert "vector_store_loaded" in data
39
+
40
+ def test_get_chat_history(self):
41
+ """Test the chat history endpoint."""
42
+ response = self.session.get(f"{self.BASE_URL}/chat-history")
43
+ assert response.status_code == 200
44
+ data = response.json()
45
+ assert "history" in data
46
+ assert isinstance(data["history"], list)
47
+
48
+ def test_set_api_key_missing(self):
49
+ """Test setting API key with missing key."""
50
+ response = self.session.post(f"{self.BASE_URL}/set-api-key", json={})
51
+ assert response.status_code == 422 # Validation error
52
+
53
+ def test_set_api_key_invalid(self):
54
+ """Test setting API key with invalid key."""
55
+ response = self.session.post(
56
+ f"{self.BASE_URL}/set-api-key",
57
+ json={"api_key": "invalid_key"}
58
+ )
59
+ # This might succeed or fail depending on validation
60
+ assert response.status_code in [200, 400]
61
+
62
+ def test_chat_without_documents(self):
63
+ """Test chat endpoint without uploaded documents."""
64
+ response = self.session.post(
65
+ f"{self.BASE_URL}/chat",
66
+ json={"message": "What is the main topic?"}
67
+ )
68
+ # Should fail without documents loaded
69
+ assert response.status_code in [400, 500]
70
+
71
+ def test_upload_no_files(self):
72
+ """Test upload endpoint with no files."""
73
+ response = self.session.post(f"{self.BASE_URL}/upload-files")
74
+ assert response.status_code == 422 # Validation error
75
+
76
+ def test_process_nonexistent_directory(self):
77
+ """Test processing a non-existent directory."""
78
+ response = self.session.post(
79
+ f"{self.BASE_URL}/process-directory",
80
+ data={"directory_path": "/nonexistent/path"}
81
+ )
82
+ assert response.status_code == 400
83
+
84
+ def test_save_vector_store_without_data(self):
85
+ """Test saving vector store without loaded data."""
86
+ response = self.session.post(f"{self.BASE_URL}/save-vector-store")
87
+ assert response.status_code in [400, 500]
88
+
89
+ def test_load_vector_store(self):
90
+ """Test loading vector store."""
91
+ response = self.session.post(f"{self.BASE_URL}/load-vector-store")
92
+ # This might succeed if there's a saved store, or fail if not
93
+ assert response.status_code in [200, 400]
94
+
95
+ def test_clear_chat(self):
96
+ """Test clearing chat history."""
97
+ response = self.session.delete(f"{self.BASE_URL}/clear-chat")
98
+ assert response.status_code == 200
99
+ data = response.json()
100
+ assert data["status"] == "success"
101
+
102
+ @pytest.fixture
103
+ def test_files(self):
104
+ """Create temporary test files."""
105
+ temp_dir = tempfile.mkdtemp()
106
+
107
+ # Create test text file
108
+ txt_file = os.path.join(temp_dir, "test.txt")
109
+ with open(txt_file, 'w') as f:
110
+ f.write("This is a test document about machine learning and AI.")
111
+
112
+ # Create test markdown file
113
+ md_file = os.path.join(temp_dir, "test.md")
114
+ with open(md_file, 'w') as f:
115
+ f.write("# Test\nThis is a test markdown file about artificial intelligence.")
116
+
117
+ yield [txt_file, md_file]
118
+
119
+ # Cleanup
120
+ import shutil
121
+ shutil.rmtree(temp_dir)
122
+
123
+ def test_upload_files_success(self, test_files):
124
+ """Test successful file upload."""
125
+ files = []
126
+ try:
127
+ for file_path in test_files:
128
+ files.append(('files', (os.path.basename(file_path), open(file_path, 'rb'))))
129
+
130
+ response = self.session.post(f"{self.BASE_URL}/upload-files", files=files)
131
+
132
+ # This might fail if API key is not set, but should have proper error
133
+ assert response.status_code in [200, 400, 500]
134
+
135
+ if response.status_code == 200:
136
+ data = response.json()
137
+ assert data["status"] == "success"
138
+ assert "stats" in data
139
+ finally:
140
+ for _, (_, file_handle) in files:
141
+ file_handle.close()
142
+
143
+ def test_process_directory_success(self, test_files):
144
+ """Test successful directory processing."""
145
+ # Use the directory containing test files
146
+ test_dir = os.path.dirname(test_files[0])
147
+
148
+ response = self.session.post(
149
+ f"{self.BASE_URL}/process-directory",
150
+ data={"directory_path": test_dir}
151
+ )
152
+
153
+ # This might fail if API key is not set, but should have proper error
154
+ assert response.status_code in [200, 400, 500]
155
+
156
+ if response.status_code == 200:
157
+ data = response.json()
158
+ assert data["status"] == "success"
159
+ assert "stats" in data
160
+
161
+
162
+ class TestRAGAPIWithSetup:
163
+ """Test class that requires API key setup."""
164
+
165
+ BASE_URL = "http://localhost:7860"
166
+
167
+ @pytest.fixture(autouse=True)
168
+ def setup(self):
169
+ """Setup for each test."""
170
+ self.session = requests.Session()
171
+
172
+ # Try to set API key from environment
173
+ api_key = os.getenv("GROQ_API_KEY")
174
+ if api_key:
175
+ response = self.session.post(
176
+ f"{self.BASE_URL}/set-api-key",
177
+ json={"api_key": api_key}
178
+ )
179
+ self.api_key_set = response.status_code == 200
180
+ else:
181
+ self.api_key_set = False
182
+
183
+ @pytest.mark.skipif(not os.getenv("GROQ_API_KEY"), reason="GROQ_API_KEY not set")
184
+ def test_full_workflow(self):
185
+ """Test the complete workflow with API key."""
186
+ if not self.api_key_set:
187
+ pytest.skip("API key could not be set")
188
+
189
+ # Create test files
190
+ temp_dir = tempfile.mkdtemp()
191
+ txt_file = os.path.join(temp_dir, "test.txt")
192
+ with open(txt_file, 'w') as f:
193
+ f.write("Machine learning is a subset of artificial intelligence.")
194
+
195
+ try:
196
+ # Upload files
197
+ with open(txt_file, 'rb') as f:
198
+ files = [('files', (os.path.basename(txt_file), f))]
199
+ response = self.session.post(f"{self.BASE_URL}/upload-files", files=files)
200
+ assert response.status_code == 200
201
+
202
+ # Test chat
203
+ response = self.session.post(
204
+ f"{self.BASE_URL}/chat",
205
+ json={"message": "What is machine learning?"}
206
+ )
207
+ assert response.status_code == 200
208
+ data = response.json()
209
+ assert "response" in data
210
+ assert "citations" in data
211
+ assert "themes" in data
212
+
213
+ # Test save vector store
214
+ response = self.session.post(f"{self.BASE_URL}/save-vector-store")
215
+ assert response.status_code == 200
216
+
217
+ finally:
218
+ import shutil
219
+ shutil.rmtree(temp_dir)
220
+
221
+
222
+ if __name__ == "__main__":
223
+ pytest.main([__file__, "-v"])