import unittest from fastapi.testclient import TestClient import sys import os import argparse # Add the project root to sys.path to allow importing main and other modules sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) # Global storage for CLI arguments CLI_ARGS = None try: from main import app except ImportError as e: print(f"Error importing app from main: {e}") # Fallback or exit if necessary sys.exit(1) class TestSanatanAIAPI(unittest.TestCase): @classmethod def setUpClass(cls): cls.client = TestClient(app) def test_get_languages(self): """Test GET /api/languages""" response = self.client.get("/api/languages") self.assertEqual(response.status_code, 200) data = response.json() self.assertIsInstance(data, list) self.assertTrue(len(data) > 0) # Check for English self.assertTrue(any(lang['code'] == 'en' for lang in data)) def test_get_languages_v2(self): """Test GET /api/languages_v2""" response = self.client.get("/api/languages_v2") self.assertEqual(response.status_code, 200) data = response.json() self.assertIsInstance(data, list) def test_post_greet(self): """Test POST /api/greet""" payload = { "language": "English", "text": "Hello", "session_id": "test-session" } response = self.client.post("/api/greet", json=payload) self.assertEqual(response.status_code, 200) data = response.json() self.assertIn("reply", data) self.assertIn("session_id", data) self.assertEqual(data["session_id"], "test-session") def test_get_scriptures(self): """Test GET /api/scriptures""" response = self.client.get("/api/scriptures") self.assertEqual(response.status_code, 200) data = response.json() self.assertIsInstance(data, dict) self.assertTrue(len(data) > 0) def test_get_scripture_configs(self): """Test GET /api/scripture_configs""" response = self.client.get("/api/scripture_configs") self.assertEqual(response.status_code, 200) data = response.json() self.assertIn("scriptures", data) self.assertIsInstance(data["scriptures"], list) def test_get_scripture_categories(self): """Test GET /api/scripture_categories""" response = self.client.get("/api/scripture_categories") self.assertEqual(response.status_code, 200) data = response.json() self.assertIn("categories", data) self.assertIsInstance(data["categories"], list) def test_get_donation_products(self): """Test GET /api/donation/products""" response = self.client.get("/api/donation/products") self.assertEqual(response.status_code, 200) data = response.json() self.assertIsInstance(data, list) self.assertTrue(any(p['id'] == 'donation_unit_0100' for p in data)) def test_get_translations(self): """Test GET /api/translations""" response = self.client.get("/api/translations") # This might return 404 if data/translations.json is missing if response.status_code == 200: data = response.json() self.assertIsInstance(data, dict) else: self.assertEqual(response.status_code, 404) def test_quiz_generate_basic(self): """Test POST /api/quiz/generate with minimal payload""" payload = { "language": "English" } response = self.client.post("/api/quiz/generate", json=payload) # This might take time as it calls generate_question self.assertEqual(response.status_code, 200) data = response.json() self.assertIn("question", data) self.assertIn("choices", data) def test_chat_basic(self): """Test POST /api/chat basic interaction with optional CLI query""" query = CLI_ARGS.query if CLI_ARGS else "What is the Bhagavad Gita?" payload = { "language": "English", "text": query, "session_id": "test-chat-session" } print(f"\n[Chat Test] Sending query: '{query}'") response = self.client.post("/api/chat", json=payload) self.assertEqual(response.status_code, 200) data = response.json() self.assertIn("reply", data) self.assertIn("session_id", data) print(f" -> Received reply (length: {len(data['reply'])})") print(f" -> Received reply : \n{data['reply']}") def test_search_scripture(self): """Test POST /api/scripture/{scripture_name}/search with optional CLI params""" # Use CLI args if provided, else fall back to defaults scripture_name = CLI_ARGS.scripture if CLI_ARGS else "bhagavat_gita" field = CLI_ARGS.field if CLI_ARGS else "verse" raw_value = CLI_ARGS.value if CLI_ARGS else "1" # Simple casting: try int, then float, then stay string try: value = int(raw_value) except ValueError: try: value = float(raw_value) except ValueError: value = raw_value payload = { "filter_obj": { "filters": [ { "metadata_field": field, "metadata_search_operator": "$eq", "metadata_value": value } ] } } print(f"\n[Search Test] Testing {scripture_name} where {field} = {value}") response = self.client.post(f"/api/scripture/{scripture_name}/search", json=payload) self.assertEqual(response.status_code, 200) data = response.json() self.assertIn("results", data) self.assertIsInstance(data["results"], list) # Mark as failed if results are empty self.assertTrue(len(data["results"]) > 0, f"No results found for {scripture_name} where {field} = {value}") print(f" -> Found {len(data['results'])} matches. First match: {data['results'][0].get('text')[:50]}...") def test_get_scripture_toc(self): """Test GET /api/scripture/{scripture_name}/toc""" scripture_name = CLI_ARGS.scripture if CLI_ARGS else "bhagavat_gita" response = self.client.get(f"/api/scripture/{scripture_name}/toc") self.assertEqual(response.status_code, 200) data = response.json() self.assertIn("toc", data) self.assertIsInstance(data["toc"], list) if __name__ == "__main__": parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--scripture', default='bhagavat_gita', help='Scripture name to search') parser.add_argument('--field', default='verse', help='Metadata field to filter by') parser.add_argument('--value', default='1', help='Metadata value to search for') parser.add_argument('--query', default=None, help='Custom chat query for test_chat_basic') # Parse our specific args and leave the rest for unittest (like -v or test names) CLI_ARGS, remaining_argv = parser.parse_known_args() # Re-inject the script name to keep unittest happy unittest.main(argv=[sys.argv[0]] + remaining_argv)