""" Tests for FAZA 2 extended helper functions. Tests new helpers for treasury breakdown, clients/suppliers with maturity, and invoices. """ import pytest from unittest.mock import AsyncMock, patch, MagicMock from app.bot.helpers import ( get_treasury_breakdown_split, get_clients_with_maturity, get_suppliers_with_maturity, get_cashflow_evolution_data, get_client_invoices, get_supplier_invoices ) @pytest.mark.asyncio async def test_get_treasury_breakdown_split(): """Test split trezorerie în casa/banca""" mock_response = { 'accounts': [ {'name': 'Casa Ron', 'type': 'Casa', 'balance': 5000}, {'name': 'Casa Valuta', 'type': 'Casa', 'balance': 2000}, {'name': 'BCR', 'type': 'Banca', 'balance': 10000}, {'name': 'BRD', 'type': 'Banca', 'balance': 5000} ] } with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.get_treasury_breakdown = AsyncMock(return_value=mock_response) mock_client_getter.return_value = mock_client result = await get_treasury_breakdown_split(1, "fake_token") assert result is not None assert 'casa' in result assert 'banca' in result assert result['casa']['total'] == 7000 # 5000 + 2000 assert result['banca']['total'] == 15000 # 10000 + 5000 assert len(result['casa']['accounts']) == 2 assert len(result['banca']['accounts']) == 2 @pytest.mark.asyncio async def test_get_treasury_breakdown_split_casa_in_name(): """Test că identifică casa după nume (nu doar după type)""" mock_response = { 'accounts': [ {'name': 'Casa principala', 'type': 'Gest', 'balance': 3000}, {'name': 'Cont BCR', 'type': 'Gest', 'balance': 10000} ] } with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.get_treasury_breakdown = AsyncMock(return_value=mock_response) mock_client_getter.return_value = mock_client result = await get_treasury_breakdown_split(1, "fake_token") assert result['casa']['total'] == 3000 # Casa identificată după nume assert result['banca']['total'] == 10000 @pytest.mark.asyncio async def test_get_treasury_breakdown_split_api_error(): """Test comportament când API returnează None""" with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.get_treasury_breakdown = AsyncMock(return_value=None) mock_client_getter.return_value = mock_client result = await get_treasury_breakdown_split(1, "fake_token") assert result is None @pytest.mark.asyncio async def test_get_clients_with_maturity(): """Test obținere clienți cu scadențe""" mock_clients_data = { 'clients': [ {'id': 1, 'name': 'Client A', 'balance': 15000}, {'id': 2, 'name': 'Client B', 'balance': 8500} ] } mock_maturity_data = { 'in_term': 18000, 'overdue': 5500, 'total': 23500 } with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.get_detailed_data = AsyncMock(return_value=mock_clients_data) mock_client.get_maturity_data = AsyncMock(return_value=mock_maturity_data) mock_client_getter.return_value = mock_client result = await get_clients_with_maturity(1, "fake_token") assert result is not None assert 'clients' in result assert 'maturity' in result assert len(result['clients']) == 2 assert result['maturity']['in_term'] == 18000 assert result['maturity']['overdue'] == 5500 assert result['maturity']['total'] == 23500 @pytest.mark.asyncio async def test_get_clients_with_maturity_items_key(): """Test că acceptă atât 'clients' cât și 'items' ca key""" mock_clients_data = { 'items': [ {'id': 1, 'name': 'Client A', 'balance': 15000} ] } mock_maturity_data = {'in_term': 15000, 'overdue': 0, 'total': 15000} with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.get_detailed_data = AsyncMock(return_value=mock_clients_data) mock_client.get_maturity_data = AsyncMock(return_value=mock_maturity_data) mock_client_getter.return_value = mock_client result = await get_clients_with_maturity(1, "fake_token") assert len(result['clients']) == 1 @pytest.mark.asyncio async def test_get_clients_with_maturity_no_maturity_data(): """Test fallback când maturity data e None""" mock_clients_data = { 'clients': [{'id': 1, 'name': 'Client A', 'balance': 15000}] } with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.get_detailed_data = AsyncMock(return_value=mock_clients_data) mock_client.get_maturity_data = AsyncMock(return_value=None) mock_client_getter.return_value = mock_client result = await get_clients_with_maturity(1, "fake_token") assert result['maturity'] == {'in_term': 0, 'overdue': 0, 'total': 0} @pytest.mark.asyncio async def test_get_suppliers_with_maturity(): """Test obținere furnizori cu scadențe""" mock_suppliers_data = { 'suppliers': [ {'id': 1, 'name': 'Supplier A', 'balance': 5000} ] } mock_maturity_data = { 'in_term': 4000, 'overdue': 1000, 'total': 5000 } with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.get_detailed_data = AsyncMock(return_value=mock_suppliers_data) mock_client.get_maturity_data = AsyncMock(return_value=mock_maturity_data) mock_client_getter.return_value = mock_client result = await get_suppliers_with_maturity(1, "fake_token") assert result is not None assert 'suppliers' in result assert 'maturity' in result assert len(result['suppliers']) == 1 @pytest.mark.asyncio async def test_get_cashflow_evolution_data(): """Test obținere date evoluție cash flow""" mock_performance = { 'incasari_total': 100000, 'plati_total': 80000, 'net': 20000 } mock_monthly = { 'months': ['Ian', 'Feb', 'Mar'], 'incasari': [30000, 35000, 35000], 'plati': [25000, 27000, 28000] } with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.get_performance_data = AsyncMock(return_value=mock_performance) mock_client.get_monthly_flows = AsyncMock(return_value=mock_monthly) mock_client_getter.return_value = mock_client result = await get_cashflow_evolution_data(1, "fake_token") assert result is not None assert 'performance' in result assert 'monthly' in result assert result['performance']['net'] == 20000 assert len(result['monthly']['months']) == 3 @pytest.mark.asyncio async def test_get_cashflow_evolution_data_no_monthly(): """Test fallback când monthly data e None""" mock_performance = { 'incasari_total': 100000, 'plati_total': 80000, 'net': 20000 } with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.get_performance_data = AsyncMock(return_value=mock_performance) mock_client.get_monthly_flows = AsyncMock(return_value=None) mock_client_getter.return_value = mock_client result = await get_cashflow_evolution_data(1, "fake_token") assert result['monthly'] == {'months': [], 'incasari': [], 'plati': []} @pytest.mark.asyncio async def test_get_client_invoices(): """Test obținere facturi client""" mock_invoices = [ {'id': 1, 'number': 'FV001', 'amount': 5000, 'status': 'unpaid'}, {'id': 2, 'number': 'FV002', 'amount': 3500, 'status': 'paid'} ] with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.search_invoices = AsyncMock(return_value=mock_invoices) mock_client_getter.return_value = mock_client result = await get_client_invoices(1, "Client A", "fake_token") assert len(result) == 2 assert result[0]['number'] == 'FV001' # Verifică că a fost apelat cu filtrul corect mock_client.search_invoices.assert_called_once() call_args = mock_client.search_invoices.call_args assert call_args[1]['filters']['partner_type'] == 'CLIENTI' assert call_args[1]['filters']['partner_name'] == 'Client A' @pytest.mark.asyncio async def test_get_supplier_invoices(): """Test obținere facturi furnizor""" mock_invoices = [ {'id': 1, 'number': 'FC001', 'amount': 2000, 'status': 'unpaid'} ] with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.search_invoices = AsyncMock(return_value=mock_invoices) mock_client_getter.return_value = mock_client result = await get_supplier_invoices(1, "Supplier A", "fake_token") assert len(result) == 1 assert result[0]['number'] == 'FC001' # Verifică că a fost apelat cu filtrul corect mock_client.search_invoices.assert_called_once() call_args = mock_client.search_invoices.call_args assert call_args[1]['filters']['partner_type'] == 'FURNIZORI' assert call_args[1]['filters']['partner_name'] == 'Supplier A' @pytest.mark.asyncio async def test_get_client_invoices_empty(): """Test comportament când nu există facturi""" with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mock_client.search_invoices = AsyncMock(return_value=[]) mock_client_getter.return_value = mock_client result = await get_client_invoices(1, "Client A", "fake_token") assert result == [] @pytest.mark.asyncio async def test_get_client_invoices_error_handling(): """Test error handling pentru get_client_invoices""" with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(side_effect=Exception("API Error")) mock_client_getter.return_value = mock_client result = await get_client_invoices(1, "Client A", "fake_token") assert result == [] # Returnează listă goală la eroare @pytest.mark.asyncio async def test_helpers_handle_none_responses(): """Test că helper-ii handle-uiesc răspunsuri None de la API""" with patch('app.bot.helpers.get_backend_client') as mock_client_getter: mock_client = MagicMock() mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) # Test toate funcțiile cu None responses mock_client.get_detailed_data = AsyncMock(return_value=None) mock_client.get_maturity_data = AsyncMock(return_value=None) mock_client.get_performance_data = AsyncMock(return_value=None) mock_client.get_monthly_flows = AsyncMock(return_value=None) mock_client.search_invoices = AsyncMock(return_value=None) mock_client_getter.return_value = mock_client # Niciunul nu ar trebui să crapeze result1 = await get_clients_with_maturity(1, "token") assert result1 is None result2 = await get_suppliers_with_maturity(1, "token") assert result2 is None result3 = await get_cashflow_evolution_data(1, "token") assert result3 is None result4 = await get_client_invoices(1, "Client", "token") assert result4 == [] # Empty list, not None result5 = await get_supplier_invoices(1, "Supplier", "token") assert result5 == [] # Empty list, not None