"""Test ABACUS state logic.""" from typing import NamedTuple from unittest import mock import pytest from src.logic import abacus_state from src.models.ows_abacus_state import AbacusStateGetResponseItemModel from src.models.payee import Payee, PayeeEntityType from tests.unit.factories import AbacusStateGetResponseItemFactory def get_items( id_name_status: list[tuple[int, str, str]] | None = None, ) -> dict[str, AbacusStateGetResponseItemModel] | None: """Generate test items list.""" if id_name_status is None: return None result = [ AbacusStateGetResponseItemFactory.build( abacus_state_id=abacus_state_id, action_name=action_name, action_status=action_status, ) for abacus_state_id, action_name, action_status in id_name_status ] return {i.action_name: i for i in result} def inner_set_param( name_status: dict[str, str] | None = None, get_result: list[tuple[int, str, str]] | None = None, create_result: list[tuple[int, str, str]] | None = None, missing_names: list[str] | None = None, state_id_to_status: dict[int, str] | None = None, ) -> NamedTuple: """Build test params for _set_states.""" return pytest.param( name_status or {}, get_items(get_result or []), get_items(create_result), missing_names, state_id_to_status, ) @pytest.mark.parametrize( 'name_status,get_result,create_result,missing_names,state_id_to_status', ( inner_set_param(), inner_set_param( name_status={'ac1': 'st1', 'ac2': 'st2', 'ac3': 'st3'}, get_result=[(1, 'ac1', 'st1'), (2, 'ac2', 'st4'), (5, 'ac5', 'st5')], create_result=[(6, 'ac3', 'new')], missing_names=['ac3'], state_id_to_status={2: 'st2', 6: 'st3'}, ), inner_set_param( name_status={'ac1': 'st1', 'ac2': 'st2', 'ac3': 'st3'}, get_result=[ (1, 'ac1', 'st1'), (2, 'ac2', 'st2'), (3, 'ac3', 'st3'), (4, 'ac4', 'st4'), ], state_id_to_status={1: 'st1', 2: 'st2', 3: 'st3'}, ), inner_set_param( name_status={'ac1': 'st1', 'ac2': 'st2', 'ac3': 'st3'}, get_result=[(5, 'ac5', 'st5'), (6, 'ac6', 'st6')], create_result=[(7, 'ac1', 'new'), (8, 'ac2', 'new'), (9, 'ac3', 'new')], missing_names=['ac1', 'ac2', 'ac3'], state_id_to_status={7: 'st1', 8: 'st2', 9: 'st3'}, ), inner_set_param( name_status={'ac1': 'st1', 'ac2': 'st2', 'ac3': 'st3'}, get_result=[(1, 'ac1', 'st7'), (2, 'ac2', 'st8'), (3, 'ac3', 'st8')], state_id_to_status={1: 'st1', 2: 'st2', 3: 'st3'}, ), ), ) @mock.patch('src.logic.abacus_state.create_states') @mock.patch('src.logic.abacus_state.update_state') def test_internal_set_states( mocked_update_state: mock.Mock, mocked_create_states: mock.Mock, name_status: dict[str, str], get_result: dict[str, AbacusStateGetResponseItemModel], create_result: dict[str, AbacusStateGetResponseItemModel], missing_names: list[str], state_id_to_status: dict[int, str], ) -> None: """Test set_states.""" payee = Payee(payee_type=PayeeEntityType.account_payee, payee_id='233') message = 'test_message' mocked_create_states.return_value = create_result abacus_state._set_states(payee, message, name_status, get_result) if missing_names: mocked_create_states.assert_called_once() assert len(mocked_create_states.call_args.args) == 2 assert ( mocked_create_states.call_args.args[0], list(sorted(mocked_create_states.call_args.args[1])), ) == (payee, missing_names) else: mocked_create_states.assert_not_called() if state_id_to_status: mocked_update_state.assert_has_calls( [ mock.call(state_id, status, message) for state_id, status in state_id_to_status.items() ] ) else: mocked_update_state.assert_not_called() def shared_set_param( banking_details_review_status: str, payment_eligibility_status: str | None = None, get_result: dict[str, str] | None = None, action_name_to_status: dict[str, str] | None = None, captured_message: str | None = None, expected_result: bool = True, ) -> NamedTuple: """Build test params for set_states.""" get_data = [ (int(index) + 1, name, state) for index, (name, state) in enumerate((get_result or {}).items()) ] return pytest.param( banking_details_review_status, payment_eligibility_status, get_items(get_data), action_name_to_status, captured_message, expected_result, ) @pytest.mark.parametrize( ( 'banking_details_review_status,payment_eligibility_status,action_name_to_state,' 'action_name_to_status,captured_message,expected_result' ), ( shared_set_param( banking_details_review_status='init', get_result={'banking_details_review': 'init'}, captured_message='Cannot change banking_details_review 1 status init -> init', expected_result=False, ), shared_set_param( banking_details_review_status='abc', get_result={'banking_details_review': 'init'}, captured_message='Cannot change banking_details_review 1 status init -> abc', expected_result=False, ), shared_set_param( banking_details_review_status='running', get_result={'banking_details_review': 'approved'}, captured_message='Cannot change banking_details_review 1 status approved -> running', expected_result=False, ), shared_set_param( banking_details_review_status='running', get_result={'banking_details_review': 'rejected'}, captured_message='Cannot change banking_details_review 1 status rejected -> running', expected_result=False, ), shared_set_param( banking_details_review_status='running', get_result={'banking_details_review': 'dummy'}, captured_message='Cannot change banking_details_review 1 status dummy -> running', expected_result=False, ), shared_set_param( banking_details_review_status='approved', get_result={'banking_details_review': 'approved'}, captured_message='Cannot change banking_details_review 1 status approved -> approved', expected_result=False, ), shared_set_param( banking_details_review_status='rejected', get_result={'banking_details_review': 'rejected'}, captured_message='Cannot change banking_details_review 1 status rejected -> rejected', expected_result=False, ), shared_set_param( banking_details_review_status='running', get_result={'banking_details_review': 'running'}, action_name_to_status={'banking_details_review': 'running'}, ), shared_set_param( banking_details_review_status='running', payment_eligibility_status='status1', get_result={'banking_details_review': 'init'}, action_name_to_status={ 'banking_details_review': 'running', 'payment_eligibility': 'status1', }, ), shared_set_param( banking_details_review_status='approved', payment_eligibility_status='status2', get_result={'banking_details_review': 'running'}, action_name_to_status={ 'banking_details_review': 'approved', 'payment_eligibility': 'status2', }, ), shared_set_param( banking_details_review_status='rejected', get_result={'banking_details_review': 'running'}, action_name_to_status={'banking_details_review': 'rejected'}, ), shared_set_param( banking_details_review_status='approved', get_result={'banking_details_review': 'init'}, action_name_to_status={'banking_details_review': 'approved'}, ), shared_set_param( banking_details_review_status='rejected', get_result={'banking_details_review': 'init'}, action_name_to_status={'banking_details_review': 'rejected'}, ), ), ) @mock.patch('src.logic.abacus_state._set_states') @mock.patch('src.logic.abacus_state.capture_message') @mock.patch('src.logic.abacus_state.get_all_states') def test_set_states( mocked_get_all_states: mock.Mock, mocked_capture_message: mock.Mock, mocked__set_states: mock.Mock, banking_details_review_status: str, payment_eligibility_status: str | None, action_name_to_state: dict[str, AbacusStateGetResponseItemModel] | None, action_name_to_status: dict[str, str] | None, captured_message: str | None, expected_result: bool, ) -> None: """Test set_states.""" payee = Payee(payee_type=PayeeEntityType.account_payee, payee_id='233') message = 'test_message' mocked_get_all_states.return_value = action_name_to_state result = abacus_state.set_states( payee, message, banking_details_review_status, payment_eligibility_status, ) assert result == expected_result mocked_get_all_states.assert_called_once_with(payee) if captured_message: mocked_capture_message.assert_called_once_with(captured_message, 'error') else: mocked_capture_message.assert_not_called() if action_name_to_status: mocked__set_states.assert_called_once_with( payee, message, action_name_to_status, action_name_to_state ) else: mocked__set_states.assert_not_called()