"""Test the ows-product model.""" import json from unittest.mock import Mock from unittest.mock import patch from oto import response from oto import status as response_code from oto.adaptors.flask import flaskify from owsrequest import request from owsrequest import test_utils import pytest from requests.models import Response from backend.constants import error from backend.constants import services from backend.models import ows_product def mock_get_for_ownership(*args): """Mock a successful response.""" return flaskify(response.Response(status=200)) @patch( target='backend.models.ows_product._get_head_from_ows_product_service', side_effect=mock_get_for_ownership) def test_get_verify_product_ownership(mock_get): """Test the product ownership call returns a success response.""" res = ows_product.verify_product_ownership('vendor', 1, 1) assert mock_get(None).status == res.status def test_get_head_from_ows_product_service(monkeypatch): """Test the ows-product microservice call returns a success response.""" # The call spec list used by mock_ows_requests to mock these requests call_specs = [{ 'service': 'ows-product', 'path': '/endpoint', 'status': 200, 'json': {}}] monkeypatch.setattr( request, 'head', test_utils.mock_ows_requests(call_specs), raising=False) res = ows_product._get_head_from_ows_product_service('/endpoint') assert res.status == 200 @pytest.fixture def update_track_localization_args(): """Fixture for update function arguments.""" return { 'tuid': 123, 'language_id': 2, 'track_name': 'Gangsta paradice', 'version': 'Explicit', 'artists': [ { 'track_artist_id': '1', 'name': 'Coolio', 'type': 'performer' } ] } @pytest.fixture def update_track_localization_ows_product_response(): """Fixture for ows-product response for updating localization.""" return { 'tuid': 123, 'language_id': 2, 'track_name': 'Gangsta paradice', 'version': 'Explicit', 'artists': {'1': 'Coolio'} } @pytest.fixture def update_track_localization_without_artists_args( update_track_localization_args): """Fixture for update function arguments. Without 'artists' dict. """ json_data = update_track_localization_args.copy() json_data['artists'] = [] return json_data @pytest.fixture def put_localization_request_data(): """Fixture for PUT track localization request data.""" json_data = { 'track_name': 'Gangsta paradice', 'version': 'Explicit', 'artists': {'1': 'Coolio'} } return json_data @pytest.fixture def put_localization_without_artists_request_data( put_localization_request_data): """Fixture for PUT track localization request data without artists.""" json_data = put_localization_request_data.copy() json_data.pop('artists') return json_data def _patch_request(monkeypatch, method, mock_json_response, status_code): """Patch owsrequest to return required data. Args: monkeypatch (object): pytest monkeypatch helper method (str): http method mock_json_response (json): response json object status_code (int): HTTP status code Returns: unittest.Mock """ mock_content = json.dumps(mock_json_response).encode('utf-8') response_mock = Response() response_mock._content = mock_content response_mock.status_code = status_code put_request_mock = Mock(return_value=response_mock) monkeypatch.setattr( request, method, put_request_mock) return put_request_mock @pytest.fixture def put_localization_endpoint(update_track_localization_args): """Fixture for ows-product localization endpoint.""" return '/localization/track/{tuid}/language/{language_id}'.format( tuid=update_track_localization_args['tuid'], language_id=update_track_localization_args['language_id']) def test_update_track_localization_with_artists( monkeypatch, update_track_localization_args, update_track_localization_ows_product_response, put_localization_request_data, put_localization_endpoint): """Test update with artists dict passed.""" put_request_mock = _patch_request( monkeypatch, 'put', update_track_localization_ows_product_response, 200) result = ows_product.update_track_localization( **update_track_localization_args) put_request_mock.assert_called_with( services.OWS_PRODUCT, put_localization_endpoint, json=put_localization_request_data) assert result assert result.message == update_track_localization_args def test_update_track_localization_without_artists( monkeypatch, update_track_localization_without_artists_args, update_track_localization_ows_product_response, put_localization_without_artists_request_data, put_localization_endpoint): """Test update without artists dict passed.""" update_track_localization_ows_product_response.pop('artists') put_request_mock = _patch_request( monkeypatch, 'put', update_track_localization_ows_product_response, 200) result = ows_product.update_track_localization( **update_track_localization_without_artists_args) put_request_mock.assert_called_with( services.OWS_PRODUCT, put_localization_endpoint, json=put_localization_without_artists_request_data) assert result assert result.message == update_track_localization_without_artists_args def test_update_track_localization_failed( monkeypatch, update_track_localization_args, put_localization_request_data, put_localization_endpoint): """Test update ows-product call failed.""" mock_json_response = { 'code': 'LOCALIZATION_ERROR', 'message': 'Failed to update localization' } put_request_mock = _patch_request( monkeypatch, 'put', mock_json_response, 403) result = ows_product.update_track_localization( **update_track_localization_args) put_request_mock.assert_called_with( services.OWS_PRODUCT, put_localization_endpoint, json=put_localization_request_data) assert not result assert result.errors['message'] == mock_json_response def test_update_track_localization_server_error( monkeypatch, update_track_localization_args, put_localization_request_data, put_localization_endpoint): """Test update ows-product call failed. Test for case when we do not receive JSON with error details. """ mock_response = 'Server error' put_request_mock = _patch_request( monkeypatch, 'put', mock_response, 500) result = ows_product.update_track_localization( **update_track_localization_args) put_request_mock.assert_called_with( services.OWS_PRODUCT, put_localization_endpoint, json=put_localization_request_data) assert not result assert result.errors['message'] == mock_response @pytest.fixture def delete_track_localization_args(): """Fixture for delete track localization args.""" return { 'tuid': 123, 'language_id': 2 } @pytest.fixture def delete_track_localization_ows_product_response(): """Fixture for ows-product response for deleting localization.""" return 'track localizations deleted' def test_delete_track_localization( monkeypatch, delete_track_localization_ows_product_response, delete_track_localization_args, put_localization_endpoint): """Test delete track localization.""" delete_request_mock = _patch_request( monkeypatch, 'delete', delete_track_localization_ows_product_response, 200) result = ows_product.delete_track_localization( **delete_track_localization_args) delete_request_mock.assert_called_with( services.OWS_PRODUCT, put_localization_endpoint) assert result assert result.message == delete_track_localization_args def test_delete_track_localization_failed( monkeypatch, delete_track_localization_ows_product_response, delete_track_localization_args, put_localization_endpoint): """Test delete track localization failed.""" mock_json_response = { 'code': 'LOCALIZATION_ERROR', 'message': 'Failed to delete localization' } delete_request_mock = _patch_request( monkeypatch, 'delete', mock_json_response, 500) result = ows_product.delete_track_localization( **delete_track_localization_args) delete_request_mock.assert_called_with( services.OWS_PRODUCT, put_localization_endpoint) assert not result assert result.errors['message'] == mock_json_response @pytest.fixture def get_localization_endpoint(): """Fixture for ows-product get localization endpoint.""" return '/localization/track' def test_get_track_localization( monkeypatch, track_localization_get_data, get_localization_endpoint): """Test get track localizations from ows-product service.""" tuid = 123 get_request_mock = _patch_request( monkeypatch, 'post', track_localization_get_data, 200) result = ows_product.get_track_localizations(tuid) get_request_mock.assert_called_with( services.OWS_PRODUCT, get_localization_endpoint, json={'tuids': [tuid]}) assert result assert result.message == track_localization_get_data def test_get_track_localizations_failed( monkeypatch, get_localization_endpoint): """Test get track localizations from ows-product service failed.""" tuid = 123 message = 'Failed to get localization' mock_json_response = { 'code': error.OWS_PRODUCT_ERROR_CODE, 'message': message } get_request_mock = _patch_request( monkeypatch, 'post', mock_json_response, 500) result = ows_product.get_track_localizations(tuid) get_request_mock.assert_called_with( services.OWS_PRODUCT, get_localization_endpoint, json={'tuids': [tuid]}) assert not result assert result.errors['message'] == mock_json_response def test_delete_track_localizations_calls_correct_url(mocker): """Test delete track localizations calls correct url.""" tuid = 123 mock_delete = mocker.patch('backend.models.ows_product.request.delete') ows_product.delete_track_localizations([tuid]) expected_url = '/localization/track/{}'.format(tuid) mock_delete.assert_called_with( services.OWS_PRODUCT, expected_url) many_tuids = [123, 234, 345] expected_url = '/localization/track/{}'.format( ','.join(str(t) for t in many_tuids)) ows_product.delete_track_localizations(many_tuids) mock_delete.assert_called_with( services.OWS_PRODUCT, expected_url) def test_delete_track_localizations_handles_success_response(monkeypatch): """Test success response is handled.""" tuid = 123 mock_response = '2 track localizations deleted.' _patch_request(monkeypatch, 'delete', mock_response, 200) delete_response = ows_product.delete_track_localizations([tuid]) assert isinstance(delete_response, response.Response) assert delete_response.status == response_code.OK def test_delete_track_localizations_error_response(monkeypatch): """Test error response is handled.""" tuid = 123 mock_response = { 'code': 'LOCALIZATION_ERROR', 'message': 'Failed to delete localization' } _patch_request(monkeypatch, 'delete', mock_response, 400) delete_response = ows_product.delete_track_localizations([tuid]) assert isinstance(delete_response, response.Response) assert delete_response.status == response_code.BAD_REQUEST def test_update_localizations_success_response( monkeypatch, update_track_localization_args): """Test update localization happy path.""" # See PUT /localization/tracks for more info # https://docs.google.com/document/d/1ikFWFJtkC3_U5GvzH1r74dDFfhPAjodPyzFCRcIxlmY data = [update_track_localization_args] mock_response = 'Localizations updated' _patch_request(monkeypatch, 'put', mock_response, 200) update_response = ows_product.update_localizations(data) assert isinstance(update_response, response.Response) assert update_response.status == response_code.OK def test_update_localizations_error_response( monkeypatch, update_track_localization_args): """Test bulk update error response is handled.""" data = [update_track_localization_args] mock_response = { 'code': 'LOCALIZATION_ERROR', 'message': 'Failed to update localization' } _patch_request(monkeypatch, 'put', mock_response, 400) update_response = ows_product.update_localizations(data) assert isinstance(update_response, response.Response) assert update_response.status == response_code.BAD_REQUEST def test_get_localization_languages(monkeypatch, localization_languages_data): """Test get localization languages from ows-product service.""" ows_product._response_cache = {} get_request_mock = _patch_request( monkeypatch, 'get', localization_languages_data, 200) result = ows_product.get_localization_languages() get_request_mock.assert_called_with( services.OWS_PRODUCT, '/localization/languages') assert result assert result.message == localization_languages_data assert 'localization_languages' in ows_product._response_cache # Validate result is cached result = ows_product.get_localization_languages() assert result.message == localization_languages_data assert get_request_mock.call_count == 1 def test_get_localization_languages_failed(monkeypatch, mocker, mock_app): """Test get localization languages from ows-product service failed.""" message = 'Failed to get localization languages' mock_json_response = { 'code': error.OWS_PRODUCT_ERROR_CODE, 'message': message } ows_product._response_cache = {} with mock_app: mocker.patch('backend.models.ows_product.g') get_request_mock = _patch_request( monkeypatch, 'get', mock_json_response, 500) result = ows_product.get_localization_languages() get_request_mock.assert_called_with( services.OWS_PRODUCT, '/localization/languages') assert not result assert result.errors['message'] == mock_json_response