"""Test lambda app.""" import json from unittest.mock import MagicMock from unittest.mock import patch import pytest import config from src import app as index from src import constants @patch('src.app.get_snowflake_connector') def test_valid_message(snowflake_mock, kafka_mock, valid_message): """Test handler for valid_message.""" mock_cursor = MagicMock() snowflake_mock.__enter__().cursor().__enter__.return_value = mock_cursor result = index.handler(valid_message, None) assert result.get('statusCode') == 200 assert result.get('isBase64Encoded') is False assert result.get('body') == '{"status": "SUCCESS"}' kafka_mock.assert_call_count('produce', 0) @patch('src.app.get_snowflake_connector') def test_snowflake_exception(snowflake_mock, kafka_mock, valid_message): """Test handler any exceptions.""" snowflake_mock.side_effect = Exception('Test') result = index.handler(valid_message, None) assert result is None kafka_mock.assert_call_count('produce', 1) kafka_mock.assert_messages([{ 'topic': config.DLQ_TOPIC, 'value': json.dumps(valid_message).encode('utf-8'), 'key': valid_message.get('requestContext', {}).get('requestId', '').encode('utf-8') }]) @pytest.mark.parametrize('test_input,error_message', [ ({}, constants.INVALID_MESSAGE), ({'pathParameters': {}}, constants.INVALID_MESSAGE), ({'pathParameters': {'vendor': 'unknown'}}, constants.INVALID_MESSAGE), ({'pathParameters': {'vendor': 'smf'}}, constants.INVALID_MESSAGE), ({'pathParameters': {'vendor': 'smf'}, 'dummy': 'message'}, constants.INVALID_MESSAGE), ({'pathParameters': {'vendor': 'smf'}, 'headers': 'message'}, constants.INVALID_MESSAGE), ({'pathParameters': {'vendor': 'smf'}, 'body': 'foobar'}, constants.INVALID_MESSAGE), ({'pathParameters': {'vendor': 'smf'}, 'headers': 'message'}, constants.INVALID_MESSAGE), ( {'pathParameters': {'vendor': 'smf'}, 'body': 'foobar', 'headers': {'authorization': 'test-token'}}, constants.INVALID_MESSAGE_BODY ), ( {'pathParameters': {'vendor': 'smf'}, 'body': '{"foo": "bar"}', 'headers': {'authorization': 'test-token'}}, constants.MISSING_SOURCE ), ( # SOURCE key is case-sensitive {'pathParameters': {'vendor': 'smf'}, 'body': '{"source": "Tunespeak"}', 'headers': {'authorization': 'test-token'}}, constants.MISSING_SOURCE ), ( # SOURCE values is case-sensitive {'pathParameters': {'vendor': 'smf'}, 'body': '{"SOURCE": "tunespeak"}', 'headers': {'authorization': 'test-token'}}, constants.INVALID_SOURCE.format(source='tunespeak') ), ( {'pathParameters': {'vendor': 'smf'}, 'body': '{"SOURCE": "Sony Music Fans"}', 'headers': {'authorization': 'test-token'}}, constants.INVALID_SOURCE.format(source='Sony Music Fans') ), ]) def test_ignored_messages(test_input, error_message, kafka_mock): """Test handler for invalid messages.""" result = index.handler(test_input, None) assert result.get('statusCode') == 400 assert result.get('isBase64Encoded') is False assert json.loads(result.get('body')) == { 'status': 'IGNORED', 'message': error_message} # it does not write this to DLQ since these are known invalid errors. kafka_mock.assert_call_count('produce', 0) def test_prepare_metadata(valid_message): """Test _prepare_metadata.""" metadata = index._prepare_metadata(valid_message) assert 'body' not in metadata assert 'headers' in metadata assert 'Authorization' not in metadata['headers'] assert 'Authorization' not in metadata['multiValueHeaders']