"""Shared test mocks.""" import copy import json from kafka_utils.consumer.deserializer.avro import AvroDeserializer import pytest import responses @pytest.fixture def mock_row_data(): """Mock row data.""" return { 'product_id': 1, 'release_status': 1, 'review_queue_id': 1, 'status': 'new', 'added_at': '2021-08-03T01:13:14Z' } @pytest.fixture def mock_graphql_response_subaccount(mock_graphql_response): """Mock graphql response for a subaccount's product.""" mock_graphql_response['data']['product']['label'] = { 'name': 'Subaccount1', 'id': { 'subaccountId': 10, 'vendorId': 16160 }, 'vendor': { 'name': 'Label1', 'owner': 'odd', 'country': 'USA', 'countryCode': 'US', 'id': { 'vendorId': 16160 }, 'serviceTier': { 'uuid': '93185c0c-fe01-4bff-bb0d-a7609b8711e5', 'displayName': 'applesauce-bananas' }, 'companyBrand': { 'uuid': '0fd602fc-76b0-42fd-8607-2a0ddeca46e7', 'name': 'brandie', 'displayName': 'Brandie' }, 'assignedTo': { 'id': 1, 'firstName': 'foo', 'lastName': 'bar' }, 'secondaryInternalContact': { 'id': 2, 'firstName': 'baz', 'lastName': 'qux' }, 'assignedReviewer': { 'id': 1, 'firstName': 'foo', 'lastName': 'bar' } } } return mock_graphql_response @pytest.fixture def mock_graphql_response_product_validation(mock_graphql_response): """Mock graphql response for a subaccount's product.""" mock_graphql_response['data']['product']['validation']['warnings'] = [ { 'reason': 'Field `audio_file` is required', 'code': 'MISSING_AUDIO_FILE', } ] return mock_graphql_response @pytest.fixture def mock_graphql_response_track_validation(mock_graphql_response): """Mock graphql response for a subaccount's product.""" mock_graphql_response['data']['product']['tracks'][0]['validation']['errors'] = [ { 'reason': 'Field `audio_file` is required', 'code': 'MISSING_AUDIO_FILE', } ] return mock_graphql_response @pytest.fixture def mock_graphql_base_product_response(): """Mock graphql response for base product data.""" return { 'data': { 'product': { 'displayStatus': 'submitted', 'productConfiguration': 'Digital Audio', 'productId': 1, 'upc': '23456789234562', 'productName': 'This is the name.', 'distributionFormatId': 1, 'format': 'Full Length', 'bulkSession': None, 'label': { 'name': 'Foo', 'owner': 'odd', 'country': 'USA', 'countryCode': 'US', 'id': { 'vendorId': 1, 'subaccountId': 0 }, 'serviceTier': { 'uuid': '93185c0c-fe01-4bff-bb0d-a7609b8711e5', 'displayName': 'applesauce-bananas' }, 'companyBrand': { 'uuid': '0fd602fc-76b0-42fd-8607-2a0ddeca46e7', 'name': 'brandie' }, 'assignedTo': { 'id': 123, 'firstName': None, 'lastName': None }, 'secondaryInternalContact': { 'id': None, 'firstName': None, 'lastName': None }, 'assignedReviewer': { 'id': 101, 'firstName': None, 'lastName': None } }, 'releaseCorrection': None } }, 'errors': ['err1', 'err2'] } @pytest.fixture def mock_graphql_base_d3_subaccount_product_response(): """Mock graphql response for d3 subaccount base product data.""" return { 'data': { 'product': { 'displayStatus': 'action_required', 'productConfiguration': 'Digital Audio', 'productId': 2, 'upc': '12345678912343', 'productName': 'This is the name.', 'distributionFormatId': 1, 'format': 'Full Length', 'label': { 'id': { 'vendorId': 2, 'subaccountId': 3 }, 'vendor': { 'name': 'Foo', 'owner': 'odd', 'id': { 'vendorId': 2 }, 'serviceTier': { 'uuid': '93185c0c-fe01-4bff-bb0d-a7609b8711e5', 'displayName': 'applesauce-bananas' }, 'companyBrand': { 'uuid': '0fd602fc-76b0-42fd-8607-2a0ddeca46e7', 'name': 'brandie' }, 'assignedTo': { 'id': 1, 'firstName': 'foo', 'lastName': 'bar' }, 'secondaryInternalContact': { 'id': 2, 'firstName': 'baz', 'lastName': 'qux' }, 'assignedReviewer': { 'id': 1, 'firstName': 'foo', 'lastName': 'bar' } } }, 'releaseCorrection': { 'status': 'foo' } } }, 'errors': ['err1', 'err2'] } graphql_product_response = { 'data': { 'product': { 'artists': [ { 'artistId': '7222718', 'artistName': 'Sinaloha', 'artistType': 'primary_artist' }, { 'artistId': '7222720', 'artistName': 'PRONOUN', 'artistType': 'featuring' }, { 'artistId': '7222721', 'artistName': 'PeterPeter', 'artistType': 'remixer' }, { 'artistId': '7222722', 'artistName': 'CCubed', 'artistType': 'producer' } ], 'cLine': '2021 petertest', 'status': 'transfer_to_content', 'displayStatus': 'error_correction', 'distributionFormatId': 1, 'deliveredVersion': 'For Ui', 'format': 'Full Length', 'bulkSession': { 'id': 'test-bulk-session-id', 'ingestion': { 'submittedProductsCount': 2 }, }, 'label': { 'name': 'Non-Mechanical M/USD', 'owner': 'odd', 'country': 'USA', 'countryCode': 'US', 'assignedTo': { 'id': 1, 'firstName': 'foo', 'lastName': 'bar' }, 'secondaryInternalContact': { 'id': 2, 'firstName': 'baz', 'lastName': 'qux' }, 'assignedReviewer': { 'id': 1, 'firstName': 'foo', 'lastName': 'bar' }, 'id': { 'subaccountId': 0, 'vendorId': 16160 }, 'serviceTier': { 'displayName': 'applesauce-bananas', 'uuid': '93185c0c-fe01-4bff-bb0d-a7609b8711e5', }, 'companyBrand': { 'name': 'foo', 'uuid': 'abc', 'displayName': 'Foo', }, }, 'imageLocation': 'http://image.png', 'imprint': 'petertest', 'metadataLanguage': { 'name': 'English', 'code': 'ENG' }, 'productCode': 'CONTEST02', 'productConfiguration': 'Digital Audio', 'productId': 1, 'productName': 'Contest02', 'preorderDate': None, 'releaseDate': '2022-07-01', 'saleStartDate': '2022-07-01', 'specialInstructions': 'SI', 'subgenre': { 'id': 662, 'name': 'Pop', 'genre': { 'id': 20, 'name': 'Blues' } }, 'upc': '196292189827', 'validation': { 'isValid': True, 'errors': [], 'warnings': [] }, 'version': 'Content Review UI Testing', 'previewable': True, 'labelParticipations': [], 'productLocalizations': [], 'reviewHistory': None, 'albumPricingTier': { 'pricingFamily': 'MUSIC_ALBUM', 'orchardPricingTier': { 'id': '1', 'name': 'Front Line', '__typename': 'OrchardPricingTier' }, 'productOverrides': [] }, 'trackPricingTier': { 'pricingFamily': 'MUSIC_TRACK', 'orchardPricingTier': { 'id': '1', 'name': 'Front Line' }, 'trackOverrides': [] }, 'releaseSchedule': None, 'releaseCorrection': None, 'tracks': [ { 'validation': { 'isValid': True, 'errors': [], 'warnings': [] } } ] } } } @pytest.fixture def mock_graphql_review_queue_item_response(): """Mock graphql response for a review queue item.""" return { 'data': { 'reviewQueueItem': { 'queueName': 'initial', 'createdDatetime': '2023-08-01T15:23:20.113741Z', 'lockedByUserId': None, 'lockedUntilDatetime': None, 'movedToQueueByIdentity': { 'id': 'cce11590-be86-4fb6-a384-afffff643af1', 'firstName': 'Very', 'lastName': 'Cool' }, 'movedToTargetId': None, 'movedToTargetName': None, 'movedToTargetEmail': None, 'movedToTarget': None, 'submissionCount': 1, 'submissionType': 'new', 'submissionDatetime': '1975-04-09 09:17:24' } } } @pytest.fixture def mock_graphql_locked_review_queue_item_response(): """Mock graphql response for a locked review queue item.""" return { 'data': { 'reviewQueueItem': { 'queueName': 'initial', 'createdDatetime': '2023-08-01T15:23:20.113741Z', 'lockedByUserId': 'ab2dd624-367f-4a96-99a3-10b19f01598f', 'lockedUntilDatetime': '2023-10-12T15:35:07.659792Z', 'movedToTargetEmail': None, 'movedToTargetId': None, 'movedToTargetName': None, 'movedToQueueByIdentity': { 'id': 'cce11590-be86-4fb6-a384-afffff643af1', 'firstName': 'Very', 'lastName': 'Cool' }, 'movedToTargetId': None, 'movedToTargetName': None, 'movedToTargetEmail': None, 'movedToTarget': None, 'submissionCount': 1, 'submissionType': 'new', 'submissionDatetime': '1975-04-09 09:17:24' } } } @pytest.fixture def mock_review_queue_item(mock_graphql_review_queue_item_response): """Mock review queue item.""" return mock_graphql_review_queue_item_response['data']['reviewQueueItem'] @pytest.fixture def mock_graphql_response(): """Mock graphql response for a label's product.""" return copy.deepcopy(graphql_product_response) @pytest.fixture def mock_graphql_response_with_corrections(): """Mock graphql response for a label's product.""" graphql_product_response_copy = copy.deepcopy(graphql_product_response) corrections = [ { 'tableName': 'releases', 'fieldName': 'release_name', 'keyValue': json.dumps('NEW Product') }, { 'tableName': 'tracks', 'fieldName': 'release_name', 'keyValue': json.dumps('Alt Title') }, { 'tableName': 'releases', 'fieldName': 'meta_language', 'keyValue': json.dumps('GER') }, { 'tableName': 'releases', 'fieldName': 'featuring', 'keyValue': json.dumps([{ 'role': 'featuring', 'artistName': 'Anon' }]) }, { 'tableName': 'releases', 'fieldName': 'coverart', 'keyValue': json.dumps('https://qa-images.theorchard.io/v2/product/xlarge_cover/f5ca69bcc783419baec89c64f374a7e6_c5a78c8f_57af_4424_9af8_d7349a5aef85.jpeg') # noqa }, { 'tableName': 'releases', 'fieldName': 'genre_id', 'keyValue': '16' }, ] graphql_product_response_copy['data']['product']['releaseCorrection'] = { 'status': 'submitted', 'items': corrections } graphql_product_response_copy['data']['product']['status'] = 'in_content' return graphql_product_response_copy @pytest.fixture def mock_genre_response(): """Mock graphql response for genre.""" return { 'data': { 'genres': [ {'id': 12, 'name': 'Classical'} ] } } @pytest.fixture def mock_language_response(): """Mock graphql response for meta language.""" return { 'data': { 'metaLanguages': [ {'code': 'GER', 'name': 'German'}, {'code': 'ENG', 'name': 'English'} ] } } @pytest.fixture def mock_graphql_d3_subaccount_response(): """Mock graphql response for a d3 subaccount's product.""" graphql_product_response_copy = copy.deepcopy(graphql_product_response) graphql_product_response_copy['data']['product']['label'] = { 'name': 'asdf asdf', 'id': { 'subaccountId': 123123, 'vendorId': 123 }, 'vendor': { 'id': { 'vendorId': 123, }, 'name': 'qwery qwerty', 'owner': 'odd', 'country': 'USA', 'countryCode': 'US', 'serviceTier': { 'displayName': 'applesauce-bananas', 'uuid': '93185c0c-fe01-4bff-bb0d-a7609b8711e5', }, 'companyBrand': { 'name': 'foo', 'uuid': 'abc', 'displayName': 'Foo' }, 'assignedTo': { 'id': 1, 'firstName': 'foo', 'lastName': 'bar' }, 'secondaryInternalContact': { 'id': 2, 'firstName': 'AWAL', 'lastName': 'Content' }, 'assignedReviewer': { 'id': 1, 'firstName': 'foo', 'lastName': 'bar' } } } return graphql_product_response_copy @pytest.fixture def mock_formatted_corrections(): """Mock formatted corrections.""" return { 'product_name': 'NEW Product', 'metadata_language_code': 'GER', 'featuring_artist': 'Anon', 'image_location': 'https://qa-images.theorchard.io/v2/product/xlarge_cover/f5ca69bcc783419baec89c64f374a7e6_c5a78c8f_57af_4424_9af8_d7349a5aef85.jpeg', # noqa 'genre_id': 16 } @pytest.fixture def mock_index_document(mock_row_data, mock_graphql_response): """Mock an indexed product document.""" product_metadata = mock_graphql_response.get('data').get('product') label_id = product_metadata.get('label').get('id').get('vendorId') subaccount_id = product_metadata.get('label').get('id').get('subaccountId') return { 'added_at': mock_row_data.get('added_at'), 'account_id': f'{label_id}:{subaccount_id}', 'account_name': product_metadata.get('label').get('name'), 'account_country': product_metadata.get('label').get('country'), 'account_country_code': product_metadata.get('label').get('countryCode'), 'assigned_reviewer_id': product_metadata.get('label').get('assignedReviewer').get('id'), 'assigned_reviewer_name': 'foo bar', 'assigned_to_id': product_metadata.get('label').get('assignedTo').get('id'), 'assigned_to_name': 'foo bar', 'bulk_session_id': product_metadata.get('bulkSession').get('id'), 'company_brand': product_metadata['label']['companyBrand'], 'company_brand_name': product_metadata['label']['companyBrand']['name'], 'company_brand_display_name': product_metadata['label']['companyBrand']['displayName'], 'company_brand_uuid': product_metadata['label']['companyBrand']['uuid'], 'configuration': product_metadata.get('productConfiguration'), 'display_status': product_metadata.get('displayStatus'), 'distribution_format_id': product_metadata.get('distributionFormatId'), 'escalation_type': None, 'featuring_artist': 'PRONOUN', 'format': product_metadata.get('format'), 'genre_id': product_metadata.get('subgenre').get('genre').get('id'), 'genre_name': product_metadata.get('subgenre').get('genre').get('name'), 'image_location': product_metadata.get('imageLocation'), 'imprint': product_metadata.get('imprint'), 'label_id': label_id, 'label_owner': product_metadata.get('label').get('owner'), 'label_name': product_metadata.get('label').get('name'), 'locked_by_user_id': None, 'locked_until_datetime': None, 'notices': [], 'preorder_date': product_metadata.get('preorderDate'), 'primary_artist': 'Sinaloha', 'product_id': mock_row_data.get('product_id'), 'product_name': product_metadata.get('productName'), 'release_correction_status': mock_row_data.get('releaseCorrection', {}).get('status', ''), 'review_queue_id': mock_row_data.get('review_queue_id'), 'queue_name': 'initial', 'metadata_language_code': 'ENG', 'metadata_language_name': 'English', 'moved_to_group_name': None, 'moved_to_queue_by_user_id': 'cce11590-be86-4fb6-a384-afffff643af1', 'moved_to_queue_by_user_name': 'Very Cool', 'moved_to_target_email': None, 'moved_to_target_id': None, 'moved_to_target_name': None, 'sale_start_date': product_metadata.get('saleStartDate'), 'secondary_internal_contact_id': 2, 'secondary_internal_contact_name': 'baz qux', 'service_tier_name': 'applesauce-bananas', 'service_tier_uuid': '93185c0c-fe01-4bff-bb0d-a7609b8711e5', 'special_instructions': product_metadata.get('specialInstructions'), 'version': product_metadata.get('version'), 'subaccount_id': subaccount_id, 'subaccount_name': '', 'submission_count': 1, 'submission_type': 'New', 'upc': product_metadata.get('upc'), 'submission_datetime': '1975-04-09 09:17:24', } @pytest.fixture def mock_d3_subaccount_index_document(mock_row_data, mock_graphql_d3_subaccount_response): """Mock an d3 subaccount indexed product document.""" product_metadata = mock_graphql_d3_subaccount_response.get('data').get('product') label_id = product_metadata.get('label').get('id').get('vendorId') subaccount_id = product_metadata.get('label').get('id').get('subaccountId') return { 'account_id': f'{label_id}:{subaccount_id}', 'account_name': product_metadata.get('label').get('name'), 'account_country': product_metadata['label']['vendor'].get('country'), 'account_country_code': product_metadata['label']['vendor'].get('countryCode'), 'added_at': mock_row_data.get('added_at'), 'assigned_reviewer_id': 1, 'assigned_reviewer_name': 'foo bar', 'assigned_to_id': 1, 'assigned_to_name': 'foo bar', 'bulk_session_id': product_metadata.get('bulkSession').get('id'), 'company_brand': product_metadata['label']['vendor']['companyBrand'], 'company_brand_display_name': product_metadata['label']['vendor']['companyBrand'].get( 'displayName'), 'company_brand_name': product_metadata['label']['vendor']['companyBrand']['name'], 'company_brand_uuid': product_metadata['label']['vendor']['companyBrand']['uuid'], 'configuration': product_metadata.get('productConfiguration'), 'display_status': product_metadata.get('displayStatus'), 'distribution_format_id': product_metadata.get('distributionFormatId'), 'escalation_type': None, 'featuring_artist': 'PRONOUN', 'format': product_metadata.get('format'), 'genre_id': product_metadata.get('subgenre').get('genre').get('id'), 'genre_name': product_metadata.get('subgenre').get('genre').get('name'), 'image_location': product_metadata.get('imageLocation'), 'imprint': product_metadata.get('imprint'), 'label_id': label_id, 'label_name': product_metadata['label']['vendor']['name'], 'label_owner': product_metadata['label']['vendor']['owner'], 'locked_by_user_id': None, 'locked_until_datetime': None, 'metadata_language_code': 'ENG', 'metadata_language_name': 'English', 'moved_to_group_name': None, 'moved_to_queue_by_user_id': 'cce11590-be86-4fb6-a384-afffff643af1', 'moved_to_queue_by_user_name': 'Very Cool', 'moved_to_target_email': None, 'moved_to_target_id': None, 'moved_to_target_name': None, 'notices': [], 'preorder_date': product_metadata.get('preorderDate'), 'primary_artist': 'Sinaloha', 'product_id': mock_row_data.get('product_id'), 'product_name': product_metadata.get('productName'), 'queue_name': 'initial', 'release_correction_status': ( product_metadata.get('releaseCorrection').get('status', '') if product_metadata.get('releaseCorrection') else '' ), 'review_queue_id': mock_row_data.get('review_queue_id'), 'sale_start_date': product_metadata.get('saleStartDate'), 'secondary_internal_contact_id': 2, 'secondary_internal_contact_name': 'AWAL Content', 'service_tier_name': 'applesauce-bananas', 'service_tier_uuid': '93185c0c-fe01-4bff-bb0d-a7609b8711e5', 'special_instructions': product_metadata.get('specialInstructions'), 'version': product_metadata.get('version'), 'submission_count': 1, 'submission_type': 'New', 'subaccount_id': subaccount_id, 'subaccount_name': 'asdf asdf', 'upc': product_metadata.get('upc'), 'submission_datetime': '1975-04-09 09:17:24', } @pytest.fixture def mock_schema_string(): """Mock schema string.""" return ( '{\"type\":\"record\",\"name\":\"review\",\"namespace\":\"owsContentReview\",' '\"fields\":[{\"name\":\"operation\",\"type\":{\"type\":\"record\",\"name\":\"' 'operationInformation\",\"fields\":[{\"name\":\"type\",\"type\":{\"type\":\"en' 'um\",\"name\":\"operationOptions\",\"symbols\":[\"create\",\"update\",\"patch' '\",\"delete\"]},\"doc\":\"Operation type.\"},{\"name\":\"context\",\"type\":[' '\"null\",{\"type\":\"enum\",\"name\":\"operationContextOptions\",\"doc\":\"Ad' 'ditional information about event.\",\"symbols\":[\"new\",\"approve\",\"reject' '\",\"escalate\",\"close\",\"lock\",\"unlock\"]}],\"default\":null},{\"name\":' '\"timestamp\",\"type\":{\"type\":\"long\",\"logicalType\":\"timestamp-millis\"' '},\"doc\":\"timestamp of the operation.\"}]},\"doc\":\"Operation information\"' '},{\"name\":\"payload\",\"type\":{\"type\":\"record\",\"name\":\"payloadInfor' 'mation\",\"fields\":[{\"name\":\"product_id\",\"type\":\"int\",\"doc\":\"Produ' 'ct unique identifier generated by art_relations database.\"},{\"name\":\"revie' 'w_queue_id\",\"type\":\"int\",\"doc\":\"Review unique identifier generated by ' 'content_review database.\"},{\"name\":\"review_note\",\"type\":[\"null\",\"str' 'ing\"],\"doc\":\"A note from the reviewer regarding the approval / rejection.' '\"},{\"name\":\"user_id\",\"type\":[\"null\",\"string\"],\"doc\":\"The user_id' ' of the reviewer who approved / rejected the product.\"},{\"name\":\"locked_by' '_user_id\",\"type\":[\"null\",{\"type\":\"string\",\"logicalType\":\"uuid\"}],' '\"doc\":\"Orchard Identity Id of user with exclusive access to review this rev' 'iew queue item.\"},{\"name\":\"locked_until_datetime\",\"type\":[\"null\",{\"t' 'ype\":\"long\",\"logicalType\":\"timestamp-micros\"}],\"doc\":\"UTC time when ' 'locked_by_user_id will lose exclusive access to review this review queue item.' '\"}]},\"doc\":\"Payload information.\"}]}' ) @pytest.fixture def mock_avro_serializer(mock_schema_string): """Mock avro serializer.""" with responses.RequestsMock() as rsps: rsps.add( responses.GET, 'https://example.com/schemas/ids/28', json={'schema': mock_schema_string}, status=200, ) avro_serializer = AvroDeserializer('https://example.com') yield avro_serializer