findEthics/Atlas
0
1"""2Integration tests for chat API with user authentication3 4Consolidated from:5- test_chat_integration_user_auth.py6- test_chat_analytics.py (integration portions)7- Parts of test_user_authentication_comprehensive.py (integration portions)8"""9 10import asyncio11import time12 13import pytest14 15from tests.utilities import HTTPHelpers, MockHelpers, TestHelpers, ValidationHelpers, authenticated_chat_request, empty_user_ids, invalid_user_ids, sample_chat_request, skip_if_no_server, valid_user_ids16 17 HTTPHelpers, TestHelpers, MockHelpers, ValidationHelpers,18 skip_if_no_server, authenticated_chat_request, sample_chat_request,19 valid_user_ids, invalid_user_ids, empty_user_ids20)21 22 23class TestChatRequestValidation:24 """Test chat request validation with user_id"""25 26 @pytest.mark.asyncio27 @skip_if_no_server()28 async def test_valid_user_id_formats(self, valid_user_ids):29 """Test chat requests with various valid user_id formats"""30 for user_id in valid_user_ids[:5]: # Test first 5 to avoid too many requests31 chat_data = {32 "prompt": f"Test message for user {user_id}",33 "max_new_tokens": 50,34 "use_search": False,35 "temperature": 0.7,36 "user_id": user_id37 }38 39 response = await HTTPHelpers.make_chat_request(chat_data)40 if response is None:41 pytest.skip("Server not available")42 43 session_id = HTTPHelpers.assert_successful_chat_response(response)44 assert session_id is not None45 46 @pytest.mark.asyncio47 @skip_if_no_server()48 async def test_invalid_user_id_formats(self, invalid_user_ids):49 """Test chat requests with invalid user_id formats"""50 for user_id in invalid_user_ids[:10]: # Test first 10 to avoid too many requests51 chat_data = {52 "prompt": f"Test message for invalid user {user_id}",53 "max_new_tokens": 50,54 "use_search": False,55 "temperature": 0.7,56 "user_id": user_id57 }58 59 response = await HTTPHelpers.make_chat_request(chat_data)60 if response is None:61 pytest.skip("Server not available")62 63 HTTPHelpers.assert_failed_chat_response(response, expected_status=400)64 65 @pytest.mark.asyncio66 @skip_if_no_server()67 async def test_empty_user_id_handling(self, empty_user_ids):68 """Test that empty user_id is treated as anonymous"""69 for empty_user_id in empty_user_ids:70 chat_data = {71 "prompt": "Test message with empty user_id",72 "max_new_tokens": 50,73 "use_search": False,74 "temperature": 0.7,75 "user_id": empty_user_id76 }77 78 response = await HTTPHelpers.make_chat_request(chat_data)79 if response is None:80 pytest.skip("Server not available")81 82 session_id = HTTPHelpers.assert_successful_chat_response(response)83 assert session_id is not None84 85 @pytest.mark.asyncio86 @skip_if_no_server()87 async def test_missing_user_id_field(self, sample_chat_request):88 """Test that missing user_id field works (backward compatibility)"""89 response = await HTTPHelpers.make_chat_request(sample_chat_request)90 if response is None:91 pytest.skip("Server not available")92 93 session_id = HTTPHelpers.assert_successful_chat_response(response)94 assert session_id is not None95 96 97class TestChatRequestFlow:98 """Test complete chat request flow with user authentication"""99 100 @pytest.mark.asyncio101 @skip_if_no_server()102 async def test_authenticated_user_session_flow(self):103 """Test complete flow for authenticated user"""104 user_id = "test_flow_user"105 106 # First request - creates new session107 chat_data1 = {108 "prompt": "First message from authenticated user",109 "max_new_tokens": 50,110 "use_search": False,111 "temperature": 0.7,112 "user_id": user_id113 }114 115 response1 = await HTTPHelpers.make_chat_request(chat_data1)116 if response1 is None:117 pytest.skip("Server not available")118 119 session_id = HTTPHelpers.assert_successful_chat_response(response1)120 121 # Second request - uses existing session122 chat_data2 = {123 "prompt": "Second message from same user",124 "max_new_tokens": 50,125 "use_search": True, # Enable search this time126 "temperature": 0.7,127 "user_id": user_id128 }129 130 response2 = await HTTPHelpers.make_chat_request(chat_data2, session_id=session_id)131 if response2 is None:132 pytest.skip("Server not available")133 134 session_id2 = HTTPHelpers.assert_successful_chat_response(response2)135 136 # Should return same session ID137 assert session_id2 == session_id138 139 # Wait for data to be written140 await TestHelpers.wait_for_data_persistence(2.0)141 142 # Verify data was stored correctly143 session_valid = await TestHelpers.verify_session_data(144 session_id, user_id, expected_messages=2145 )146 assert session_valid147 148 @pytest.mark.asyncio149 @skip_if_no_server()150 async def test_anonymous_user_session_flow(self):151 """Test complete flow for anonymous user"""152 # First request - anonymous user153 chat_data1 = {154 "prompt": "First message from anonymous user",155 "max_new_tokens": 50,156 "use_search": False,157 "temperature": 0.7158 # No user_id field159 }160 161 response1 = await HTTPHelpers.make_chat_request(chat_data1)162 if response1 is None:163 pytest.skip("Server not available")164 165 session_id = HTTPHelpers.assert_successful_chat_response(response1)166 167 # Second request - same anonymous user168 chat_data2 = {169 "prompt": "Second message from anonymous user",170 "max_new_tokens": 50,171 "use_search": True,172 "temperature": 0.7173 # No user_id field174 }175 176 response2 = await HTTPHelpers.make_chat_request(chat_data2, session_id=session_id)177 if response2 is None:178 pytest.skip("Server not available")179 180 session_id2 = HTTPHelpers.assert_successful_chat_response(response2)181 assert session_id2 == session_id182 183 # Wait for data to be written184 await TestHelpers.wait_for_data_persistence(2.0)185 186 # Verify data was stored correctly (user_id should be None)187 session_valid = await TestHelpers.verify_session_data(188 session_id, None, expected_messages=2189 )190 assert session_valid191 192 @pytest.mark.asyncio193 @skip_if_no_server()194 async def test_mixed_user_sessions(self):195 """Test that different users get different sessions"""196 user_id1 = "test_user_1"197 user_id2 = "test_user_2"198 199 # Request from user 1200 chat_data1 = {201 "prompt": "Message from user 1",202 "max_new_tokens": 50,203 "use_search": False,204 "temperature": 0.7,205 "user_id": user_id1206 }207 208 response1 = await HTTPHelpers.make_chat_request(chat_data1)209 if response1 is None:210 pytest.skip("Server not available")211 212 session_id1 = HTTPHelpers.assert_successful_chat_response(response1)213 214 # Request from user 2215 chat_data2 = {216 "prompt": "Message from user 2",217 "max_new_tokens": 50,218 "use_search": False,219 "temperature": 0.7,220 "user_id": user_id2221 }222 223 response2 = await HTTPHelpers.make_chat_request(chat_data2)224 if response2 is None:225 pytest.skip("Server not available")226 227 session_id2 = HTTPHelpers.assert_successful_chat_response(response2)228 229 # Sessions should be different230 assert session_id1 != session_id2231 232 @pytest.mark.asyncio233 @skip_if_no_server()234 async def test_session_continuation_with_user_id(self):235 """Test that sessions can be continued with proper user_id"""236 user_id = "test_continuation_user"237 238 # First request creates session239 chat_data1 = {240 "prompt": "First message in session",241 "max_new_tokens": 50,242 "use_search": False,243 "temperature": 0.7,244 "user_id": user_id245 }246 247 response1 = await HTTPHelpers.make_chat_request(chat_data1)248 if response1 is None:249 pytest.skip("Server not available")250 251 session_id = HTTPHelpers.assert_successful_chat_response(response1)252 253 # Second request continues same session with same user_id254 chat_data2 = {255 "prompt": "Second message in same session",256 "max_new_tokens": 50,257 "use_search": True,258 "temperature": 0.7,259 "user_id": user_id260 }261 262 response2 = await HTTPHelpers.make_chat_request(chat_data2, session_id=session_id)263 if response2 is None:264 pytest.skip("Server not available")265 266 session_id2 = HTTPHelpers.assert_successful_chat_response(response2)267 268 # Should be same session269 assert session_id2 == session_id270 271 272class TestChatAnalyticsIntegration:273 """Test that chat requests properly trigger analytics collection"""274 275 @pytest.mark.asyncio276 @skip_if_no_server()277 async def test_chat_request_creates_analytics_data(self):278 """Test that chat requests create analytics data"""279 user_id = "analytics_integration_user"280 281 chat_data = {282 "prompt": "Test message for analytics collection",283 "max_new_tokens": 100,284 "use_search": True,285 "temperature": 0.7,286 "user_id": user_id287 }288 289 response = await HTTPHelpers.make_chat_request(chat_data)290 if response is None:291 pytest.skip("Server not available")292 293 session_id = HTTPHelpers.assert_successful_chat_response(response)294 295 # Wait for analytics data to be written296 await TestHelpers.wait_for_data_persistence(3.0)297 298 # Verify session was created299 session_valid = await TestHelpers.verify_session_data(300 session_id, user_id, expected_messages=1301 )302 assert session_valid303 304 # Check that we can count the user's data305 session_count = await TestHelpers.count_documents_by_user_id("sessions", user_id)306 message_count = await TestHelpers.count_documents_by_user_id("messages", user_id)307 308 assert session_count >= 1309 assert message_count >= 1310 311 @pytest.mark.asyncio312 @skip_if_no_server()313 async def test_anonymous_chat_request_creates_analytics_data(self):314 """Test that anonymous chat requests create analytics data"""315 chat_data = {316 "prompt": "Test anonymous message for analytics",317 "max_new_tokens": 100,318 "use_search": False,319 "temperature": 0.7320 }321 322 response = await HTTPHelpers.make_chat_request(chat_data)323 if response is None:324 pytest.skip("Server not available")325 326 session_id = HTTPHelpers.assert_successful_chat_response(response)327 328 # Wait for analytics data to be written329 await TestHelpers.wait_for_data_persistence(3.0)330 331 # Verify session was created with null user_id332 session_valid = await TestHelpers.verify_session_data(333 session_id, None, expected_messages=1334 )335 assert session_valid336 337 # Check that we can count anonymous data338 anon_session_count = await TestHelpers.count_documents_by_user_id("sessions", None)339 anon_message_count = await TestHelpers.count_documents_by_user_id("messages", None)340 341 assert anon_session_count >= 1342 assert anon_message_count >= 1343 344 @pytest.mark.asyncio345 @skip_if_no_server()346 async def test_search_analytics_collection(self):347 """Test that search analytics are collected when search is used"""348 user_id = "search_analytics_user"349 350 chat_data = {351 "prompt": "What is the weather like today?",352 "max_new_tokens": 100,353 "use_search": True, # Enable search354 "temperature": 0.7,355 "user_id": user_id356 }357 358 response = await HTTPHelpers.make_chat_request(chat_data)359 if response is None:360 pytest.skip("Server not available")361 362 session_id = HTTPHelpers.assert_successful_chat_response(response)363 364 # Wait for analytics data to be written365 await TestHelpers.wait_for_data_persistence(5.0) # Search might take longer366 367 # Verify session and message were created368 session_valid = await TestHelpers.verify_session_data(369 session_id, user_id, expected_messages=1370 )371 assert session_valid372 373 # Check for search analytics (if search was actually performed)374 search_count = await TestHelpers.count_documents_by_user_id("search_analytics", user_id)375 # Note: Search analytics might be 0 if search was not actually performed376 # This is acceptable as it depends on the search implementation377 assert search_count >= 0378 379 380class TestChatRequestPerformance:381 """Test performance of chat requests with user authentication"""382 383 @pytest.mark.asyncio384 @skip_if_no_server()385 async def test_authenticated_request_performance(self):386 """Test performance of authenticated chat requests"""387 user_id = "perf_test_user"388 389 # Warm up request390 warmup_data = {391 "prompt": "Warmup message",392 "max_new_tokens": 50,393 "use_search": False,394 "temperature": 0.7,395 "user_id": user_id396 }397 398 warmup_response = await HTTPHelpers.make_chat_request(warmup_data)399 if warmup_response is None:400 pytest.skip("Server not available")401 402 # Performance test403 num_requests = 3 # Keep small for CI404 total_time = 0405 406 for i in range(num_requests):407 chat_data = {408 "prompt": f"Performance test message {i}",409 "max_new_tokens": 50,410 "use_search": False,411 "temperature": 0.7,412 "user_id": user_id413 }414 415 start_time = time.time()416 response = await HTTPHelpers.make_chat_request(chat_data)417 end_time = time.time()418 419 if response is None:420 pytest.skip("Server not available")421 422 HTTPHelpers.assert_successful_chat_response(response)423 424 request_time = end_time - start_time425 total_time += request_time426 427 avg_time = total_time / num_requests428 429 # Performance assertion (requests should be reasonably fast)430 assert avg_time < 30.0, f"Requests too slow: {avg_time:.2f}s average"431 432 @pytest.mark.asyncio433 @skip_if_no_server()434 async def test_anonymous_vs_authenticated_performance(self):435 """Compare performance between anonymous and authenticated requests"""436 # Test anonymous requests437 anonymous_times = []438 for i in range(2): # Keep small for CI439 chat_data = {440 "prompt": f"Anonymous performance test {i}",441 "max_new_tokens": 50,442 "use_search": False,443 "temperature": 0.7444 }445 446 start_time = time.time()447 response = await HTTPHelpers.make_chat_request(chat_data)448 end_time = time.time()449 450 if response is None:451 pytest.skip("Server not available")452 453 HTTPHelpers.assert_successful_chat_response(response)454 anonymous_times.append(end_time - start_time)455 456 # Test authenticated requests457 authenticated_times = []458 for i in range(2): # Keep small for CI459 chat_data = {460 "prompt": f"Authenticated performance test {i}",461 "max_new_tokens": 50,462 "use_search": False,463 "temperature": 0.7,464 "user_id": "perf_auth_user"465 }466 467 start_time = time.time()468 response = await HTTPHelpers.make_chat_request(chat_data)469 end_time = time.time()470 471 if response is None:472 pytest.skip("Server not available")473 474 HTTPHelpers.assert_successful_chat_response(response)475 authenticated_times.append(end_time - start_time)476 477 avg_anonymous = sum(anonymous_times) / len(anonymous_times)478 avg_authenticated = sum(authenticated_times) / len(authenticated_times)479 480 # Performance should be similar (user authentication shouldn't add significant overhead)481 time_difference = abs(avg_authenticated - avg_anonymous)482 assert time_difference < 10.0, f"Too much performance difference: {time_difference:.2f}s"483 484 485class TestChatRequestErrorHandling:486 """Test error handling in chat requests"""487 488 @pytest.mark.asyncio489 @skip_if_no_server()490 async def test_malformed_request_handling(self):491 """Test handling of malformed requests"""492 malformed_requests = [493 {}, # Empty request494 {"prompt": ""}, # Empty prompt495 {"user_id": "valid_user"}, # Missing prompt496 {"prompt": "test", "user_id": "invalid@user"}, # Invalid user_id497 ]498 499 for malformed_data in malformed_requests:500 response = await HTTPHelpers.make_chat_request(malformed_data)501 if response is None:502 pytest.skip("Server not available")503 504 # Should return error status505 assert response.status_code >= 400506 507 @pytest.mark.asyncio508 @skip_if_no_server()509 async def test_request_with_invalid_session_id(self):510 """Test request with invalid session ID"""511 chat_data = {512 "prompt": "Test message with invalid session",513 "max_new_tokens": 50,514 "use_search": False,515 "temperature": 0.7,516 "user_id": "test_user"517 }518 519 # Use invalid session ID520 invalid_session_id = "invalid-session-id-12345"521 522 response = await HTTPHelpers.make_chat_request(chat_data, session_id=invalid_session_id)523 if response is None:524 pytest.skip("Server not available")525 526 # Should still work (create new session or handle gracefully)527 # The exact behavior depends on implementation528 assert response.status_code in [200, 400, 404]529 530 531class TestChatRequestWithMocks:532 """Test chat requests with mocked dependencies"""533 534 @pytest.mark.asyncio535 async def test_chat_request_with_mocked_ai(self):536 """Test chat request with mocked AI response"""537 with MockHelpers.mock_gemini_inference("Mocked AI response"), \538 MockHelpers.mock_web_search([]):539 540 chat_data = {541 "prompt": "Test prompt for mocked AI",542 "max_new_tokens": 100,543 "use_search": False,544 "temperature": 0.7,545 "user_id": "mock_test_user"546 }547 548 response = await HTTPHelpers.make_chat_request(chat_data)549 if response is None:550 pytest.skip("Server not available")551 552 HTTPHelpers.assert_successful_chat_response(response)553 554 # Verify the mocked response555 data = response.json()556 assert "Mocked AI response" in data["response"]557 558 @pytest.mark.asyncio559 async def test_chat_request_with_mocked_search(self):560 """Test chat request with mocked search results"""561 mock_results = [562 {"title": "Test Result", "url": "https://example.com", "snippet": "Test snippet"}563 ]564 565 with MockHelpers.mock_gemini_inference("AI response with search"), \566 MockHelpers.mock_web_search(mock_results):567 568 chat_data = {569 "prompt": "Test prompt with search",570 "max_new_tokens": 100,571 "use_search": True,572 "temperature": 0.7,573 "user_id": "search_mock_user"574 }575 576 response = await HTTPHelpers.make_chat_request(chat_data)577 if response is None:578 pytest.skip("Server not available")579 580 HTTPHelpers.assert_successful_chat_response(response)581 582 583if __name__ == "__main__":584 # Run tests manually for debugging585 async def run_basic_tests():586 test_validation = TestChatRequestValidation()587 # Note: These would need fixtures to run manually588 print("✅ Chat request validation tests defined")589 590 test_flow = TestChatRequestFlow()591 print("✅ Chat request flow tests defined")592 593 test_analytics = TestChatAnalyticsIntegration()594 print("✅ Chat analytics integration tests defined")595 596 asyncio.run(run_basic_tests())