"""Tests for Track Publishing Obligation Logic.""" from unittest.mock import MagicMock from oto import status as response_code import pytest from backend.constants import track_field as tf from backend.constants import us_publishing_obligation as pub_obl from backend.logic import track_publishing as track_pub_logic from backend.models.track_persister import TrackPersister from tests.testutils import mocks from tests.testutils.functions import wrap_api_results def test_get_publishing_obligation_data_for_product( mocker, logic_headers, tds_get_pub_obl): """Verify retrieving publishing obligation for product.""" tds = tds_get_pub_obl tracks = tds['seed_data'] mocks.head_response(mocker) mocks.track_persister.get_all_by_product_id(mocker, tracks) response = track_pub_logic.get_all_for_product( product_id=1, **logic_headers) assert response.status == response_code.OK tds['validate_response_message'](response.message) def test_update_publishing_obligation( mocker, logic_headers, tds_update_pub_obl_for_mech_admin): """Verify publishing obligation logic.""" tds = tds_update_pub_obl_for_mech_admin request_data = tds['request_data'] # Create expected persister response tracks = [] seed_map = {track.tuid: track for track in tds['seed_data']} for delta in request_data: track = seed_map[delta[tf.TUID]] for key, value in delta.items(): if key == tf.PUBLISHER_NAMES: for name in value: track.add_role('publisher', name) else: setattr(track, key, value) tracks.append(track.to_dict()) mocks.ows_contracts_is_mech_admin(mocker, is_mech_admin=True) mocker.patch.object( TrackPersister, 'update_multiple_tracks', return_value=MagicMock( status=200, message=wrap_api_results(tracks))) response = track_pub_logic.update( product_id=tds['product_id'], request_data=request_data, **logic_headers) tds['validate_response_message'](response.message) def test_update_publishing_obligation_missing_fields(mocker, logic_headers): """Verify publishing obligation logic.""" product_id = 1 data = [ { tf.TUID: 1, tf.US_PUBLISHING_OBLIGATION: pub_obl.COMPOSITION } ] mocks.ows_contracts_is_mech_admin(mocker, is_mech_admin=True) response = track_pub_logic.update( product_id=product_id, request_data=data, **logic_headers) assert not response def test_validate_tracks_pub_obl_for_product( mocker, logic_headers, tds_validate_pub_obl_for_mech_admin): """Verify number of tracks is returned.""" tds = tds_validate_pub_obl_for_mech_admin mocks.ows_contracts_is_mech_admin(mocker, is_mech_admin=True) mocks.track_persister.get_all_by_product_id(mocker, tds['seed_data']) response = track_pub_logic.validate_for_product( product_id=1, **logic_headers) assert response tds['validate_response_message'](response.message) def test_validate_publishing_obligation(track_factory): """Test.""" track = track_factory( us_publishing_obligation=pub_obl.PUBLIC_DOMAIN, publishers=['pub 1', 'pub 2']) error_obj = track_pub_logic._validate_publishing_obligation( track.to_dict(), vendor_is_mech_admin=True) assert error_obj == {} track.us_publishing_obligation = pub_obl.CONTROLLED_BY_YOUR_LABEL error_obj = track_pub_logic._validate_publishing_obligation( track.to_dict(), vendor_is_mech_admin=True) assert error_obj == {} track.us_publishing_obligation = pub_obl.COMPOSITION track.third_party_publisher = 'N' error_obj = track_pub_logic._validate_publishing_obligation( track.to_dict(), vendor_is_mech_admin=True) assert error_obj == {} track.third_party_publisher = 'Y' error_obj = track_pub_logic._validate_publishing_obligation( track.to_dict(), vendor_is_mech_admin=True) assert error_obj == {} track.sync_role('publisher', []) error_obj = track_pub_logic._validate_publishing_obligation( track.to_dict(), vendor_is_mech_admin=False) assert error_obj == {} def test_validate_publishing_obligation_invalid(track_factory): """Test.""" def assert_error_code(error_obj, track_field): assert len(error_obj) == 1 assert track_field in error_obj assert error_obj[track_field]['validator'] == 'required' assert error_obj[track_field]['validator_value'] assert error_obj[track_field]['message'] track = track_factory( us_publishing_obligation=None, third_party_publisher=None) # US Publishing Obligation is required error error_obj = track_pub_logic._validate_publishing_obligation( track.to_dict(), vendor_is_mech_admin=True) assert_error_code(error_obj, tf.US_PUBLISHING_OBLIGATION) # Third Party Publisher answer required track.us_publishing_obligation = pub_obl.COMPOSITION error_obj = track_pub_logic._validate_publishing_obligation( track.to_dict(), vendor_is_mech_admin=True) assert_error_code(error_obj, tf.THIRD_PARTY_PUBLISHER) # Publishers need to be answered track.third_party_publisher = 'Y' error_obj = track_pub_logic._validate_publishing_obligation( track.to_dict(), vendor_is_mech_admin=True) assert_error_code(error_obj, tf.PUBLISHER_NAMES) def test_composition_obligation_with_publishers_is_valid_for_mech_admin(): """Verify answer is valid when 3rd party and has publishers.""" data = { tf.US_PUBLISHING_OBLIGATION: pub_obl.COMPOSITION, tf.THIRD_PARTY_PUBLISHER: 'Y', tf.PUBLISHER_NAMES: ['Pub 1'] } is_valid = track_pub_logic._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=True) assert is_valid, 'When us_publishing_obligations is composition and ' \ 'has third-party publishers' @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_composition_obligation_non_third_party_is_valid(vendor_is_mech_admin): """Verify answer is valid when not 3rd party.""" data = { tf.US_PUBLISHING_OBLIGATION: pub_obl.COMPOSITION, tf.THIRD_PARTY_PUBLISHER: 'N' } is_valid = track_pub_logic._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin) assert is_valid, 'When us_publishing_obligations is composition and ' \ 'third-party publishers is \'N\'' @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_composition_obligation_non_third_party_with_publsihers_is_valid( vendor_is_mech_admin): """Verify answer is valid when not 3rd party and has publishers.""" data = { tf.US_PUBLISHING_OBLIGATION: pub_obl.COMPOSITION, tf.THIRD_PARTY_PUBLISHER: 'N', tf.PUBLISHER_NAMES: ['Pub 1'] } is_valid = track_pub_logic._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin) assert is_valid, 'When us_publishing_obligations is composition and ' \ 'third-party publishers is \'N\' and publishers is specified' def test_composition_with_publishers_is_required_when_mech_admin(): """Verify publishers must be specified when 3rd party is 'Y'.""" data = { tf.US_PUBLISHING_OBLIGATION: pub_obl.COMPOSITION, tf.THIRD_PARTY_PUBLISHER: 'Y' } is_valid = track_pub_logic._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=True) assert not is_valid, 'When us_publishing_obligations is composition, ' \ 'has third-party publishers, and vendor is mech admin - ' \ 'the publisher_names field must be filled in' def test_composition_third_party_cannot_be_yes_when_not_mech_admin(): """Verify third party cannot be set to 'Y' when vendor not mech admin.""" data = { tf.US_PUBLISHING_OBLIGATION: pub_obl.COMPOSITION, tf.THIRD_PARTY_PUBLISHER: 'Y' } is_valid = track_pub_logic._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=False) assert not is_valid, 'When us_publishing_obligations is ' \ 'composition a vendor without mech admin access cannot answer ' \ 'yes to third party publishers question' @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_non_third_party_obligations_are_valid(vendor_is_mech_admin): """Verify non third-party obligation answer are valid by itself.""" for obligation_answer in pub_obl.NO_3RD_PARTY_ENUM: data = {tf.US_PUBLISHING_OBLIGATION: obligation_answer} is_valid = track_pub_logic._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin) assert is_valid, 'When us_publishing_obligation is not set to ' \ 'composition and no other fields are filled in' @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_null_obligation_when_answers_are_valid(vendor_is_mech_admin): """Verify publishing obligation answer doesn't have to be filled in.""" for third_party_publisher in (None, 'N'): data = { tf.US_PUBLISHING_OBLIGATION: None, tf.THIRD_PARTY_PUBLISHER: third_party_publisher, tf.PUBLISHER_NAMES: ['Some publisher'] } is_valid = track_pub_logic._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin) assert is_valid, 'When us_publishing_obligation is set to None' @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_null_obligation_when_answers_are_not_valid(vendor_is_mech_admin): """Verify publishing obligation answer can't have certain answers.""" data = { tf.US_PUBLISHING_OBLIGATION: None, tf.THIRD_PARTY_PUBLISHER: 'Y' } is_valid = track_pub_logic._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin) assert not is_valid, 'When us_publishing_obligation is set to None and ' \ 'third-party publishers is set to \'Y\'' @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_answer_is_not_blank(vendor_is_mech_admin): """Verify blank answer for publishing obligation is invalid.""" data = {tf.US_PUBLISHING_OBLIGATION: ''} is_valid = track_pub_logic._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin) assert not is_valid, 'Publishing obligation must be provided'