Spaces:
Runtime error
Runtime error
| """Unit tests for LangGraph workflow state and nodes.""" | |
| import pytest | |
| from unittest.mock import AsyncMock | |
| from src.workflows.types import IntelligenceState | |
| from src.workflows.market_analysis import MarketIntelligenceWorkflow | |
| class TestIntelligenceState: | |
| """Test state schema validation.""" | |
| def test_state_has_required_fields(self): | |
| """Verify state schema has all required fields.""" | |
| required_fields = [ | |
| "research_type", | |
| "company_name", | |
| "industry", | |
| "research_data", | |
| "competitors", | |
| "market_trends", | |
| "raw_sources", | |
| "swot", | |
| "competitive_matrix", | |
| "positioning", | |
| "strategic_recommendations", | |
| "executive_summary", | |
| "full_report", | |
| "report_metadata", | |
| "current_agent", | |
| "iteration", | |
| "total_cost", | |
| "total_tokens", | |
| "errors", | |
| "human_feedback", | |
| "approved", | |
| "revision_count", | |
| ] | |
| state_annotations = IntelligenceState.__annotations__ | |
| for field in required_fields: | |
| assert field in state_annotations, f"Missing required field: {field}" | |
| class TestWorkflowInitialization: | |
| """Test workflow initialization.""" | |
| def test_workflow_initializes(self): | |
| """Test workflow can be initialized.""" | |
| workflow = MarketIntelligenceWorkflow() | |
| assert workflow is not None | |
| assert workflow.max_budget == 2.0 | |
| assert workflow.research_agent is not None | |
| assert workflow.analysis_agent is not None | |
| assert workflow.writer_agent is not None | |
| def test_custom_budget(self): | |
| """Test workflow with custom budget.""" | |
| workflow = MarketIntelligenceWorkflow(max_budget=5.0) | |
| assert workflow.max_budget == 5.0 | |
| class TestConditionalRouting: | |
| """Test workflow routing logic.""" | |
| def test_should_continue_to_analysis_success(self): | |
| """Test routing to analysis when research succeeds.""" | |
| workflow = MarketIntelligenceWorkflow() | |
| state = { | |
| "research_data": {"some": "data"}, | |
| "errors": [], | |
| } | |
| result = workflow._should_continue_to_analysis(state) | |
| assert result == "analysis" | |
| def test_should_continue_to_analysis_with_errors(self): | |
| """Test routing ends when research has errors.""" | |
| workflow = MarketIntelligenceWorkflow() | |
| state = { | |
| "research_data": {}, | |
| "errors": ["Some error"], | |
| } | |
| result = workflow._should_continue_to_analysis(state) | |
| assert result == "end" | |
| def test_should_continue_to_analysis_no_data(self): | |
| """Test routing ends when no research data.""" | |
| workflow = MarketIntelligenceWorkflow() | |
| state = { | |
| "errors": [], | |
| } | |
| result = workflow._should_continue_to_analysis(state) | |
| assert result == "end" | |
| def test_check_approval_approved(self): | |
| """Test approval check when approved.""" | |
| workflow = MarketIntelligenceWorkflow() | |
| state = { | |
| "approved": True, | |
| "revision_count": 0, | |
| } | |
| result = workflow._check_approval(state) | |
| assert result == "approved" | |
| def test_check_approval_max_revisions(self): | |
| """Test approval check at max revisions.""" | |
| workflow = MarketIntelligenceWorkflow() | |
| state = { | |
| "approved": False, | |
| "revision_count": 2, | |
| } | |
| result = workflow._check_approval(state) | |
| assert result == "max_revisions" | |
| def test_check_approval_revision_requested(self): | |
| """Test approval check with feedback.""" | |
| workflow = MarketIntelligenceWorkflow() | |
| state = { | |
| "approved": False, | |
| "revision_count": 0, | |
| "human_feedback": "Please add more details", | |
| } | |
| result = workflow._check_approval(state) | |
| assert result == "revise" | |
| class TestWorkflowNodes: | |
| """Test individual workflow nodes.""" | |
| async def test_research_node_structure(self): | |
| """Test research node returns correct state structure.""" | |
| workflow = MarketIntelligenceWorkflow() | |
| # Mock the research agent's run method | |
| workflow.research_agent.run = AsyncMock( | |
| return_value={ | |
| "company_name": "Test Company", | |
| "company_overview": "Overview", | |
| "competitors": "Competitors", | |
| "market_trends": "Trends", | |
| "raw_sources": [], | |
| } | |
| ) | |
| state = { | |
| "company_name": "Test Company", | |
| "industry": "Technology", | |
| "iteration": 0, | |
| } | |
| result = await workflow._research_node(state) | |
| assert "current_agent" in result | |
| assert result["current_agent"] == "research" | |
| assert "iteration" in result | |
| async def test_human_review_node_auto_approves(self): | |
| """Test human review node auto-approves for now.""" | |
| workflow = MarketIntelligenceWorkflow() | |
| state = { | |
| "company_name": "Test Company", | |
| } | |
| result = await workflow._human_review_node(state) | |
| assert result["current_agent"] == "human_review" | |
| assert result["approved"] is True | |
| assert result["human_feedback"] is None | |