"""Test handler.""" from unittest.mock import MagicMock, patch import pytest from ddex_ingester_common.constants.send_acknowledgement import ( SME_ERROR_STATUS, SME_SUCCESS_STATUS) from requests import Response import index from config import SME_DDEXWS_HOST from constants.status import INGESTION_FAILURE_STATUS, INGESTION_SUCCESS_STATUS @patch('index.logger') @patch('index.send_ack') @patch('index.ddex_scsm') @patch('index.register_ddex_result') def test_handler( mock_register_ddex_result, mock_dcsm, mock_send_ack, mock_current_logger, context_success): """Test the main handler.""" mock_logger = MagicMock(name='info') mock_current_logger.return_value = mock_logger mock_response = Response() mock_response.status_code = 200 mock_send_ack.return_value = mock_response mock_dcsm_generator = MagicMock(name='DDEXSupplyChainStatusMessage') mock_dcsm.return_value = mock_dcsm_generator index.handler(context_success, None) mock_dcsm.DDEXSupplyChainStatusMessage.assert_called_with( 'A10301A0004280500R', SME_SUCCESS_STATUS) mock_register_ddex_result.assert_called_with( '231232563123', INGESTION_SUCCESS_STATUS, '2021-07-13T09:20:48.653Z', '12345', 'key') @patch('index.secrets_manager_client') @patch('index.auth') @patch('index.requests') @pytest.mark.parametrize('ddex_provider,secret_prefix', [('SME_ANALYTICS_PROVIDER', 'SME_ANALYTICS_PROVIDER'), ('SME', 'SME_DDEXWS')]) def test_send_ack(mock_requests, mock_auth, mock_secret_manager_client, ddex_provider, secret_prefix): """Test send_ack.""" mock_requests.return_value = MagicMock( name={'Request', 'Session'}) mock_auth.return_value = MagicMock(name='HTTPBasicAuth') mock_secret_manager_client.return_value = MagicMock(name='get_cred') index.send_ack('this is the XML', ddex_provider) assert mock_requests.Session.called mock_requests.Request.assert_called_with( method='post', url=SME_DDEXWS_HOST, auth=mock_auth.HTTPBasicAuth( username=None, password=None ), headers={'Content-Type': 'application/xml'}, data='this is the XML' ) mock_secret_manager_client.get_cred.assert_any_call( f'{secret_prefix}_PASSWD') mock_secret_manager_client.get_cred.assert_any_call( f'{secret_prefix}_USER') @patch('index.logger') @patch('index.send_ack') @patch('index.ddex_scsm') @patch('index.boto3.client') @patch('index.register_ddex_result') def test_handler_with_error( mock_register_ddex_result, mock_boto3_client, mock_dcsm, mock_send_ack, mock_current_logger, error_context, ddex_xml): """Test the main handler.""" mock_logger = MagicMock(name='info') mock_current_logger.return_value = mock_logger mock_response = Response() mock_response.status_code = 200 mock_send_ack.return_value = mock_response mock_dcsm_generator = MagicMock(name='DDEXSupplyChainStatusMessage') mock_dcsm.return_value = mock_dcsm_generator mock_s3_client = MagicMock(name='get_object') mock_fileobject = MagicMock(name='read') mock_fileobject.read.return_value = ddex_xml mock_s3_client.get_object.return_value = { 'Body': mock_fileobject } mock_boto3_client.return_value = mock_s3_client index.handler(error_context, None) mock_logger.info.assert_not_called() mock_dcsm.DDEXSupplyChainStatusMessage.assert_called_with( 'A10301A00035480592', SME_ERROR_STATUS) mock_register_ddex_result.assert_called_with( '195497918690', INGESTION_FAILURE_STATUS, None, '222894344', 'sme_ddex/20201214203341552/A10301A00035480592.xml' ) @patch('index.send_ack') @patch('index.ddex_scsm') @patch('index.boto3.client') @patch('index.register_ddex_result') def test_handler_with_malformed_xml( mock_register_ddex_result, mock_boto3_client, mock_dcsm, mock_send_ack, error_context): """Test the main handler.""" mock_response = Response() mock_response.status_code = 200 mock_send_ack.return_value = mock_response mock_dcsm_generator = MagicMock(name='DDEXSupplyChainStatusMessage') mock_dcsm.return_value = mock_dcsm_generator mock_s3_client = MagicMock(name='get_object') mock_fileobject = MagicMock(name='read') mock_fileobject.read.return_value = 'not an xml' mock_s3_client.get_object.return_value = { 'Body': mock_fileobject } mock_boto3_client.return_value = mock_s3_client with pytest.raises(SystemError) as e: index.handler(error_context, None) mock_dcsm.DDEXSupplyChainStatusMessage.assert_called_with( 'A10301A00035480592', SME_ERROR_STATUS) # Malformed DDEX so no UPC to parse from it. mock_register_ddex_result.assert_not_called() assert str(e.value) == \ 'No UPC parsed to be able to call Switchboard with DDEX result' @patch('index.logger') @patch('index.send_ack') @patch('index.ddex_scsm') @patch('index.boto3.client') @patch('index.register_ddex_result') def test_handler_with_webservice_error( mock_register_ddex_result, mock_boto3_client, mock_dcsm, mock_send_ack, mock_current_logger, error_context, ddex_xml): """Test the main handler.""" mock_logger = MagicMock(name='info') mock_current_logger.return_value = mock_logger mock_response = Response() mock_response.status_code = 500 mock_response._content = 'Error handling request' mock_send_ack.return_value = mock_response mock_dcsm_generator = MagicMock(name='DDEXSupplyChainStatusMessage') mock_dcsm.return_value = mock_dcsm_generator mock_s3_client = MagicMock(name='get_object') mock_fileobject = MagicMock(name='read') mock_fileobject.read.return_value = ddex_xml mock_s3_client.get_object.return_value = { 'Body': mock_fileobject } mock_boto3_client.return_value = mock_s3_client with pytest.raises(SystemError) as e: index.handler(error_context, None) mock_logger.info.assert_not_called() mock_dcsm.DDEXSupplyChainStatusMessage.assert_called_with( 'A10301A00035480592', SME_ERROR_STATUS) assert str(e.value) == \ f'Call to SME DDEX WS failed. Response: {mock_response.content}' @patch('index.config.graphql_switchboard') @patch('index.generate_switchboard_jwt') def test_register_ddex_result_success( mock_generate_switchboard_jwt, mock_graphql_switchboard): """Test register_ddex_result.""" expected_graphql_input = { 'input': { 'upc': '195497918690', 'status': 'SUCCESS', 'timestamp': '2021-07-13T09:20:48.653Z', 'ddexMessageId': '12345', 'deliveryLocation': 'key' } } index.register_ddex_result( expected_graphql_input['input']['upc'], INGESTION_SUCCESS_STATUS, expected_graphql_input['input']['timestamp'], expected_graphql_input['input']['ddexMessageId'], expected_graphql_input['input']['deliveryLocation'] ) assert mock_graphql_switchboard.execute.called actual_graphql_input = mock_graphql_switchboard.execute.call_args[0][1] assert actual_graphql_input == expected_graphql_input @patch('index.config.graphql_switchboard') @patch('index.generate_switchboard_jwt') def test_register_ddex_result_failure( mock_generate_switchboard_jwt, mock_graphql_switchboard): """Test register_ddex_result.""" expected_graphql_input = { 'input': { 'upc': '195497918690', 'status': 'FAILURE', 'timestamp': '2021-07-13T09:20:48.653Z', 'ddexMessageId': '12345', 'deliveryLocation': 'key' } } index.register_ddex_result( expected_graphql_input['input']['upc'], INGESTION_FAILURE_STATUS, expected_graphql_input['input']['timestamp'], expected_graphql_input['input']['ddexMessageId'], expected_graphql_input['input']['deliveryLocation'] ) assert mock_graphql_switchboard.execute.called actual_graphql_input = mock_graphql_switchboard.execute.call_args[0][1] assert actual_graphql_input == expected_graphql_input