| | """TDD tests for Parlant guideline configuration.""" |
| |
|
| | from unittest.mock import AsyncMock, MagicMock |
| |
|
| | import pytest |
| |
|
| | from trialpath.agent.guidelines import GUIDELINE_SPECS, configure_guidelines |
| |
|
| |
|
| | class TestGuidelineConfiguration: |
| | """Test guideline setup.""" |
| |
|
| | @pytest.fixture |
| | def mock_agent(self): |
| | agent = MagicMock() |
| | agent.create_guideline = AsyncMock(return_value=MagicMock()) |
| | return agent |
| |
|
| | @pytest.mark.asyncio |
| | async def test_correct_number_of_guidelines(self, mock_agent): |
| | """Should create exactly 11 guidelines.""" |
| | guidelines = await configure_guidelines(mock_agent) |
| | assert len(guidelines) == 11 |
| | assert mock_agent.create_guideline.call_count == 11 |
| |
|
| | def test_each_guideline_has_condition_and_action(self): |
| | """Each spec should have condition and action strings.""" |
| | for spec in GUIDELINE_SPECS: |
| | assert "condition" in spec |
| | assert "action" in spec |
| | assert isinstance(spec["condition"], str) |
| | assert isinstance(spec["action"], str) |
| | assert len(spec["condition"]) > 10 |
| | assert len(spec["action"]) > 10 |
| |
|
| | def test_ingest_guidelines_count(self): |
| | """Should have 2 INGEST phase guidelines.""" |
| | ingest = [s for s in GUIDELINE_SPECS if s["phase"] == "INGEST"] |
| | assert len(ingest) == 2 |
| |
|
| | def test_prescreen_guidelines_count(self): |
| | """Should have 3 PRESCREEN phase guidelines.""" |
| | prescreen = [s for s in GUIDELINE_SPECS if s["phase"] == "PRESCREEN"] |
| | assert len(prescreen) == 3 |
| |
|
| | def test_validate_trials_guidelines_count(self): |
| | """Should have 1 VALIDATE_TRIALS guideline.""" |
| | validate = [s for s in GUIDELINE_SPECS if s["phase"] == "VALIDATE_TRIALS"] |
| | assert len(validate) == 1 |
| |
|
| | def test_gap_followup_guidelines_count(self): |
| | """Should have 1 GAP_FOLLOWUP guideline.""" |
| | gap = [s for s in GUIDELINE_SPECS if s["phase"] == "GAP_FOLLOWUP"] |
| | assert len(gap) == 1 |
| |
|
| | def test_summary_guidelines_count(self): |
| | """Should have 1 SUMMARY guideline.""" |
| | summary = [s for s in GUIDELINE_SPECS if s["phase"] == "SUMMARY"] |
| | assert len(summary) == 1 |
| |
|
| | def test_global_guidelines_count(self): |
| | """Should have 3 global guidelines.""" |
| | global_g = [s for s in GUIDELINE_SPECS if s["phase"] == "GLOBAL"] |
| | assert len(global_g) == 3 |
| |
|
| | def test_tool_associations(self): |
| | """Guidelines with tools should reference correct tool entries.""" |
| | from parlant.sdk import ToolEntry |
| |
|
| | for spec in GUIDELINE_SPECS: |
| | for tool in spec["tools"]: |
| | assert isinstance(tool, ToolEntry), ( |
| | f"Tool {tool} in guideline '{spec['condition'][:30]}...' is not a ToolEntry" |
| | ) |
| |
|
| | def test_medical_disclaimer_guideline_exists(self): |
| | """Should have a medical disclaimer guideline.""" |
| | disclaimer = [ |
| | s |
| | for s in GUIDELINE_SPECS |
| | if "disclaimer" in s["action"].lower() or "medical advice" in s["action"].lower() |
| | ] |
| | assert len(disclaimer) >= 1 |
| |
|
| | @pytest.mark.asyncio |
| | async def test_configure_passes_tools_to_agent(self, mock_agent): |
| | """configure_guidelines should pass tools list to create_guideline.""" |
| | await configure_guidelines(mock_agent) |
| |
|
| | |
| | calls_with_tools = [ |
| | c for c in mock_agent.create_guideline.call_args_list if c.kwargs.get("tools") |
| | ] |
| | assert len(calls_with_tools) > 0 |
| |
|