"""Functional tests for fetching scheduling and pricing data.""" import json from unittest.mock import MagicMock from flexmock import flexmock from owsrequest import request import pytest from product_digital.constants import error from product_digital.constants import header from product_digital.constants import services from product_digital.constants import pricing_family from tests.factories import release as release_factory from tests.testutils import db @pytest.fixture def mock_product_tier_response(product_pricing_tier_payload): """Return a mock response for product tier pricing.""" response = MagicMock(status_code=200) response.json = MagicMock( return_value=product_pricing_tier_payload) return response @pytest.fixture def mock_track_tier_response(track_pricing_tier_payload): """Return a mock response for track tier pricing.""" response = MagicMock(status_code=200) response.json = MagicMock( return_value=track_pricing_tier_payload) return response @pytest.fixture def mock_product_overrides_response(product_pricing_overrides_payload): """Return a mock response for product pricing overrides.""" response = MagicMock(status_code=200) response.json = MagicMock( return_value=product_pricing_overrides_payload) return response @pytest.fixture def mock_track_overrides_response(track_pricing_overrides_payload): """Return a mock response for track pricing overrides.""" response = MagicMock(status_code=200) response.json = MagicMock( return_value=track_pricing_overrides_payload) return response @pytest.fixture def mock_get_tiers_for_products_response(get_tiers_for_albums_message): """Return a mock response for getting track pricing tiers.""" response = MagicMock(status_code=200) response.json = MagicMock( return_value=get_tiers_for_albums_message) return response @pytest.fixture def mock_get_tiers_for_tracks_response(get_tiers_for_tracks_message): """Return a mock response for getting track pricing tiers.""" response = MagicMock(status_code=200) response.json = MagicMock( return_value=get_tiers_for_tracks_message) return response @pytest.fixture def mock_get_track_response(): """Return a mock response for geting track info.""" response = MagicMock(status_code=200) response.json = MagicMock( return_value={'track_name': 'Best Track'}) return response @pytest.fixture def expected_ows_pricing_payload( expected_track_pricing_overrides, track_pricing_tier_by_product, active_overrides_payload_converted_dates, product_pricing_tier_by_product): """Return expected payload from calls to ows-pricing.""" tier_id = 'orchard_pricing_tier_id' return { 'album_pricing_tier': { 'id': product_pricing_tier_by_product.get(tier_id), 'name': product_pricing_tier_by_product.get('name')}, 'track_pricing_tier': { 'id': track_pricing_tier_by_product.get(tier_id), 'name': track_pricing_tier_by_product.get('name')}, 'album_override_items': active_overrides_payload_converted_dates, 'track_override_items': expected_track_pricing_overrides} @pytest.fixture def expected_ows_pricing_bff_payload(): """Return expected payload from calls to ows-pricing.""" return { 'album_pricing_tier': { 'name': 'Mid/Front', 'id': 15 }, 'track_pricing_tier': { 'name': 'Mid', 'id': 26 }, 'track_override_items': [ { 'created_date': '2018-11-01', 'territories': [], 'price_code': None, 'stores': [], 'end_date': None, 'territory_list_include': False, 'updated_date': None, 'custom_price': None, 'track_id': 29136821, 'sort_order': 1, 'track_pricing_override_id': 981295, 'activated': True, 'orchard_pricing_tier_id': 26, 'applies_worldwide': True, 'start_date': None, 'custom_currency_code': None, 'track_name': 'Track 1', 'orchard_pricing_tier_name': 'Mid' } ], 'album_override_items': [ { 'territories': [], 'product_id': 2493970, 'applies_worldwide': True, 'stores': [], 'updated_date': None, 'pricing_family_id': 2, 'custom_price': None, 'territory_list_include': False, 'store_id': None, 'price_code': None, 'sort_order': 1, 'created_date': '2018-11-01', 'end_date': '2018-12-06', 'resolution': None, 'product_pricing_override_id': 5336585, 'activated': True, 'orchard_pricing_tier_id': 18, 'start_date': '2018-12-02', 'custom_currency_code': None, 'orchard_pricing_tier_name': 'Budget 2' } ] } @db.test_schema def test_get_schedling_and_pricing_when_successful( client, product_id, valid_headers, mock_product_tier_response, mock_track_tier_response, mock_product_overrides_response, mock_track_overrides_response, expected_ows_pricing_payload, mock_get_tiers_for_products_response, track_ids_for_testing, mock_get_track_response, mock_get_tiers_for_tracks_response): """Test that pricing and scheduling data is returned.""" existing_release = release_factory.ReleaseFactory.build( release_id=product_id) db.seed_models(existing_release) flexmock(request).should_receive('get').with_args( services.OWS_PRICING, '/product/{}/pricing-family/{}/orchard_pricing_tier'.format( product_id, pricing_family.ALBUM), ).and_return(mock_product_tier_response) flexmock(request).should_receive('get').with_args( services.OWS_PRICING, '/pricing-family/{}/orchard-pricing-tier'.format(2), ).and_return(mock_get_tiers_for_products_response) flexmock(request).should_receive('get').with_args( services.OWS_PRICING, '/pricing-family/{}/orchard-pricing-tier'.format(3), ).and_return(mock_get_tiers_for_tracks_response) flexmock(request).should_receive('get').with_args( services.OWS_PRICING, '/product/{}/pricing-family/{}/orchard_pricing_tier'.format( product_id, pricing_family.TRACK), ).and_return(mock_track_tier_response) flexmock(request).should_receive('get').with_args( services.OWS_PRICING, '/product/{}/override'.format(product_id), ).and_return(mock_product_overrides_response) flexmock(request).should_receive('get').with_args( services.OWS_PRICING, '/product/{}/track-overrides'.format(product_id), ).and_return(mock_track_overrides_response) flexmock(request).should_receive('get').with_args( services.OWS_TRACK, '/track/{}'.format(track_ids_for_testing[0]), ).and_return(mock_get_track_response) flexmock(request).should_receive('get').with_args( services.OWS_TRACK, '/track/{}'.format(track_ids_for_testing[1]), ).and_return(mock_get_track_response) existing_release_data = existing_release.to_dict() expected_payload = { 'sale_start_date': existing_release_data['sale_start_date'], 'release_date': existing_release_data['release_date'], 'preorder_date': existing_release_data['preorder_date'], 'previewable': existing_release_data['itunes_previewable']} expected_payload.update(expected_ows_pricing_payload) get_response = client.get( '/product/{}/scheduling-and-pricing'.format(product_id), headers=valid_headers) response_body = json.loads(get_response.data.decode()) assert get_response.status_code == 200 assert response_body == expected_payload @db.test_schema def test_get_schedling_and_pricing_when_error_from_release_model( client, product_id, valid_headers): """Test that pricing and scheduling error returned when release error.""" get_response = client.get( '/product/{}/scheduling-and-pricing'.format(product_id), headers=valid_headers) # response_body = json.loads(get_response.data.decode()) assert get_response.status_code == 404 @db.test_schema def test_get_schedling_and_pricing_error_when_error_from_pricing_service( client, product_id, valid_headers): """Test that error returned when error from ows-pricing.""" mock_error_response = MagicMock(status_code=400) mock_error_response.json = MagicMock(return_value={}) existing_release = release_factory.ReleaseFactory.build( release_id=product_id) db.seed_models(existing_release) (flexmock(request).should_receive('get').and_return(mock_error_response)) get_response = client.get( '/product/{}/scheduling-and-pricing'.format(product_id), headers=valid_headers) assert get_response.status_code == 400 def test_get_schedling_and_pricing_error_when_grass_header_missing( client, product_id, valid_headers_for_vendor, mocker): """Test that error returned when grass header missing.""" del valid_headers_for_vendor[header.GRASS_ACCOUNT_TYPE] get_response = client.get( '/product/{}/scheduling-and-pricing'.format(product_id), headers=valid_headers_for_vendor) response_body = json.loads(get_response.data.decode()) assert get_response.status_code == 400 assert response_body.get('message') == \ error.ERROR_MESSAGE_INCOMPLETE_GRASS_HEADERS def test_get_schedling_and_pricing_error_when_not_owner( client, product_id, valid_headers_for_vendor, mocker): """Test that error returned when requestor is not the product owner.""" head_response = MagicMock(status_code=403) mocker.patch.object(request, 'head', return_value=head_response) get_response = client.get( '/product/{}/scheduling-and-pricing'.format(product_id), headers=valid_headers_for_vendor) assert get_response.status_code == 403