Rabbook / tests /test_phase4_research_agent.py
Matcry's picture
Deploy snapshot
c76423f
Raw
History Blame Contribute Delete
4 kB
import unittest
from unittest.mock import MagicMock, patch
from agents.research_graph import (
plan_search_node,
execute_search_node,
route_research,
save_note_node,
finalize_research_node
)
class ResearchAgentNodesTests(unittest.TestCase):
@patch("agents.research_graph.generate_sub_queries")
def test_plan_search_node_extracts_queries(self, mock_generate_sub_queries):
state = {"topic": "AI agents", "debug_mode": False}
llm = MagicMock()
mock_generate_sub_queries.return_value = [
"what are ai agents",
"benefits of ai agents",
"future of ai agents",
]
updated_state = plan_search_node(state, llm=llm, max_queries=3)
expected_queries = ["what are ai agents", "benefits of ai agents", "future of ai agents"]
self.assertEqual(updated_state["search_queries"], expected_queries)
@patch("agents.research_graph.generate_sub_queries")
def test_plan_search_node_respects_max_queries(self, mock_generate_sub_queries):
state = {"topic": "AI agents", "debug_mode": False}
llm = MagicMock()
mock_generate_sub_queries.return_value = ["q1", "q2"]
updated_state = plan_search_node(state, llm=llm, max_queries=2)
self.assertEqual(len(updated_state["search_queries"]), 2)
self.assertEqual(updated_state["search_queries"], ["q1", "q2"])
@patch("agents.research_graph.fetch_urls_parallel")
@patch("agents.research_graph.web_search")
def test_execute_search_node_collects_results(self, mock_search, mock_fetch_parallel):
mock_search.return_value = [
{"url": "http://e1.com", "title": "T1", "snippet": "S1"},
{"url": "http://e2.com", "title": "T2", "snippet": "S2"}
]
mock_fetch_parallel.return_value = [
{"source_url": "http://e1.com", "page_text": "Full Content"},
]
state = {"search_queries": ["query 1"], "debug_mode": False}
updated_state = execute_search_node(state)
self.assertEqual(len(updated_state["search_results"]), 2)
self.assertEqual(updated_state["search_results"][0]["content"], "Full Content")
@patch("agents.research_graph.save_note")
def test_save_note_node_calls_save_note_when_requested(self, mock_save):
mock_save.return_value = "note_123"
state = {
"topic": "Research Topic",
"synthesis": "The Synthesis",
"save_to_notes": True,
"search_results": [{"url": "U1", "snippet": "S1"}]
}
updated_state = save_note_node(state)
self.assertEqual(updated_state["note_id"], "note_123")
mock_save.assert_called_once()
def test_save_note_node_skips_when_not_requested(self):
state = {"save_to_notes": False}
updated_state = save_note_node(state)
self.assertNotIn("note_id", updated_state)
def test_finalize_research_node_handles_no_results_error(self):
state = {"topic": "Unknown topic", "error": "no_search_results"}
updated_state = finalize_research_node(state)
self.assertIn("unable to find", updated_state["synthesis"])
def test_finalize_research_node_builds_lightweight_summary_when_results_exist(self):
state = {
"topic": "Topic",
"search_results": [
{"title": "Result One"},
{"title": "Result Two"},
],
}
updated_state = finalize_research_node(state)
self.assertIn("Collected web sources", updated_state["synthesis"])
def test_route_research_returns_finalize_on_error(self):
state = {"error": "no_search_results"}
self.assertEqual(route_research(state), "finalize")
def test_route_research_returns_finalize_when_no_error(self):
state = {"search_results": [{"url": "http://e1.com"}]}
self.assertEqual(route_research(state), "finalize")