"""Test highlight endpoints.""" import json from unittest.mock import MagicMock from oto import response from oto import status from owsrequest import request from owsrequest import test_utils from owsrequest.constants import headers as owsrequest_constants import pytest from marketing.logic import entities from marketing.logic import highlights from tests import fixtures from tests.fixtures.models.highlight import HighlightFactory from tests.utils import db_operations def test_getting_highlights(client, monkeypatch): """Test getting highlights.""" monkeypatch.setattr( highlights, 'get_highlights', MagicMock(wraps=highlights.get_highlights)) model_data = fixtures.models.highlight.get_data_sample() entity = model_data.get('entity') entity_id = model_data.get('entity_id') count = 5 data = fixtures.models.highlight.get_samples( count, entity=entity, entity_id=entity_id, client='alw') response = client.get('/highlights/{}/{}'.format(entity, entity_id)) assert response.status_code == 200 assert highlights.get_highlights.called highlights.get_highlights.assert_called_with( entity, str(entity_id), client=None, offset=None, limit=None, mkt_program_id=None) data = json.loads(response.data.decode('utf8')) assert len(data.get('items')) == count for item in data.get('items'): assert item.get('entity') == entity assert item.get('entity_id') == entity_id def test_get_highlights_filtered_by_program_id(client): """Test that results are filtered by mkt_program_id.""" entity_type = 'project' entity_id = 12345 wanted_program_id = 20 wanted_records = HighlightFactory.build_batch( size=4, entity=entity_type, entity_id=entity_id, mkt_program_id=wanted_program_id) unwanted_records = HighlightFactory.build_batch( size=3, entity=entity_type, entity_id=entity_id, mkt_program_id=5) db_operations.seed_models(wanted_records + unwanted_records) response = client.get('/highlights/{}/{}?mkt_program_id={}'.format( entity_type, entity_id, wanted_program_id)) data = json.loads(response.data.decode('utf-8')) assert response.status_code == 200 assert len(data.get('items')) == len(wanted_records) for index, item in enumerate(data.get('items')): assert item.get('highlight_id') == wanted_records[index].highlight_id @pytest.mark.parametrize('request_client, result_status, item_count', ( # We add into the db items that are for alw client, so OA shouldn't # have any records - and thus returns a 404. ['oa', 404, 0], ['alw', 200, 5])) def test_getting_highlights_with_client( client, monkeypatch, request_client, result_status, item_count): """Test getting highlights with client.""" monkeypatch.setattr( highlights, 'get_highlights', MagicMock(wraps=highlights.get_highlights)) model_data = fixtures.models.highlight.get_data_sample() entity = model_data.get('entity') entity_id = model_data.get('entity_id') data = fixtures.models.highlight.get_samples( item_count, entity=entity, entity_id=entity_id, client='alw') response = client.get('/highlights/{}/{}?client={}'.format( entity, entity_id, request_client)) assert response.status_code == result_status if item_count: data = json.loads(response.data.decode('utf8')) assert len(data.get('items')) == item_count assert highlights.get_highlights.called highlights.get_highlights.assert_called_with( entity, str(entity_id), client=request_client, offset=None, limit=None, mkt_program_id=None) def test_getting_highlights_with_offset_and_limit(client, monkeypatch): """Test getting highlights with offset and limit.""" monkeypatch.setattr( highlights, 'get_highlights', MagicMock(wraps=highlights.get_highlights)) entity = 'release' entity_id = 29847 count = 100 data = fixtures.models.highlight.get_samples( count, entity=entity, entity_id=entity_id, client='alw') response = client.get('/highlights/release/29847?offset=10&limit=20') assert response.status_code == 200 assert highlights.get_highlights.called highlights.get_highlights.assert_called_with( entity, str(entity_id), client=None, offset='10', limit='20', mkt_program_id=None) items = json.loads(response.data.decode('utf8')).get('items') assert len(items) == 20 for index, item in enumerate(items): current_item = data[10 + index].message assert current_item.get('highlight_id') == item.get('highlight_id') def test_getting_highlight_by_entity_with_grass_headers(client, monkeypatch): """Testing getting highlights by entity with Grass headers.""" account_type = 'vendor' account_id = 93873 product_id = 29847 request_specs = [{ 'service': 'ows-product', 'path': '/{type}/{account_id}/product/{product_id}'.format( type=account_type, account_id=account_id, product_id=product_id), 'status': 403}] monkeypatch.setattr( request, 'head', test_utils.mock_ows_requests(request_specs)) monkeypatch.setattr(highlights, 'get_highlights', MagicMock()) http_response = client.get( '/highlights/release/{product_id}?offset=10&limit=20'.format( product_id=product_id), headers={ owsrequest_constants.GRASS_ACCOUNT_TYPE: account_type, owsrequest_constants.GRASS_ACCOUNT_ID: account_id}) assert http_response.status_code == 403 def test_highlight_creation(client, monkeypatch): """Test highlight creation success.""" data = fixtures.models.highlight.get_data_sample( entity='release', entity_id=15) request_specs = [{ 'service': 'ows-product', 'path': '/product/{entity_id}'.format(entity_id=data['entity_id']), 'status': 200}] monkeypatch.setattr( request, 'get', test_utils.mock_ows_requests(request_specs)) monkeypatch.setattr( highlights, 'create_highlight', MagicMock(wraps=highlights.create_highlight)) http_response = client.post( '/highlights', data=json.dumps(data)) highlights.create_highlight.assert_called_with(data) assert http_response.status_code == 201 @pytest.mark.parametrize('entity_owner_response', [ response.Response(status=403), response.Response(status=200)]) def test_highlight_creation_with_grass_headers( client, monkeypatch, entity_owner_response): """Test highlight creation with Grass Headers.""" account_type = 'vendor' account_id = 93873 product_id = 29847 data = fixtures.models.highlight.get_data_sample( entity='release', entity_id=product_id) head_specs = [{ 'service': 'ows-product', 'path': '/{type}/{account_id}/product/{product_id}'.format( type=account_type, account_id=account_id, product_id=product_id), 'status': entity_owner_response.status, 'json': entity_owner_response.message}] monkeypatch.setattr( request, 'head', test_utils.mock_ows_requests(head_specs)) get_specs = [{ 'service': 'ows-product', 'path': '/product/{entity_id}'.format(entity_id=data['entity_id']), 'status': 200}] monkeypatch.setattr( request, 'get', test_utils.mock_ows_requests(get_specs)) monkeypatch.setattr( highlights, 'create_highlight', MagicMock(wraps=highlights.create_highlight)) http_response = client.post( '/highlights', data=json.dumps(data), headers={ owsrequest_constants.GRASS_ACCOUNT_TYPE: account_type, owsrequest_constants.GRASS_ACCOUNT_ID: account_id }) if entity_owner_response: highlights.create_highlight.assert_called_with(data) assert http_response.status_code == 201 else: assert not highlights.create_highlight.called assert http_response.status_code == entity_owner_response.status def test_highlight_creation_without_data(client, monkeypatch): """Test highlight creation without data.""" monkeypatch.setattr( highlights, 'create_highlight', MagicMock(wraps=highlights.create_highlight)) http_response = client.post('/highlights') highlights.create_highlight.assert_called_with({}) assert http_response.status_code == 400 @pytest.mark.parametrize('field_info,has_changed', [ [{'subject': 'Hello'}, True], [{'description': 'Hello'}, True], [{'attachment': 'wrong_value'}, False], [{'client': 'wrong_value'}, False], [{'entity_id': '29874'}, False], [{'entity_type': 'wrong_value'}, False]]) def test_highlight_update(client, monkeypatch, field_info, has_changed): """Test highlight update.""" monkeypatch.setattr( highlights, 'update_highlight', MagicMock(wraps=highlights.update_highlight)) data = fixtures.models.highlight.get_sample().message response = client.put( '/highlights/{}'.format(data.get('highlight_id')), data=json.dumps(field_info)) assert response.status_code == 200 data = json.loads(response.data.decode('utf8')) field_key, field_value = list(field_info.items())[0] if has_changed: assert data.get(field_key) == field_value else: assert data.get(field_key) != field_value def test_highlight_update_with_invalid_ownership(client, monkeypatch): """Test updating an highlight while not having the right owner.""" account_type = 'vendor' account_id = 93873 product_id = 29847 data = fixtures.models.highlight.get_sample( entity='release', entity_id=product_id).message head_specs = [{ 'service': 'ows-product', 'path': '/{type}/{account_id}/product/{product_id}'.format( type=account_type, account_id=account_id, product_id=product_id), 'status': 403}] monkeypatch.setattr( request, 'head', test_utils.mock_ows_requests(head_specs)) http_response = client.put( '/highlights/{}'.format(data.get('highlight_id')), headers={ owsrequest_constants.GRASS_ACCOUNT_TYPE: account_type, owsrequest_constants.GRASS_ACCOUNT_ID: account_id }) assert http_response.status_code == status.FORBIDDEN def test_highlight_deletion(client, monkeypatch): """Test highlight deletion.""" monkeypatch.setattr( highlights, 'delete_highlight', MagicMock(wraps=highlights.delete_highlight)) data = fixtures.models.highlight.get_sample().message highlight_id = data.get('highlight_id') response = client.delete('/highlights/{}'.format(highlight_id)) highlights.delete_highlight.assert_called_with(str(highlight_id)) assert response.status_code == status.OK def test_highlight_deletion_with_grass_headers(client, monkeypatch): """Test highlight deletion with Grass headers.""" monkeypatch.setattr( highlights, 'delete_highlight', MagicMock(wraps=highlights.delete_highlight)) is_owner = MagicMock(spec=entities.is_owner) is_owner.return_value = response.Response(status=status.FORBIDDEN) monkeypatch.setattr(highlights, 'is_owner', is_owner) account_type = 'vendor' account_id = 93873 data = fixtures.models.highlight.get_sample().message highlight_id = data.get('highlight_id') delete_response = client.delete( '/highlights/{}'.format(highlight_id), headers={ owsrequest_constants.GRASS_ACCOUNT_TYPE: account_type, owsrequest_constants.GRASS_ACCOUNT_ID: account_id }) # Counter intuitive: the is_owner.assert_called_with does not work in this # case even though the “expected” shows identical to the expected. See: # # Expected call: # mock('1', account_id='93873', account_type='vendor') # # Actual call: # mock('1', account_id='93873', account_type='vendor') assert is_owner.call_args[0] == (str(highlight_id),) assert is_owner.call_args[1] == { 'account_id': str(account_id), 'account_type': account_type } assert not highlights.delete_highlight.called assert delete_response.status_code == status.FORBIDDEN