"""Unit tests for payment search handler.""" import datetime from unittest.mock import call, patch from payment.constants.error import ERROR_PAYMENTS_SEARCH_REQUIRED_FILTERS from payment.schemas.payment_search import ( PaymentSearchFilterParamsPostSchema, PaymentSearchListSchema, ) from tests.utils.factories import PaymentSearchItemFactory @patch('payment.blueprints.payment_search.logic') def test_search_payments_success(mock_logic, fixture_client, mocker): """Test POST /payment-search/search with all filters returns 200.""" mock_payment_items = PaymentSearchItemFactory.create_batch(1) body = { 'filters': { 'account': '10863', 'contract': '87653', 'payment_types': ['balance_payment', 'advance_payment'], 'payment_statuses': ['successful', 'cancelled'], 'payment_release_date_from': '2025-01-01', 'payment_release_date_to': '2025-03-31', 'payment_created_date_from': '2025-01-01', 'payment_created_date_to': '2025-03-31', } } mock_result = {'items': mock_payment_items, 'total_count': len(mock_payment_items)} mock_logic.search_payments.return_value = mock_result spy_validation = mocker.spy(PaymentSearchFilterParamsPostSchema, 'load') spy_serialization = mocker.spy(PaymentSearchListSchema, 'dump') res = fixture_client.post('/payment-search/search', json=body) assert res.status_code == 200, res.text assert res.json == mock_result assert mock_logic.search_payments.call_args_list == [ call( account='10863', contract='87653', payment_types=['balance_payment', 'advance_payment'], payment_statuses=['successful', 'cancelled'], payment_release_date_from=datetime.date(2025, 1, 1), payment_release_date_to=datetime.date(2025, 3, 31), payment_created_date_from=datetime.date(2025, 1, 1), payment_created_date_to=datetime.date(2025, 3, 31), ) ] assert spy_validation.called assert spy_serialization.called @patch('payment.blueprints.payment_search.logic') def test_search_payments_single_filter(mock_logic, fixture_client): """Test POST /payment-search/search with a single account filter returns 200.""" mock_payment_items = PaymentSearchItemFactory.create_batch(1) body = {'filters': {'account': '10863'}} mock_result = {'items': mock_payment_items, 'total_count': len(mock_payment_items)} mock_logic.search_payments.return_value = mock_result res = fixture_client.post('/payment-search/search', json=body) assert res.status_code == 200, res.text assert res.json == mock_result assert mock_logic.search_payments.call_args_list == [call(account='10863')] @patch('payment.blueprints.payment_search.logic') def test_search_payments_empty_filters_returns_400(mock_logic, fixture_client): """Test POST /payment-search/search with no filters returns 400.""" res = fixture_client.post('/payment-search/search', json={}) assert res.status_code == 400, res.text assert res.json['code'] == 'error' assert res.json['message'] == {'json': {'filters': ['Must be specified.']}} assert not mock_logic.search_payments.called res = fixture_client.post('/payment-search/search', json={'filters': {}}) assert res.status_code == 400, res.text assert res.json['code'] == 'error' assert res.json['message'] == { 'json': {'filters': {'_schema': [ERROR_PAYMENTS_SEARCH_REQUIRED_FILTERS]}} } assert not mock_logic.search_payments.called @patch('payment.blueprints.payment_search.logic') def test_search_payments_invalid_date_returns_400(mock_logic, fixture_client): """Test POST /payment-search/search with invalid date format returns 400.""" body = {'filters': {'payment_release_date_from': 'not-a-date'}} res = fixture_client.post('/payment-search/search', json=body) assert res.status_code == 400, res.text assert not mock_logic.search_payments.called @patch('payment.blueprints.payment_search.logic') def test_search_payments_invalid_payment_type_returns_400(mock_logic, fixture_client): """Test POST /payment-search/search with invalid payment_type value returns 400.""" body = {'filters': {'payment_types': ['invalid_type']}} res = fixture_client.post('/payment-search/search', json=body) assert res.status_code == 400, res.text assert not mock_logic.search_payments.called @patch('payment.blueprints.payment_search.logic') def test_search_payments_invalid_payment_status_returns_400(mock_logic, fixture_client): """Test POST /payment-search/search with invalid payment_status value returns 400.""" body = {'filters': {'payment_statuses': ['invalid_status']}} res = fixture_client.post('/payment-search/search', json=body) assert res.status_code == 400, res.text assert not mock_logic.search_payments.called