"""Functional tests for updating a track. Test endpoint: PUT /track/ """ import json from oto import status as response_code import pytest from backend.connectors import mysql from backend.constants import track_field as tf from backend.models.track_query import TrackQuery from tests.testutils import constants as test_consts from tests.testutils import db from tests.testutils import mocks import tests.testutils.functions as test_funcs @db.test_schema_no_seed def test_put_track( client_put_track, mocker, track_factory, track_localization_factory): """Test PUT track is successful.""" track = track_factory() localizations = track_localization_factory(track, [1]) db.merge_model_objects([track]) update_data = track.to_dict() update_data[tf.TRACK_NAME] = 'Updated track name' update_data[tf.OWNERSHIP_RIGHTS] = 'acquired_rights' update_data[tf.EXPLICIT] = 'Y' update_data[tf.IS_OWNER] = 'y' del update_data[tf.TRACK_NUMBER] del update_data[tf.VOLUME_NUMBER] del update_data[tf.PUBLISHERS] update_response = track.to_dict() update_response.update(update_data) update_response = test_funcs.make_track_logic_response(update_response) update_response[tf.LOCALIZATIONS] = localizations mocks.ows_product_get_track_localizations( mocker, localizations) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_data) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.OK assert res_body == update_response @db.test_schema_no_seed def test_put_track_with_artists_writers( client_put_track, mocker, track_factory): """Test PUT track updates artist data.""" track = track_factory() db.merge_model_objects([track]) update_data = { 'artists': [ {'type': 'performer', 'name': 'Performer 1'}], 'writers': [{'type': 'writer', 'name': 'Writer 1'}] } update_request = test_funcs.create_track_update_request( track.to_dict(), update_data) mocks.ows_product_get_track_localizations(mocker) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_request) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.OK test_funcs.validate_artists_are_same( res_body[tf.ARTISTS], update_data['artists']) assert tf.WRITERS in res_body writers = res_body[tf.WRITERS] assert len(writers) == 1 assert writers[0]['name'] == 'Writer 1' @db.test_schema_no_seed def test_put_track_with_version_none( client_put_track, mocker, track_factory): """Test PUT track updates version to none.""" track = track_factory() db.merge_model_objects([track]) update_data = { 'version': None } update_request = test_funcs.create_track_update_request( track.to_dict(), update_data) mocks.ows_product_get_track_localizations(mocker) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_request) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.OK version = res_body[tf.VERSION] assert version == update_data['version'] @db.test_schema_no_seed def test_put_track_with_meta_language_code_none( client_put_track, mocker, track_factory): """Test PUT track updates meta_language_code to none.""" track = track_factory() db.merge_model_objects([track]) update_data = { 'meta_language_code': None } update_request = test_funcs.create_track_update_request( track.to_dict(), update_data) mocks.ows_product_get_track_localizations(mocker) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_request) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.OK meta_language_code = res_body[tf.META_LANGUAGE_CODE] assert meta_language_code == update_data['meta_language_code'] @db.test_schema_no_seed def test_put_track_with_p_info_none( client_put_track, mocker, track_factory): """Test PUT track updates p_info to none.""" track = track_factory() db.merge_model_objects([track]) update_data = { 'p_info': None } update_request = test_funcs.create_track_update_request( track.to_dict(), update_data) mocks.ows_product_get_track_localizations(mocker) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_request) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.OK p_info = res_body[tf.P_INFO] assert p_info == update_data['p_info'] @db.test_schema_no_seed def test_put_track_with_artist_and_artist_info_id( client_put_track, mocker, track_factory): """Test PUT track updates artist info ID data.""" track = track_factory() db.merge_model_objects([track]) update_data = { 'artists': [ {'type': 'performer', 'artist_info_id': 1, 'name': 'Performer 1', 'track_artist_id': 1}] } update_request = test_funcs.create_track_update_request( track.to_dict(), update_data) mocks.ows_product_get_track_localizations(mocker) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_request) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.OK test_funcs.validate_artists_are_same( res_body[tf.ARTISTS], update_data['artists']) @db.test_schema_no_seed def test_put_track_with_artist_and_artist_info_id_no_track_artist_id( client_put_track, mocker, track_factory): """Test PUT track updates artist info ID data.""" track = track_factory() db.merge_model_objects([track]) update_data = { 'artists': [ {'type': 'performer', 'artist_info_id': 1, 'name': 'Performer 1'}] } update_request = test_funcs.create_track_update_request( track.to_dict(), update_data) mocks.ows_product_get_track_localizations(mocker) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_request) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.BAD_REQUEST assert res_body['code'] == 'validation_error' @db.test_schema_no_seed def test_put_track_with_writer_and_artist_info_id( client_put_track, mocker, track_factory): """Test PUT track updates artist info ID for writers.""" track = track_factory() db.merge_model_objects([track]) update_data = { 'writers': [ { 'type': 'writer', 'artist_info_id': 1, 'name': 'Shake Spear', 'track_writer_id': 1 } ] } update_request = test_funcs.create_track_update_request( track.to_dict(), update_data) mocks.ows_product_get_track_localizations(mocker) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_request) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.OK test_funcs.validate_writers_are_same( res_body[tf.WRITERS], update_data['writers']) @db.test_schema_no_seed def test_put_track_writer_and_artist_info_id_and_no_track_artist_id( client_put_track, mocker, track_factory): """Test PUT track does not updates artist info ID.""" track = track_factory() db.merge_model_objects([track]) update_data = { 'writers': [ { 'type': 'writer', 'artist_info_id': 1, 'name': 'Shake Spear' } ] } update_request = test_funcs.create_track_update_request( track.to_dict(), update_data) mocks.ows_product_get_track_localizations(mocker) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_request) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.BAD_REQUEST assert res_body['code'] == 'validation_error' @db.test_schema @pytest.mark.parametrize('track_name', test_consts.TEST_INVALID_TRACK_NAMES) def test_put_track_invalid_name( client_put_track, track_update_tuid, track_update_data, track_name): """Test PUT track fails with invalid track name.""" track_update_data['track_name'] = track_name res = client_put_track(track_update_tuid, track_update_data) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.BAD_REQUEST assert 'track_name' in res_body['message'] @pytest.mark.parametrize('p_info', test_consts.TEST_INVALID_P_INFOS_LIST) def test_put_track_invalid_p_info( client_put_track, track_update_tuid, track_update_data, p_info): """Test PUT track fails with invalid p_info.""" track_update_data['p_info'] = p_info res = client_put_track(track_update_tuid, track_update_data) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.BAD_REQUEST assert 'p_info' in res_body['message'] @db.test_schema def test_put_track_with_isrc( client, valid_headers, track_update_tuid, track_update_data, track_update_expected_response_with_isrc, mocker, track_localization_put_data): """Test PUT track is successful.""" expected_isrc = 'ABC12345678' mocks.ows_product_get_track_localizations( mocker, track_localization_put_data) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) mocker.patch.object( TrackQuery, 'claim_new_isrcs', return_value=[expected_isrc]) res = client.put( 'track/{}?generate_isrc=1'.format(track_update_tuid), headers=valid_headers, data=json.dumps(track_update_data)) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.OK assert res_body == test_funcs.make_track_logic_response( track_update_expected_response_with_isrc) def test_put_track_invalid_id_type(client): """Test PUT invalid track with id of type string.""" res = client.put('track/abc') assert res.status_code == response_code.NOT_FOUND def test_put_track_with_invalid_writer_role_type( client_put_track, track_factory): """Test PUT track fails if invalid writer type is specified.""" track = track_factory() update_data = { 'writers': [{'type': 'not_a_writer', 'name': 'Writer 1'}] } update_request = test_funcs.create_track_update_request( track.to_dict(), update_data) res = client_put_track(track.tuid, update_request) assert res.status_code == response_code.BAD_REQUEST @db.test_schema_no_seed def test_put_track_with_empty_explicit( client_put_track, mocker, track_factory, track_localization_factory): """Test PUT track is successful with explicit value as empty string.""" track = track_factory() localizations = track_localization_factory(track, [1]) db.merge_model_objects([track]) update_data = track.to_dict() update_data[tf.EXPLICIT] = '' update_response = track.to_dict() update_response.update(update_data) update_response = test_funcs.make_track_logic_response(update_response) update_response[tf.LOCALIZATIONS] = localizations mocks.ows_product_get_track_localizations( mocker, localizations) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_data) res_body = json.loads(res.data.decode()) assert res.status_code == response_code.OK assert res_body == update_response @db.test_schema_no_seed @pytest.mark.parametrize( ( 'data', 'expected_status_code', ), test_consts.TEST_FOCUS_TRACK_VALID ) def test_put_track_with_focus_track_valid( data, expected_status_code, client_put_track, mocker, track_factory, track_localization_factory ): """Test PUT track with focus_track data.""" track = track_factory() localizations = track_localization_factory(track, [1]) db.merge_model_objects([track]) update_data = track.to_dict() update_data.update(data) update_response = track.to_dict() update_response.update(update_data) update_response = test_funcs.make_track_logic_response(update_response) update_response[tf.LOCALIZATIONS] = localizations if data['focus_track'] == 'N': update_response['focus_track_start_date'] = None update_response['focus_track_end_date'] = None mocks.ows_product_get_track_localizations( mocker, localizations) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_data) res_body = json.loads(res.data.decode()) assert res.status_code == expected_status_code assert res_body == update_response @db.test_schema_no_seed @pytest.mark.parametrize( ( 'data', 'expected_status_code', 'expected_error' ), test_consts.TEST_FOCUS_TRACK_INVALID ) def test_put_track_with_focus_track_invalid( data, expected_status_code, expected_error, client_put_track, mocker, track_factory, track_localization_factory ): """Test PUT track is invalid with focus_track data missing.""" track = track_factory() localizations = track_localization_factory(track, [1]) db.merge_model_objects([track]) update_data = track.to_dict() del update_data['focus_track'] del update_data['focus_track_start_date'] del update_data['focus_track_end_date'] update_data.update(data) update_response = track.to_dict() update_response.update(update_data) update_response = test_funcs.make_track_logic_response(update_response) update_response[tf.LOCALIZATIONS] = localizations mocks.ows_product_get_track_localizations( mocker, localizations) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_data) res_body = json.loads(res.data.decode()) assert res.status_code == expected_status_code assert expected_error in res_body['message']['_schema'] @db.test_schema_no_seed def test_put_track_with_users_and_focus_track_( client_put_track, mocker, track_factory, track_localization_factory ): """Test PUT track is invalid with focus_track data missing.""" track = track_factory() localizations = track_localization_factory(track, [1]) db.merge_model_objects([track]) update_data = track.to_dict() update_data['focus_track'] = 'Y' update_data['focus_track_start_date'] = '2022-10-13' update_response = track.to_dict() update_response.update(update_data) update_response = test_funcs.make_track_logic_response(update_response) update_response[tf.LOCALIZATIONS] = localizations mocks.ows_product_get_track_localizations( mocker, localizations) mocks.ows_product_get_localization_languages(mocker) mocks.ows_product_digital_get_chinese_product_by_id(mocker) res = client_put_track(track.tuid, update_data, ) res_body = json.loads(res.data.decode()) assert res.status_code == 200 assert res_body == update_response with mysql.db_session() as session: query_track = TrackQuery.get_by_tuid(track.tuid, session) assert query_track assert query_track._focus_track assert query_track._focus_track.updated_by_user_type == 'alw' assert query_track._focus_track.updated_by_user_id == 123