import datetime from unittest import mock import pytest from dmp.adapters.fivetran.enums import ConnectionSetupState, ConnectionSyncState from dmp.adapters.fivetran.models import ShopifyConnection from dmp.app_connections.enums import AppConnectionStatus from dmp.shopify.handlers import RefreshStoreHandler, RefreshStoreRequest from dmp.shopify.models import ShopifyStoreAssociation from dmp.shopify.repositories import StoreAssociationRepository from tests.unit.types import BuildModel, CreateReportingModel class TestRefreshStoreHandler: @pytest.mark.db def test_refresh_store_connection_pending( self, handler: RefreshStoreHandler, store_association_repository: StoreAssociationRepository, build_model: BuildModel, create_reporting_model: CreateReportingModel, fivetran_client_mock: mock.MagicMock, ) -> None: fivetran_connection = build_model( ShopifyConnection, status={ "setup_state": ConnectionSetupState.INCOMPLETE, "sync_state": ConnectionSyncState.SCHEDULED, }, ) association = create_reporting_model( ShopifyStoreAssociation, fivetran_connector_id=fivetran_connection.id, status=AppConnectionStatus.PENDING, ) fivetran_client_mock.get_shopify_connection.return_value = fivetran_connection handler.handle( RefreshStoreRequest(fivetran_connection_id=fivetran_connection.id) ) refreshed_association = store_association_repository.first() assert refreshed_association assert refreshed_association.id == association.id assert refreshed_association.synced_at == fivetran_connection.succeeded_at assert refreshed_association.status == AppConnectionStatus.PENDING @pytest.mark.db def test_refresh_store_connection_broken( self, handler: RefreshStoreHandler, store_association_repository: StoreAssociationRepository, build_model: BuildModel, create_reporting_model: CreateReportingModel, fivetran_client_mock: mock.MagicMock, ) -> None: fivetran_connection = build_model( ShopifyConnection, status={"setup_state": ConnectionSetupState.BROKEN} ) association = create_reporting_model( ShopifyStoreAssociation, fivetran_connector_id=fivetran_connection.id, status=AppConnectionStatus.PENDING, ) fivetran_client_mock.get_shopify_connection.return_value = fivetran_connection handler.handle( RefreshStoreRequest(fivetran_connection_id=fivetran_connection.id) ) refreshed_association = store_association_repository.first() assert refreshed_association assert refreshed_association.id == association.id assert refreshed_association.synced_at == fivetran_connection.succeeded_at assert refreshed_association.status == AppConnectionStatus.ERROR @pytest.mark.db def test_refresh_store_connection_connected_not_synced_and_not_processed_store( self, handler: RefreshStoreHandler, store_association_repository: StoreAssociationRepository, build_model: BuildModel, create_reporting_model: CreateReportingModel, fivetran_client_mock: mock.MagicMock, ) -> None: fivetran_connection = build_model( ShopifyConnection, status={ "setup_state": ConnectionSetupState.CONNECTED, "sync_state": ConnectionSyncState.SCHEDULED, }, ) association = create_reporting_model( ShopifyStoreAssociation, fivetran_connector_id=fivetran_connection.id, status=AppConnectionStatus.PENDING, synced_at=None, ) fivetran_client_mock.get_shopify_connection.return_value = fivetran_connection handler.handle( RefreshStoreRequest(fivetran_connection_id=fivetran_connection.id) ) refreshed_association = store_association_repository.first() fivetran_client_mock.sync_connection_data.assert_called() assert refreshed_association assert refreshed_association.id == association.id assert refreshed_association.synced_at == fivetran_connection.succeeded_at assert refreshed_association.status == AppConnectionStatus.PENDING @pytest.mark.db def test_refresh_store_connection_syncing( self, handler: RefreshStoreHandler, store_association_repository: StoreAssociationRepository, build_model: BuildModel, create_reporting_model: CreateReportingModel, fivetran_client_mock: mock.MagicMock, ) -> None: fivetran_connection = build_model( ShopifyConnection, status={ "setup_state": ConnectionSetupState.CONNECTED, "sync_state": ConnectionSyncState.SYNCING, "is_historical_sync": False, }, ) association = create_reporting_model( ShopifyStoreAssociation, fivetran_connector_id=fivetran_connection.id, status=AppConnectionStatus.PENDING, ) fivetran_client_mock.get_shopify_connection.return_value = fivetran_connection handler.handle( RefreshStoreRequest(fivetran_connection_id=fivetran_connection.id) ) refreshed_association = store_association_repository.first() assert refreshed_association assert refreshed_association.id == association.id assert refreshed_association.synced_at == fivetran_connection.succeeded_at assert refreshed_association.status == AppConnectionStatus.SYNCING @pytest.mark.db def test_refresh_store_synced_but_not_processed( self, handler: RefreshStoreHandler, store_association_repository: StoreAssociationRepository, build_model: BuildModel, create_reporting_model: CreateReportingModel, fivetran_client_mock: mock.MagicMock, ) -> None: fivetran_connection = build_model( ShopifyConnection, status={ "setup_state": ConnectionSetupState.CONNECTED, "sync_state": ConnectionSyncState.SCHEDULED, }, ) association = create_reporting_model( ShopifyStoreAssociation, fivetran_connector_id=fivetran_connection.id, status=AppConnectionStatus.PENDING, synced_at=datetime.datetime(2021, 1, 1, tzinfo=datetime.UTC), shop=None, ) fivetran_client_mock.get_shopify_connection.return_value = fivetran_connection handler.handle( RefreshStoreRequest(fivetran_connection_id=fivetran_connection.id) ) refreshed_association = store_association_repository.first() assert refreshed_association assert refreshed_association.id == association.id assert ( refreshed_association.status == AppConnectionStatus.WAITING_FOR_PROCESSING ) @pytest.mark.db def test_refresh_store_connection_connected_after_being_broken( self, handler: RefreshStoreHandler, store_association_repository: StoreAssociationRepository, build_model: BuildModel, create_reporting_model: CreateReportingModel, fivetran_client_mock: mock.MagicMock, ) -> None: fivetran_connection = build_model( ShopifyConnection, status={ "setup_state": ConnectionSetupState.CONNECTED, "sync_state": ConnectionSyncState.SCHEDULED, }, ) association = create_reporting_model( ShopifyStoreAssociation, fivetran_connector_id=fivetran_connection.id, status=AppConnectionStatus.ERROR, synced_at=datetime.datetime(2021, 1, 1, tzinfo=datetime.UTC), ) fivetran_client_mock.get_shopify_connection.return_value = fivetran_connection handler.handle( RefreshStoreRequest(fivetran_connection_id=fivetran_connection.id) ) refreshed_association = store_association_repository.first() assert refreshed_association assert refreshed_association.id == association.id assert refreshed_association.synced_at == fivetran_connection.succeeded_at assert refreshed_association.status == AppConnectionStatus.CONNECTED @pytest.mark.db def test_refresh_store_connection_connected_synced_and_processed_store( self, handler: RefreshStoreHandler, store_association_repository: StoreAssociationRepository, build_model: BuildModel, create_reporting_model: CreateReportingModel, fivetran_client_mock: mock.MagicMock, ) -> None: fivetran_connection = build_model( ShopifyConnection, status={ "setup_state": ConnectionSetupState.CONNECTED, "sync_state": ConnectionSyncState.SCHEDULED, }, ) association = create_reporting_model( ShopifyStoreAssociation, fivetran_connector_id=fivetran_connection.id, status=AppConnectionStatus.WAITING_FOR_PROCESSING, synced_at=datetime.datetime(2021, 1, 1, tzinfo=datetime.UTC), ) fivetran_client_mock.get_shopify_connection.return_value = fivetran_connection handler.handle( RefreshStoreRequest(fivetran_connection_id=fivetran_connection.id) ) refreshed_association = store_association_repository.first() assert refreshed_association assert refreshed_association.id == association.id assert refreshed_association.synced_at == fivetran_connection.succeeded_at assert refreshed_association.status == AppConnectionStatus.CONNECTED @pytest.mark.db def test_refresh_store_connection_connected_rescheduled_not_synced_and_not_processed( self, handler: RefreshStoreHandler, store_association_repository: StoreAssociationRepository, build_model: BuildModel, create_reporting_model: CreateReportingModel, fivetran_client_mock: mock.MagicMock, ) -> None: fivetran_connection = build_model( ShopifyConnection, status={ "setup_state": ConnectionSetupState.CONNECTED, "sync_state": ConnectionSyncState.RESCHEDULED, "is_historical_sync": False, }, ) association = create_reporting_model( ShopifyStoreAssociation, fivetran_connector_id=fivetran_connection.id, status=AppConnectionStatus.SYNCING_INITIAL, synced_at=datetime.datetime(2021, 1, 1, tzinfo=datetime.UTC), ) fivetran_client_mock.get_shopify_connection.return_value = fivetran_connection handler.handle( RefreshStoreRequest(fivetran_connection_id=fivetran_connection.id) ) refreshed_association = store_association_repository.first() assert refreshed_association assert refreshed_association.id == association.id assert refreshed_association.synced_at == fivetran_connection.succeeded_at assert refreshed_association.status == AppConnectionStatus.SYNCING