"""Test for Timed Releases Model CRUD operation.""" import datetime from unittest.mock import patch import pytest from oto import status as http_status from sqlalchemy.exc import SQLAlchemyError from tests.unit.testutils import db from timed_release.connectors.sql import db_session from timed_release.models import timed_release def test_to_dict(): """Test that the to dict function only returns the expected properties.""" sale_date_time = datetime.datetime( 2023, 3, 3, 10, 10, 10).strftime('%Y-%m-%d') test_timed_release = timed_release.TimedRelease( sales_date_time=sale_date_time, store_id=1, timing='staggered') expected_dict = { 'sale_date_time': test_timed_release.sales_date_time, 'store_id': test_timed_release.store_id, 'timing': test_timed_release.timing} assert test_timed_release.to_dict() == expected_dict def to_ws_dict(): """Test that to_ws_dict function only returns the expected properties.""" sale_date_time = datetime.datetime( 2023, 3, 3, 10, 10, 10).strftime('%Y-%m-%d') test_timed_release = timed_release.TimedRelease( sales_date_time=sale_date_time, store_id=1, timing='staggered', source='workstation') expected_dict = { 'sale_date_time': test_timed_release.sales_date_time, 'store_id': test_timed_release.store_id, 'timing': test_timed_release.timing, 'source': test_timed_release.source} assert test_timed_release.to_dict() == expected_dict @db.test_schema def test_get_timed_release_data_success(): """Test to get timed release data by product id.""" expected_data = { 'timed': [ { 'delivery_store': {'id': 286}, 'sale_date_time': '2023-03-03T10:10:10Z' } ], 'staggered': [ { 'delivery_store': {'id': 1}, 'sale_date': '2023-03-03' } ] } db.insert_timed_release_data() get_response = timed_release.get_product_timed_release_data(12) assert get_response.message == expected_data @db.test_schema def test_get_timed_release_data_not_found(): """Test that timed release data not found for requested product id.""" expected_response = {'timed': [], 'staggered': []} get_response = timed_release.get_product_timed_release_data(14) assert get_response.message == expected_response @db.test_schema @patch( 'timed_release.connectors.sql.db_session', side_effect=SQLAlchemyError()) def test_get_timed_release_data_internal_error( monkeypatch): """Test get_product_timed_release_data with SQLAlchemyError.""" db.insert_timed_release_data() get_response = timed_release.get_product_timed_release_data(12) assert get_response.status == http_status.INTERNAL_ERROR @db.test_schema def test_update_timed_release_data_success(): """Test to get timed release data by product id.""" data = { 'timed': [{ 'sale_date_time': '2023-01-27 19:03:22', 'delivery_store': { 'id': 187 } }, { 'sale_date_time': '2023-01-25 10:03:22', 'delivery_store': { 'id': 286 } }], 'staggered': [{ 'sale_date': '2023-01-28', 'delivery_store': { 'id': 1 } }, { 'sale_date': '2023-01-26', 'delivery_store': { 'id': 287 } }] } orchard_identity_id = '03e83149-3c7f-4587-940b-ce83dec34bc8' db.insert_timed_release_data() update_response = timed_release.update_product_timed_release_data( 12, data, orchard_identity_id) assert update_response.status == 200 assert update_response.message is not None @db.test_schema def test_timed_release_created_and_updated_by_success(): """Test timed release created and updated columns.""" data = { 'timed': [{ 'sale_date_time': '2023-01-27 19:03:22', 'delivery_store': { 'id': 286 } }], 'staggered': [{ 'sale_date': '2023-03-03', 'delivery_store': { 'id': 1 } }] } orchard_identity_id = '03e83149-3c7f-4587-940b-ce83dec34bc4' db.insert_timed_release_data() update_response = timed_release.update_product_timed_release_data( 12, data, orchard_identity_id) assert update_response.status == 200 assert update_response.message is not None with db_session() as session: timed_object = session.query(timed_release.TimedRelease).filter( timed_release.TimedRelease.product_id == 12 ).filter(timed_release.TimedRelease.timing == 'timed').first() assert (timed_object.created_on == datetime.datetime(2023, 3, 3, 10, 10, 10)) assert timed_object.created_by != orchard_identity_id assert (timed_object.updated_on > datetime.datetime(2023, 3, 3, 10, 10, 10)) assert timed_object.updated_by == orchard_identity_id staggered_object = session.query(timed_release.TimedRelease).filter( timed_release.TimedRelease.product_id == 12 ).filter(timed_release.TimedRelease.timing == 'staggered').first() assert (staggered_object.created_on == datetime.datetime(2023, 3, 3, 10, 10, 10)) assert staggered_object.created_by != orchard_identity_id assert (staggered_object.updated_on >= datetime.datetime(2023, 3, 3, 10, 10, 10)) assert staggered_object.updated_by == orchard_identity_id @db.test_schema def test_get_supported_stores_timed_release_ws_success( supported_stores_timed_release_ws_fixture): """Test to get timed release data by product id success.""" product_id = 13 db.insert_timed_release_data() with db_session() as session: get_response = timed_release.get_supported_stores_timed_release_ws( product_id, session) assert get_response.status == http_status.OK assert get_response.message == supported_stores_timed_release_ws_fixture @db.test_schema def test_get_supported_stores_timed_release_ws_not_found(): """Test to get timed release data by product id not found.""" product_id = 12 db.insert_timed_release_data() with db_session() as session: get_response = timed_release.get_supported_stores_timed_release_ws( product_id, session) assert get_response.status == http_status.NOT_FOUND @pytest.mark.parametrize( 'product_id, expected', [ (12, True), (13, False) ] ) @db.test_schema def test_check_if_supported_stores_timed_release_oa_exists( product_id, expected): """Test check_if_supported_stores_timed_release_oa_exists.""" db.insert_timed_release_data() with db_session() as session: result = ( timed_release.check_if_supported_stores_timed_release_oa_exists( product_id, session ) ) assert result is expected @db.test_schema def test_upsert_existing_supported_stores_timed_release_ws_success( supported_stores_tr_data_fixture ): """Test upsert existing supported store timed release for ws success.""" db.insert_timed_release_data() with db_session() as session: upsert_response = ( timed_release.upsert_supported_stores_timed_release_ws( product_id=13, supported_stores_tr_data=supported_stores_tr_data_fixture, identity_id='user-123', session=session ) ) assert upsert_response.status == http_status.OK assert upsert_response.message == { 'supported_releases': [ { 'sales_date_time': '2027-05-03T10:10:10Z', 'store_id': 187, 'timing': 'timed', 'source': 'workstation', 'user_timezone': None }, { 'sales_date_time': '2027-05-03T10:10:10Z', 'store_id': 286, 'timing': 'timed', 'source': 'workstation', 'user_timezone': None }, { 'sales_date_time': '2027-05-03T10:10:10Z', 'store_id': 152, 'timing': 'timed', 'source': 'workstation', 'user_timezone': None } ] } @db.test_schema def test_upsert_new_supported_stores_timed_release_ws_success( mocker, new_supported_stores_tr_data_fixture ): """Test upsert new supported store timed release for ws success.""" db.insert_timed_release_data() with db_session() as session: upsert_response = ( timed_release.upsert_supported_stores_timed_release_ws( product_id=14, supported_stores_tr_data=new_supported_stores_tr_data_fixture, identity_id='user-123', session=session ) ) assert upsert_response.status == http_status.OK assert upsert_response.message == { 'supported_releases': [ { 'sales_date_time': '2026-04-15T15:15:15Z', 'store_id': 40, 'timing': 'timed', 'source': 'workstation', 'user_timezone': None }, { 'sales_date_time': '2026-04-15T15:15:15Z', 'store_id': 41, 'timing': 'timed', 'source': 'workstation', 'user_timezone': None } ] } @db.test_schema def test_upsert_supported_stores_timed_release_ws_db_failure( monkeypatch, db_session_fixture, supported_stores_tr_data_fixture ): """Test upsert supported store timed release for ws db failure.""" db.insert_timed_release_data() session = db_session_fixture session.query.side_effect = SQLAlchemyError('DB query failure') upsert_response = timed_release.upsert_supported_stores_timed_release_ws( product_id=13, supported_stores_tr_data=supported_stores_tr_data_fixture, identity_id='user-123', session=session ) assert upsert_response.status == http_status.INTERNAL_ERROR @db.test_schema @pytest.mark.parametrize( 'product_id, store_id, expected_status, expected_message, raises', [ # Case 1: Staggered release set in OA ( 12, 1, http_status.OK, { 'timed': None, 'staggered': { 'sales_date': '2023-03-03' }, }, None ), # Case 2: Timed release set in OA ( 12, 286, http_status.OK, { 'timed': { 'sales_date_time': '2023-03-03T10:10:10Z' }, 'staggered': None, }, None ), # Case 3: Timed release set in WS ( 13, 187, http_status.OK, { 'timed': { 'sales_date_time': '2026-05-20T11:11:11Z' }, 'staggered': None, }, None ), # Case 4: No record found (12, 5, http_status.NOT_FOUND, None, None), # Case 5: SQLAlchemyError (12, 1, http_status.INTERNAL_ERROR, None, SQLAlchemyError) ] ) def test_get_product_timed_release_by_store_id( product_id, store_id, expected_status, expected_message, raises, db_session_fixture ): """Test covers all use cases for get_product_timed_release_by_store_id.""" db.insert_timed_release_data() if raises: session = db_session_fixture session.query.side_effect = SQLAlchemyError('DB query failure') get_response = ( timed_release.get_product_timed_release_by_store_id( product_id, store_id, session ) ) else: with db_session(read_only=True) as session: get_response = timed_release.get_product_timed_release_by_store_id( product_id, store_id, session ) assert get_response.status == expected_status if expected_message: assert get_response.message == expected_message else: assert not get_response.message @pytest.mark.parametrize( 'product_id, expected_status', [ # Case 1: Delete timed releases success (13, http_status.OK), # Case 2: Timed releases not found (12, http_status.NOT_FOUND), # Case 3: DB error (13, http_status.INTERNAL_ERROR) ] ) @db.test_schema def test_delete_timed_release_ws( mocker, product_id, expected_status, db_session_fixture ): """Test delete timed release ws all use cases.""" db.insert_timed_release_data() if expected_status == http_status.INTERNAL_ERROR: session = db_session_fixture session.query.side_effect = SQLAlchemyError('DB query failure') delete_response = timed_release.delete_timed_release_ws( product_id=product_id, session=session) else: with db_session() as session: delete_response = timed_release.delete_timed_release_ws( product_id=product_id, session=session) assert delete_response.status == expected_status @db.test_schema def test_add_timed_release_ws_with_user_timezone(): """Test add timed release ws with user_timezone field.""" data = { 'store_id': 187, 'sales_date_time': datetime.datetime(2027, 5, 3, 10, 10, 10), 'user_timezone': 'America/New_York' } with db_session() as session: result = timed_release.add_timed_release_ws( product_id=100, data=data, identity_id='user-123', session=session ) assert result['user_timezone'] == 'America/New_York' assert result['store_id'] == 187 assert result['timing'] == 'timed' assert result['source'] == 'workstation' @db.test_schema def test_update_timed_release_ws_with_user_timezone(): """Test update timed release ws with user_timezone field.""" db.insert_timed_release_data() data = { 'store_id': 286, 'sales_date_time': datetime.datetime(2028, 6, 4, 11, 11, 11), 'user_timezone': 'Europe/London' } with db_session() as session: result = timed_release.update_timed_release_ws( product_id=13, data=data, identity_id='user-456', session=session ) assert result['user_timezone'] == 'Europe/London' assert result['store_id'] == 286 assert result['sales_date_time'] == '2028-06-04T11:11:11Z' @db.test_schema def test_upsert_supported_stores_timed_release_ws_with_user_timezone(): """Test upsert supported stores with user_timezone field.""" supported_stores_tr_data = [ { 'product_id': 15, 'store_id': 200, 'sales_date_time': datetime.datetime(2027, 5, 3, 10, 10, 10), 'timing': 'timed', 'source': 'workstation', 'user_timezone': 'Asia/Tokyo' } ] with db_session() as session: upsert_response = ( timed_release.upsert_supported_stores_timed_release_ws( product_id=15, supported_stores_tr_data=supported_stores_tr_data, identity_id='user-789', session=session ) ) assert upsert_response.status == http_status.OK assert ( upsert_response.message['supported_releases'][0]['user_timezone'] == 'Asia/Tokyo' )