import sys import os # Append project root to sys.path to enable src imports sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import src.llm as llm import src.contacts as contacts import src.ledger as ledger def test_llm_mock(): print("[TEST] Testing mock LLM backend...") stream = llm.generate_mock("पीलापन रोग के बारे में बताएं") response = "" for chunk in stream: response += chunk assert "पीलापन" in response or "Nitrogen" in response print("[PASS] Mock LLM backend passed!") def test_emergency_router(): print("[TEST] Testing emergency safety keywords router...") # Trigger query (Hindi) is_emergency, warning = contacts.check_emergency_query("मुझे यूरिया कीटनाशक जहर चढ़ गया है") assert is_emergency is True assert "सुरक्षा चेतावनी" in warning or "SAFETY WARNING" in warning # Hinglish suicidal query is_emergency, warning = contacts.check_emergency_query("mujhe suicidal feel ho raha h") assert is_emergency is True assert "1800-599-0019" in warning # Safe query is_emergency, warning = contacts.check_emergency_query("गेहूं में पानी कब डालना है") assert is_emergency is False assert warning is None print("[PASS] Emergency safety keyword router passed!") def test_ledger_parser(): print("[TEST] Testing ledger parser and JSON extraction...") # We write a mock prompt runner since the user selected starting without models/RAG first # This mock runner matches the expected mock JSON output inside ledger.py/llm.py def mock_generate_fn(prompt, system="", stream=False): return '{"date": "today", "item": "Wheat (गेहूं)", "qty": "40 kg", "price": 1200, "type": "sale"}' parsed = ledger.parse_transaction("मैंने आज 1200 रुपये में 40 किलो गेहूं बेचा", mock_generate_fn) assert parsed.get("date") == "today" assert "Wheat" in parsed.get("item") assert parsed.get("price") == 1200 assert parsed.get("type") == "sale" print("[PASS] Ledger transaction parser passed!") def test_onboarding(): print("[TEST] Testing profile onboarding...") from app import save_user_profile, load_user_profile, PROFILE_PATH # Clean old profile if os.path.exists(PROFILE_PATH): os.remove(PROFILE_PATH) res = save_user_profile("Ramesh Dev", "Uttar Pradesh", "Kanpur Dehat") assert res is True profile = load_user_profile() assert profile is not None assert profile["name"] == "Ramesh Dev" assert profile["state"] == "Uttar Pradesh" assert profile["district"] == "Kanpur Dehat" # Cleanup after test if os.path.exists(PROFILE_PATH): os.remove(PROFILE_PATH) print("[PASS] Onboarding profile save/load passed!") def test_proactive_nudge(): print("[TEST] Testing proactive nudge seasonal calculations...") from app import get_proactive_nudge nudge_hi = get_proactive_nudge("Wheat", "hi") assert nudge_hi is not None assert "Wheat" in nudge_hi or "गेहूं" in nudge_hi assert "💡" in nudge_hi nudge_en = get_proactive_nudge("Potato", "en") assert nudge_en is not None assert "Potato" in nudge_en or "आलू" in nudge_en assert "💡" in nudge_en print("[PASS] Proactive nudge calculations passed!") def test_contacts_categorized(): print("[TEST] Testing categorized contacts listing...") contacts_list = contacts.load_contacts() assert len(contacts_list) > 0 categories = {c.get("category") for c in contacts_list} assert "National (राष्ट्रीय)" in categories assert "Local (Kanpur Dehat) / स्थानीय संपर्क" in categories print("[PASS] Categorized contacts database integrity passed!") def test_generate_mock_ledger(): print("[TEST] Testing generate_mock with ledger extraction query...") stream = llm.generate_mock( prompt="aaj maine 1200 rupay me 5 kg cotton khareeda", system="json format precise data extractor" ) result = "".join(list(stream)) import json parsed = json.loads(result) assert "cotton" in parsed["item"].lower() assert parsed["price"] == 1200 assert "5 kg" in parsed["qty"] assert parsed["type"] == "purchase" assert parsed["date"] != "00 rupay" print("[PASS] generate_mock ledger extraction verified!") def test_generate_mock_history_recall(): print("[TEST] Testing generate_mock history recall (last questions query)...") history = [ {"role": "user", "content": "गेहूं में पीलापन क्यों आता है?"}, {"role": "assistant", "content": "नाइट्रोजन की कमी से पीलापन होता है।"}, {"role": "user", "content": "सिंचाई कब करनी चाहिए?"}, {"role": "assistant", "content": "बुवाई के 21-25 दिन बाद CRI सिंचाई करें।"}, ] # English variant stream = llm.generate_mock("what were my last questions?", history=history) result = "".join(list(stream)) assert "पीलापन" in result or "सिंचाई" in result, f"Expected history questions in result, got: {result[:200]}" # Hindi variant stream = llm.generate_mock("मेरे पिछले सवाल क्या थे?", history=history) result = "".join(list(stream)) assert "पीलापन" in result or "सिंचाई" in result, f"Expected history questions in result, got: {result[:200]}" print("[PASS] History recall test passed!") def test_generate_mock_context_aware_fallback(): print("[TEST] Testing generate_mock context-aware fallback (unrecognized topic with history)...") history = [ {"role": "user", "content": "Hello"}, {"role": "assistant", "content": "नमस्ते! मैं किसान साथी हूँ।"}, ] # An unrecognized query with history should NOT return the welcome message stream = llm.generate_mock("sugarcane ki kheti kaise karein?", history=history) result = "".join(list(stream)) # Should NOT be the generic welcome message assert "नमस्ते! मैं आपका किसान साथी हूँ।" not in result, ( f"Should not return generic welcome message when history is present, got: {result[:200]}" ) # Should reference the previous conversation assert "Hello" in result or "विवरण" in result or "समझ" in result, ( f"Expected context-aware response, got: {result[:200]}" ) print("[PASS] Context-aware fallback test passed!") if __name__ == "__main__": print("--- Running Kisan-Sathi Core Verification ---") try: test_llm_mock() test_emergency_router() test_ledger_parser() test_generate_mock_ledger() test_generate_mock_history_recall() test_generate_mock_context_aware_fallback() test_onboarding() test_proactive_nudge() test_contacts_categorized() print("[SUCCESS] ALL TESTS PASSED SUCCESSFULLY!") except AssertionError as e: print(f"[FAIL] TEST FAILED: {e}") sys.exit(1)