"""Unit tests for the release correction model.""" from datetime import datetime from unittest.mock import Mock import pytest from product_workflow.connectors import mysql from product_workflow.models import release_approval_queue from product_workflow.models import release_correction from product_workflow.models import release_correction_detail from product_workflow.utils import error_handling from tests.factories import release_approval_queue \ as raq_factory from tests.factories import release_correction_detail as \ release_correction_detail_factory from tests.testutils import db @pytest.fixture def release_id(): """Create a release id for testing.""" return 123 @pytest.fixture def release_correction_id(): """Create a release correction id for testing.""" return 567 @pytest.fixture def release_correction_data(): """Return a dictionary of release correction properties for testing.""" return { 'release_id': 1, 'status': 'active', 'last_updated': datetime(2017, 6, 10, 0, 0, 0), 'last_updated_by': 1, 'last_updated_type': 'vendor' } @pytest.fixture def release_correction_update_data(): """Return a dictionary of updated release correction properties.""" return { 'status': 'submitted' } @pytest.fixture def release_correction_model(release_correction_id): """Return a release correction model instance.""" return release_correction.ReleaseCorrection( release_correction_id=release_correction_id, release_id=1, status='active', last_updated=datetime(2017, 6, 10, 0, 0, 0), last_updated_by=1) def test_to_dict(release_correction_id, release_id): """Test that the expected properties are returned.""" status = 'rejected' correction = release_correction.ReleaseCorrection( release_correction_id=release_correction_id, release_id=release_id, status=status, last_updated_by=1) assert correction.to_dict() == { 'release_correction_id': release_correction_id, 'release_id': release_id, 'status': status, 'items': [] } @db.test_schema def test_create_release_correction(release_correction_data): """Test that a new release correction is returned.""" response = release_correction.create(release_correction_data) correction = response.message assert response.status == 201 assert correction['status'] == release_correction_data['status'] @db.test_schema def test_get_last_release_correction_success( release_id, release_correction_id): """Test that the last release correction in the db is returned.""" should_be_first = release_correction.ReleaseCorrection( release_correction_id=release_correction_id, release_id=release_id, status='submitted', last_updated=datetime(2017, 6, 10, 0, 0, 0), last_updated_by=1) should_be_last = release_correction.ReleaseCorrection( release_correction_id=release_correction_id + 1, release_id=release_id, status='applied', last_updated=datetime(2017, 6, 10, 0, 0, 0), last_updated_by=1) # set the expected payload before seeding so we don't run into a # DetachedInstanceError when executing to_dict on an object with # a closed session expected = should_be_last.to_dict() db.seed_models([should_be_first, should_be_last]) result = release_correction.get_last_release_correction( release_id=release_id) assert result.status == 200 assert result.message == expected @db.test_schema def test_get_last_release_correction_no_records(release_id): """Test that a 404 status is returned if there are no records.""" result = release_correction.get_last_release_correction( release_id=release_id) assert result.status == 404 assert result.errors == { 'code': 'not_found_error', 'message': 'No release correction record found'} def test_get_last_release_correction_db_error( db_exception, mocker, release_id): """Test that a DB exception is logged and a 500 status is returned.""" mock_session = db.mock_db_session(mocker) mock_session.query.side_effect = db_exception mocker.patch.object(error_handling, 'log_db_exception', Mock()) result = release_correction.get_last_release_correction( release_id=release_id) assert result.status == 500 error_handling.log_db_exception.assert_called_once_with(db_exception) @db.test_schema def test_get_release_correction_success(release_id, release_correction_id): """Test that the a release correction in the db is returned.""" should_exist = release_correction.ReleaseCorrection( release_correction_id=release_correction_id, release_id=release_id, status='submitted', last_updated=datetime(2017, 6, 10, 0, 0, 0), last_updated_by=1) expected = should_exist.to_dict() db.seed_models([should_exist]) result = release_correction.get_release_correction( release_correction_id=release_correction_id) assert result.to_dict() == expected @db.test_schema def test_get_release_correction_no_records(release_correction_id): """Test that None is returned if there are no records.""" result = release_correction.get_release_correction( release_correction_id=release_correction_id) assert result is None def test_get_release_correction_db_error( db_exception, mocker, release_correction_id): """Test that a DB exception is logged and a 500 status is returned.""" mock_session = db.mock_db_session(mocker) mock_session.query.side_effect = db_exception mocker.patch.object(error_handling, 'log_db_exception', Mock()) result = release_correction.get_release_correction( release_correction_id=release_correction_id) assert result.status == 500 error_handling.log_db_exception.assert_called_once_with(db_exception) @db.test_schema def test_delete_release_correction_success(release_correction_model, release_correction_id): """Test that the a release correction in the db is returned.""" correction_details = release_correction_detail_factory.\ ReleaseCorrectionDetailFactory.build_batch( 2, release_correction_id=release_correction_id) release_approval = raq_factory.ReleaseApprovalQueueFactory\ .build(release_correction_id=release_correction_id) db.seed_models([release_correction_model, release_approval]) db.seed_models(correction_details) result = release_correction.delete_release_correction( release_correction_model) assert result.status == 202 with mysql.db_session() as session: still_existing_release_correction = session.query( release_correction.ReleaseCorrection).filter_by( release_correction_id=release_correction_id).first() assert still_existing_release_correction is None still_existing_release_correction_details = session.query( release_correction_detail.ReleaseCorrectionDetail).filter_by( release_correction_id=release_correction_id).all() assert len(still_existing_release_correction_details) == 0 still_existing_release_approval = session.query( release_approval_queue.ReleaseApprovalQueue).filter_by( release_correction_id=release_correction_id).first() assert still_existing_release_approval is None def test_delete_release_correction_db_error( db_exception, mocker, release_correction_id, release_correction_model): """Test that a DB exception is logged and a 500 status is returned.""" mock_session = db.mock_db_session(mocker) mock_session.delete.side_effect = db_exception mocker.patch.object(error_handling, 'log_db_exception', Mock()) result = release_correction.delete_release_correction( release_correction_model) assert result.status == 500 error_handling.log_db_exception.assert_called_once_with(db_exception) @db.test_schema def test_update_release_correction_success( release_correction_id, release_correction_model, release_correction_update_data ): """Test that a release correction is updated and returned.""" db.seed_models([release_correction_model]) response = release_correction.update( release_correction_id, release_correction_update_data ) correction = response.message assert response.status == 200 assert correction['status'] == release_correction_update_data['status'] @db.test_schema def test_update_release_correction_ignores_release_correction_id_key( release_correction_id, release_correction_model ): """Test that a release correction cannot update its primary key.""" db.seed_models([release_correction_model]) response = release_correction.update( release_correction_id, {'release_correction_id': 9001} ) assert response.status == 400 @db.test_schema def test_update_release_correction_not_found( release_correction_id, release_correction_update_data ): """Test updating an non existent release correction returns 404 status.""" response = release_correction.update( release_correction_id, release_correction_update_data ) assert response.status == 404