"""Unit tests for AgentRegistry.""" import pytest from unittest.mock import AsyncMock, MagicMock from agent_service.agents.registry import AgentRegistry def _make_registry(): return AgentRegistry() def _make_agent(name='test_agent'): agent = MagicMock() agent.name = name return agent # ── register / get_agent_instance ─────────────────────────────────────────── def test_register_stores_instance(): reg = _make_registry() agent = _make_agent() reg.register('test_agent', agent) assert reg.get_agent_instance('test_agent') is agent def test_register_missing_returns_none(): reg = _make_registry() assert reg.get_agent_instance('nonexistent') is None def test_register_activates_agent(): reg = _make_registry() reg.register('test_agent', _make_agent()) assert 'test_agent' in reg._active def test_register_assigns_default_capability(): reg = _make_registry() reg.register('test_agent', _make_agent()) assert reg._capabilities.get('test_agent') def test_register_known_agent_uses_default_description(): reg = _make_registry() reg.register('crm_agent', _make_agent('crm_agent')) assert 'crm' in reg._capabilities['crm_agent'].lower() or \ 'lead' in reg._capabilities['crm_agent'].lower() def test_register_multiple_agents(): reg = _make_registry() reg.register('crm_agent', _make_agent('crm_agent')) reg.register('sales_agent', _make_agent('sales_agent')) assert len(reg._agents) == 2 # ── is_active ──────────────────────────────────────────────────────────────── @pytest.mark.asyncio async def test_is_active_after_register(): reg = _make_registry() reg.register('crm_agent', _make_agent()) assert await reg.is_active('crm_agent') is True @pytest.mark.asyncio async def test_is_active_unknown_agent(): reg = _make_registry() assert await reg.is_active('ghost_agent') is False # ── get_active_agents ──────────────────────────────────────────────────────── @pytest.mark.asyncio async def test_get_active_agents_returns_only_registered(): reg = _make_registry() reg.register('crm_agent', _make_agent()) reg._active.add('ghost_agent') # active but no instance result = await reg.get_active_agents() keys = {r['agent_key'] for r in result} assert 'crm_agent' in keys assert 'ghost_agent' not in keys @pytest.mark.asyncio async def test_get_active_agents_includes_capabilities(): reg = _make_registry() reg.register('crm_agent', _make_agent()) result = await reg.get_active_agents() assert any('capabilities_summary' in r for r in result) @pytest.mark.asyncio async def test_get_active_agents_empty_registry(): reg = _make_registry() result = await reg.get_active_agents() assert result == [] # ── get_all ────────────────────────────────────────────────────────────────── @pytest.mark.asyncio async def test_get_all_includes_all_registered(): reg = _make_registry() reg.register('crm_agent', _make_agent()) reg.register('sales_agent', _make_agent()) result = await reg.get_all() names = {r['name'] for r in result} assert 'crm_agent' in names assert 'sales_agent' in names @pytest.mark.asyncio async def test_get_all_marks_active_flag(): reg = _make_registry() reg.register('crm_agent', _make_agent()) result = await reg.get_all() crm = next(r for r in result if r['name'] == 'crm_agent') assert crm['active'] is True assert crm['has_instance'] is True # ── sync ───────────────────────────────────────────────────────────────────── @pytest.mark.asyncio async def test_sync_replaces_active_set(): reg = _make_registry() reg.register('crm_agent', _make_agent()) reg.register('sales_agent', _make_agent()) await reg.sync(['sales_agent']) assert await reg.is_active('sales_agent') is True assert await reg.is_active('crm_agent') is False @pytest.mark.asyncio async def test_sync_with_empty_list_deactivates_all(): reg = _make_registry() reg.register('crm_agent', _make_agent()) await reg.sync([]) assert await reg.is_active('crm_agent') is False # ── load_from_odoo ─────────────────────────────────────────────────────────── @pytest.mark.asyncio async def test_load_from_odoo_sets_active_agents(): reg = _make_registry() odoo = MagicMock() odoo.search_read = AsyncMock(return_value=[ {'agent_name': 'crm_agent', 'domain': 'CRM leads', 'backend': 'local'}, {'agent_name': 'sales_agent', 'domain': '', 'backend': 'cloud'}, ]) await reg.load_from_odoo(odoo) assert 'crm_agent' in reg._active assert 'sales_agent' in reg._active @pytest.mark.asyncio async def test_load_from_odoo_uses_domain_when_present(): reg = _make_registry() odoo = MagicMock() odoo.search_read = AsyncMock(return_value=[ {'agent_name': 'crm_agent', 'domain': 'Custom CRM description', 'backend': 'local'}, ]) await reg.load_from_odoo(odoo) assert reg._capabilities['crm_agent'] == 'Custom CRM description' @pytest.mark.asyncio async def test_load_from_odoo_falls_back_to_default_when_no_domain(): reg = _make_registry() odoo = MagicMock() odoo.search_read = AsyncMock(return_value=[ {'agent_name': 'crm_agent', 'domain': '', 'backend': 'local'}, ]) await reg.load_from_odoo(odoo) assert reg._capabilities.get('crm_agent') @pytest.mark.asyncio async def test_load_from_odoo_handles_exception_gracefully(): reg = _make_registry() odoo = MagicMock() odoo.search_read = AsyncMock(side_effect=Exception('DB error')) await reg.load_from_odoo(odoo) assert reg._active == set()