"""Test cases for Highlight Model.""" from unittest.mock import MagicMock from oto import status import pytest import sqlalchemy from sqlalchemy import event from marketing.connectors import mysql from marketing.constants import error from marketing.models import highlight from tests import fixtures from tests.fixtures.models.highlight import HighlightFactory from tests.utils import db_operations @pytest.fixture def test_entity(): """Fixture for entity.""" return fixtures.models.highlight.get_data_sample().get('entity') @pytest.fixture def test_entity_id(): """Fixture for entity_id.""" return fixtures.models.highlight.get_data_sample().get('entity_id') @pytest.fixture def test_client(): """Fixture for client.""" return fixtures.models.highlight.get_data_sample().get('client') def test_get_marketing_highlights( test_entity, test_entity_id, test_client): """Test the data in the returned highlight objects.""" test_highlight = HighlightFactory.build( entity=test_entity, entity_id=test_entity_id, client=test_client) db_operations.seed_models(test_highlight) result = highlight.get_marketing_highlights( entity=test_entity, entity_id=test_entity_id, client=test_client) result_highlights = result.message.get('items') assert len(result_highlights) == 1 result_highlight = result_highlights[0] assert result_highlight['highlight_id'] == test_highlight.highlight_id assert result_highlight['mkt_program_id'] == test_highlight.mkt_program_id assert result_highlight['entity'] == test_highlight.entity assert result_highlight['entity_id'] == test_highlight.entity_id assert result_highlight['subject'] == test_highlight.subject assert result_highlight['description'] == test_highlight.description assert result_highlight['attachment'] == test_highlight.attachment assert result_highlight['scope'] == test_highlight.scope assert result_highlight['client'] == test_highlight.client def test_get_marketing_highlights_with_no_client( test_entity, test_entity_id): """Test for getting highlight when client is not passed.""" test_highlight = HighlightFactory.build( entity=test_entity, entity_id=test_entity_id) db_operations.seed_models(test_highlight) result = highlight.get_marketing_highlights( entity=test_entity, entity_id=test_entity_id) result_highlights = result.message.get('items') assert len(result_highlights) == 1 result_highlight = result_highlights[0] assert result_highlight['highlight_id'] == test_highlight.highlight_id assert result_highlight['mkt_program_id'] == test_highlight.mkt_program_id assert result_highlight['entity'] == test_highlight.entity assert result_highlight['entity_id'] == test_highlight.entity_id assert result_highlight['subject'] == test_highlight.subject assert result_highlight['description'] == test_highlight.description assert result_highlight['attachment'] == test_highlight.attachment assert result_highlight['scope'] == test_highlight.scope assert result_highlight['client'] == test_highlight.client def test_get_marketing_highlights_limit(test_entity, test_entity_id): """Test that thee returned highlights start at the given page offset.""" test_highlight = HighlightFactory.build_batch( 10, entity=test_entity, entity_id=test_entity_id) db_operations.seed_models(test_highlight) result = highlight.get_marketing_highlights( entity=test_entity, entity_id=test_entity_id, offset=3) result_items = result.message.get('items') assert len(result_items) == 7 assert result_items[0]['highlight_id'] == test_highlight[3].highlight_id def test_get_marketing_highlights_offset(test_entity, test_entity_id): """Test that the returned highlights end at the given page limit.""" test_highlights = HighlightFactory.build_batch( 10, entity=test_entity, entity_id=test_entity_id) db_operations.seed_models(test_highlights) result = highlight.get_marketing_highlights( entity=test_entity, entity_id=test_entity_id, limit=2) result_items = result.message.get('items') assert len(result_items) == 2 assert result_items[1]['highlight_id'] == test_highlights[1].highlight_id def test_get_marketing_highlights_program_type(test_entity, test_entity_id): """Test filtering for records of a particular .""" wanted = HighlightFactory.build_batch( 2, entity=test_entity, entity_id=test_entity_id, mkt_program_id=20) not_wanted = HighlightFactory.build_batch( 5, entity=test_entity, entity_id=test_entity_id, mkt_program_id=1) db_operations.seed_models(wanted + not_wanted) result = highlight.get_marketing_highlights( entity=test_entity, entity_id=test_entity_id, limit=50, mkt_program_id=20) result_items = result.message.get('items') assert len(result_items) == len(wanted) assert result_items[0]['highlight_id'] == wanted[0].highlight_id assert result_items[1]['highlight_id'] == wanted[1].highlight_id def test_get_marketing_highlights_not_found(test_entity, test_entity_id): """Test when marketing highlight not found.""" test_highlights = HighlightFactory.build( entity=test_entity, entity_id=test_entity_id) db_operations.seed_models(test_highlights) result = highlight.get_marketing_highlights( entity=test_entity, entity_id=1111) assert result.status == 404 def test_get_marketing_highlights_with_project(test_entity_id): """Test that project is supported as an entity type.""" project_highlight = HighlightFactory.build( entity='project', entity_id=test_entity_id) db_operations.seed_models(project_highlight) result = highlight.get_marketing_highlights( entity='project', entity_id=test_entity_id) assert result.status == 200 assert result.message.get('items') == [project_highlight.to_dict()] def test_create_marketing_highlight(): """Test creating a marketing highlight.""" data = fixtures.models.highlight.get_data_sample() current_highlight = highlight.create_marketing_highlight(**data) highlight_data = current_highlight.message assert current_highlight.status == status.CREATED assert highlight_data.get('highlight_id') for highlight_field, highlight_value in data.items(): assert highlight_data.get(highlight_field) == highlight_value @pytest.mark.parametrize( 'required_field', highlight.CREATE_OPERATION_REQUIRED_FIELDS) def test_create_marketing_highlight_with_missing_required_fields( required_field): """Test creating a marketing highlight with missing required fields.""" data = fixtures.models.highlight.get_data_sample() data.pop(required_field) current_highlight = highlight.create_marketing_highlight(**data) assert not current_highlight assert current_highlight.status == status.BAD_REQUEST assert len(current_highlight.errors['message']) == 1 assert current_highlight.errors['message'].get(required_field) def test_create_marketing_highlight_on_exception(monkeypatch): """Test creating a marketing highlight with an exception.""" message = 'Message' data = fixtures.models.highlight.get_data_sample() # Mock the session, which triggers an exception on add. mock_session = MagicMock() mock_session.add.side_effect = Exception(message) # Mock the db_session call and context. mock_db_session = MagicMock(return_value=mock_session) monkeypatch.setattr(mysql, '_db_session', mock_db_session) current_highlight = highlight.create_marketing_highlight(**data) assert current_highlight.status == status.INTERNAL_ERROR errors = current_highlight.errors assert errors.get('code') == error.ERROR_CODE_MYSQL assert errors.get('message') == error.ERROR_MESSAGE_DB_ISSUE def test_get_marketing_highlight_by_id(): """Test getting a marketing highlight by its id.""" sample = fixtures.models.highlight.get_sample().message response = highlight.get_marketing_highlight_by_id( sample.get('highlight_id')) assert response.message == sample def test_get_missing_marketing_highlight_by_id(): """Test getting a missing marketing highlight by its id.""" sample = fixtures.models.highlight.get_sample().message response = highlight.get_marketing_highlight_by_id( sample.get('highlight_id') + 1) assert response.status == status.NOT_FOUND def test_update_marketing_highlight(): """Test updating a marketing highlight.""" sample = fixtures.models.highlight.get_sample().message response = highlight.update_marketing_highlight( sample.get('highlight_id'), subject='New Subject') assert response.status == 200 response = highlight.get_marketing_highlight_by_id( sample.get('highlight_id')) assert response.message.get('subject') == 'New Subject' def test_update_inexistant_marketing_highlight(): """Test updating a marketing highlight that does not exist.""" response = highlight.update_marketing_highlight( 209884, subject='New Subject') assert response.status == 404 def test_update_marketing_highlight_without_data(): """Test updating a marketing highlight without providing data.""" sample = fixtures.models.highlight.get_sample().message response = highlight.update_marketing_highlight(sample.get('highlight_id')) assert response.status == 200 assert response.message == sample def test_update_marketing_highlight_on_forbidden_field(): """Test updating a marketing highlight on forbidden fields.""" sample = fixtures.models.highlight.get_sample().message response = highlight.update_marketing_highlight( sample.get('highlight_id'), subject='New Subject', entity='release', entity_id=2083) assert response.status == 200 response = highlight.get_marketing_highlight_by_id( sample.get('highlight_id')) assert response.message.get('entity') == sample.get('entity') assert response.message.get('entity_id') == sample.get('entity_id') def test_delete_marketing_highlight(): """Test deleting an highlight.""" sample = fixtures.models.highlight.get_sample().message response = highlight.delete_marketing_highlight(sample.get('highlight_id')) deleted_highlight = highlight.get_marketing_highlight_by_id( sample.get('highlight_id')) assert response.status is status.OK assert deleted_highlight.status is status.NOT_FOUND def test_delete_nonexistent_marketing_highlight(): """Test deleting an highlight that does not exist.""" response = highlight.delete_marketing_highlight(30993) assert response.status is status.NOT_FOUND def test_table_health_check(): """Test the health of the table connection.""" table_name = highlight.Highlight.__tablename__ health = highlight.table_health_check() assert health.message.get(table_name) == 'ok' def test_bad_table_health_check(monkeypatch): """Test the health of the table connection.""" monkeypatch.setattr( mysql, 'sentry_capture_exception', MagicMock(spec=mysql.sentry_capture_exception)) # Mock the session, which triggers an exception on add. mock_session = MagicMock() mock_session.execute.side_effect = sqlalchemy.exc.SQLAlchemyError() mock_db_session = MagicMock(return_value=mock_session) monkeypatch.setattr(highlight.mysql, '_db_session', mock_db_session) health = highlight.table_health_check() assert not health assert health.errors.get('code') == error.ERROR_CODE_MYSQL assert health.errors.get('message') == error.ERROR_MESSAGE_DB_ISSUE assert mysql.sentry_capture_exception.called def test_getting_highlight_by_id_and_session(): """Test getting a highlight by its id.""" sample = fixtures.models.highlight.get_sample().message session = mysql._db_session() response = highlight._get_highlight_by_id( sample.get('highlight_id'), session) session.close() assert isinstance(response, highlight.Highlight) assert response.to_dict() == sample def test_getting_missing_highlight_by_id_and_session(): """Test getting a missing highlight by its id.""" sample = fixtures.models.highlight.get_sample().message session = mysql._db_session() response = highlight._get_highlight_by_id( sample.get('highlight_id') + 1, session) session.close() assert not response assert response.status == status.NOT_FOUND def test_getting_highlight_with_bad_id_and_session(): """Test getting a missing highlight by its id.""" session = mysql._db_session() response = highlight._get_highlight_by_id('Not Number', session) session.close() assert not response assert response.status == status.BAD_REQUEST assert len(response.errors.get('message')) == 1 assert response.errors.get('message').get('highlight_id') def test_delete_highlight_by_release_id_success(): """Test successful deletion of highlight given a release_id.""" entity_id = '123' entity_type = 'release' create_highlight_response = fixtures.models.highlight.get_sample( entity=entity_type, entity_id=entity_id) assert create_highlight_response.status == 201 response = highlight.delete_highlight_by_entity(entity_id, entity_type) assert response.status == status.OK def test_delete_highlight_by_release_id_failure(monkeypatch): """Test unsuccessful deletion of highlight given a release id.""" entity_id = '123' entity_type = 'release' fixtures.models.highlight.get_sample( entity=entity_type, entity_id=entity_id) mock_session = MagicMock() mock_session.execute.side_effect = Exception('error') mock_db_session = MagicMock(return_value=mock_session) monkeypatch.setattr(mysql, '_db_session', mock_db_session) response = highlight.delete_highlight_by_entity(entity_id, entity_type) assert response.status == status.INTERNAL_ERROR def test_get_marketing_highlights_query_count( test_entity, test_entity_id, test_client): """Test the number of queries get_marketing_highlights runs.""" test_highlight = HighlightFactory.build( entity=test_entity, entity_id=test_entity_id, client=test_client) db_operations.seed_models(test_highlight) statements = [] def catch_queries( conn, cursor, statement, parameters, context, executemany ): statements.append(statement) event.listen(mysql._db_engine, 'before_cursor_execute', catch_queries) highlight.get_marketing_highlights( entity=test_entity, entity_id=test_entity_id, client=test_client ) # There should be one query for the total highlight count and one to get # the offset highlight. assert len(statements) == 2