"""Test handler.""" import csv from io import StringIO import os from unittest.mock import MagicMock, patch from botocore.response import StreamingBody from constants.file import ( CSV_DELIMITER, CSV_QUOTECHAR ) from ddex_ingester_common.models.ddex.deal import Deal from ddex_ingester_common.models.ddex.deal_term import DealTerm from ddex_ingester_common.schemas.ddex_schema import DDEXSchema import index import pytest @pytest.mark.parametrize('test_mimetype, test_folder', [ pytest.param('s3_folder_mimetype', True, id='S3 Folder Key'), pytest.param('s3_xml_mimetype', False, id='S3 File Key') ]) @patch('index.s3') @patch('index.write_to_csv') @patch('index.get_matching_s3_keys') @patch('index.process_single_file') @patch('index.xmltodict') def test_handler_creates_csv( mock_xmltodict, mock_process_single_file, mock_get_matching_keys, mock_write_csv, mock_s3_object, test_event, test_context, test_rows, ddex_fluve_multiple_tracks, s3_eligible_keys, test_mimetype, test_folder, request): """Test the main handler.""" mock_s3_object.get_object.return_value = { 'Body': 'test fixture' } mock_s3_object.head_object.return_value = { 'ContentType': request.getfixturevalue(test_mimetype) } mock_xmltodict.parse.return_value = ddex_fluve_multiple_tracks mock_process_single_file.return_value = (test_context, test_rows) mock_get_matching_keys.return_value = s3_eligible_keys output = index.handler(test_event, {}) # Test process_single file called for each eligible file if test_folder: # Count keys in fixture xml_keys = \ [k for k in s3_eligible_keys if os.path.splitext(k)[1] == '.xml'] eligible_file_count = len(xml_keys) assert mock_process_single_file.call_count == eligible_file_count else: # One file in, one file processed. assert mock_process_single_file.call_count == 1 assert mock_write_csv.call_count == 1 assert output @patch('index.s3') @patch('index.write_csv_s3') @patch('index.get_matching_s3_keys') @patch('index.xmltodict') def test_handler_creates_csv_with_pretty_headers( mock_xmltodict, mock_get_matching_keys, mock_write_csv_s3, mock_s3_object, test_event, csv_expected_headers, ddex_fluve_multiple_tracks, s3_xml_mimetype, s3_eligible_keys): """Test the main handler.""" # Mock S3 response for StreamingBody.read() method. s3_get_response = { 'Body': StreamingBody(StringIO(None), 0) } mock_s3_object.get_object.return_value = s3_get_response mock_s3_object.head_object.return_value = { 'ContentType': s3_xml_mimetype, } mock_xmltodict.parse.return_value = ddex_fluve_multiple_tracks mock_get_matching_keys.return_value = s3_eligible_keys index.handler(test_event, {}) with open('tmp/test_output.csv', newline='') as csvfile: reader = csv.reader( csvfile, delimiter=CSV_DELIMITER, quotechar=CSV_QUOTECHAR) headers = next(reader) assert headers == csv_expected_headers assert mock_write_csv_s3.call_count == 1 @patch('index.write_csv_s3', return_value=None) @patch('index.s3') @patch('index.get_matching_s3_keys') @patch('index.xmltodict') def test_handler_creates_csv_row_with_expected_values( mock_xmltodict, mock_get_matching_keys, mock_s3_object, mock_write_csv_s3, test_event, csv_expected_row, ddex_fluve_single, s3_xml_mimetype, s3_eligible_keys): """Test the main handler.""" s3_get_response = { 'Body': StreamingBody(StringIO(None), 0) } mock_s3_object.get_object.return_value = s3_get_response mock_s3_object.head_object.return_value = { 'ContentType': s3_xml_mimetype, } mock_xmltodict.parse.return_value = ddex_fluve_single mock_get_matching_keys.return_value = s3_eligible_keys index.handler(test_event, {}) with open('tmp/test_output.csv', newline='') as csvfile: reader = csv.reader(csvfile, delimiter=CSV_DELIMITER, quotechar=CSV_QUOTECHAR) # noqa headers = next(reader) row = next(reader) assert headers assert row == csv_expected_row assert mock_write_csv_s3.call_count == 1 @patch('index.write_csv_s3', return_value=None) @patch('index.s3') @patch('index.get_matching_s3_keys') @patch('index.xmltodict') def test_handler_creates_csv_rows_with_expected_values( mock_xmltodict, mock_get_matching_keys, mock_s3_object, mock_write_csv_s3, test_event, csv_expected_rows, ddex_fluve_multiple_tracks, s3_xml_mimetype, s3_eligible_keys): """Test the main handler.""" s3_get_response = { 'Body': StreamingBody(StringIO(None), 0) } mock_s3_object.get_object.return_value = s3_get_response mock_s3_object.head_object.return_value = { 'ContentType': s3_xml_mimetype, } mock_xmltodict.parse.return_value = ddex_fluve_multiple_tracks mock_get_matching_keys.return_value = s3_eligible_keys index.handler(test_event, {}) with open('tmp/test_output.csv', newline='') as csvfile: reader = csv.reader(csvfile, delimiter=CSV_DELIMITER, quotechar=CSV_QUOTECHAR, quoting=csv.QUOTE_ALL) # noqa headers = next(reader) rows = next(reader) assert headers assert rows == csv_expected_rows assert mock_write_csv_s3.call_count == 1 def test_generate_rows_preorder_data(ddex_fluve_single): """Test the preorder logic of generate_rows().""" # This test is needed since we don't have DDEX sample data for preorders context = DDEXSchema().load(ddex_fluve_single) context.deals = [ Deal(release_references=['R0']), Deal(release_references=['R1']) ] context.deals[0].deal_terms = [DealTerm( pre_order=False, territories=['Worldwide'], start_date='2023-01-01' )] context.deals[1].deal_terms = [DealTerm( pre_order=True, territories=['Worldwide'], start_date='2023-02-02', clip_preview_date='2023-02-02' )] rows = index.generate_rows(context, MagicMock()) assert rows[0].itunes_preorder is True assert rows[0].itunes_preorder_date == '2023-02-02' assert rows[0].preorder_preview is True def test_generate_rows_preorder_data_no_preorder(ddex_fluve_single): """Test the preorder logic of generate_rows().""" # This test is needed since we don't have DDEX sample data for preorders context = DDEXSchema().load(ddex_fluve_single) context.deals = [Deal(release_references=['R0'])] context.deals[0].deal_terms = [DealTerm( pre_order=False, territories=['Worldwide'], start_date='2023-01-01' )] rows = index.generate_rows(context, MagicMock()) assert rows[0].itunes_preorder == 'No Pre-order' assert rows[0].itunes_preorder_date is None assert rows[0].preorder_preview is False