"""Test for subscriptions logic.""" from unittest.mock import call, patch import pytest from owsresponse import response from notifications.api import app from notifications.logic import subscriptions from notifications.models import subscriptions as subscriptions_model @pytest.mark.parametrize( ( 'exists_response', 'exists_deleted_response', 'create_response', 'update_response', 'expect_response', ), [ # no edge ever existed, create one (404, 404, 201, None, 201), # deleted edge exists, undeleted it (404, 200, None, 204, 204), # active edge exists, do nothing (200, None, None, None, 200), ], ) def test_create_subscription( mocker, app_context, exists_response, exists_deleted_response, create_response, update_response, expect_response, ): """Test create brand new subscription.""" has_mock = mocker.patch.object( subscriptions_model, 'has_subscription', return_value=response.Response(status=exists_response), ) has_deleted_mock = mocker.patch.object( subscriptions_model, 'has_deleted_subscription', return_value=response.Response(status=exists_deleted_response), ) create_mock = mocker.patch.object( subscriptions_model, 'create_subscription', return_value=response.Response(status=create_response), ) update_mock = mocker.patch.object( subscriptions_model, 'soft_undelete_subscription', return_value=response.Response(status=update_response), ) with app.test_request_context(): profile_type = 'InsightsProfile' profile_id = 555 entity_type = 'GlobalParticipant' entity_id = 'abcd' relationship = 'HAS_FOLLOWED' logic_response = subscriptions.create_subscription( profile_type, profile_id, entity_type, entity_id, relationship, False ) assert has_mock.called == (exists_response is not None) assert has_deleted_mock.called == (exists_deleted_response is not None) assert create_mock.called == (create_response is not None) assert update_mock.called == (update_response is not None) assert logic_response.status == expect_response @pytest.mark.parametrize( ( 'exists_response', 'delete_response', 'expect_response', ), [ # subscription does not exist, do nothing (404, None, 404), # subscription exists, update graph with delete (200, 204, 204), ], ) def test_soft_delete_subscription( mocker, app_context, exists_response, delete_response, expect_response ): """Test soft_delete_subscription.""" has_mock = mocker.patch.object( subscriptions_model, 'has_subscription', return_value=response.Response(status=exists_response), ) delete_mock = mocker.patch.object( subscriptions_model, 'soft_delete_subscription', return_value=response.Response(status=delete_response), ) with app.test_request_context(): profile_type = 'InsightsProfile' profile_id = 555 entity_type = 'GlobalParticipant' entity_id = 'abcd' relationship = 'HAS_FOLLOWED' logic_response = subscriptions.soft_delete_subscription( profile_type, profile_id, entity_type, entity_id, relationship ) assert has_mock.called == (exists_response is not None) assert delete_mock.called == (delete_response is not None) assert logic_response.status == delete_response if delete_response else exists_response @pytest.mark.parametrize(('expected_response_status'), [(200), (404)]) def test_get_subscriptions(mocker, expected_response_status): """Test get_subscriptions.""" mocker.patch.object( subscriptions_model, 'get_subscriptions', return_value=response.Response(status=expected_response_status), ) with app.test_request_context(): logic_response = subscriptions.get_subscriptions( 'ArtistInsightsProfile', 555, 'GlobalParticipant', 'HAS_FOLLOWED', [] ) assert logic_response.status == expected_response_status @pytest.mark.parametrize(('expected_response_status'), [(200), (404)]) def test_get_all_subscriptions(mocker, expected_response_status): """Test get_all_subscriptions.""" mocker.patch.object( subscriptions_model, 'get_all_subscriptions', return_value=response.Response(status=expected_response_status), ) with app.test_request_context(): logic_response = subscriptions.get_all_subscriptions() assert logic_response.status == expected_response_status @pytest.mark.parametrize(('expected_response_status'), [(200), (404)]) def test_get_all_subscriptions_for_identity(mocker, expected_response_status): """Test get_all_subscriptions_for_identity.""" identity_id = 'uuid' mocker.patch.object( subscriptions_model, 'get_all_subscriptions_for_identity', return_value=response.Response(status=expected_response_status), ) with app.test_request_context(): logic_response = subscriptions.get_all_subscriptions_for_identity(identity_id) assert logic_response.status == expected_response_status @pytest.mark.parametrize(('expected_response_status'), [(200), (404)]) def test_has_subscription(mocker, expected_response_status): """Test has_subscription.""" mocker.patch.object( subscriptions_model, 'has_subscription', return_value=response.Response(status=expected_response_status), ) with app.test_request_context(): logic_response = subscriptions.has_subscription( 'ArtistInsightsProfile', 555, 'GlobalParticipant', 19, 'HAS_FOLLOWED' ) assert logic_response.status == expected_response_status def test_unsubscribe_by_notification_type(mocker, app_context): """Test unsubscribe_by_notification_type.""" mocker.patch.object( subscriptions_model, 'soft_delete_notification_subscription', return_value=response.Response(status=204), ) with app.test_request_context(): logic_response = subscriptions.unsubscribe_by_notification_type( 'ArtistInsightsProfile', 555, 'push_notifications', 'social_spike', 'GlobalParticipant' ) assert logic_response.status == 204 @pytest.mark.parametrize( ('follow_all_resources', 'follow_resources', 'expected_message'), [ ( # auto follow all labels True, None, {'edit': 'called'}, ), ( # follow specific labels False, ['vendor-uuid'], {'edit': 'called'}, ), ( # toggle off False, [], {'delete': 'called'}, ), ], ) def test_edit_subscription_for_identity( follow_all_resources, follow_resources, expected_message, mocker ): """Test edit_subscription_for_identity.""" mocker.patch.object( subscriptions_model, 'get_subscription_by_param', return_value=response.Response({'appId': 'workstation'}), ) mocker.patch.object( subscriptions_model, 'edit_subscription_for_identity', return_value=response.Response({'edit': 'called'}), ) mocker.patch.object( subscriptions_model, 'delete_subscription_for_identity', return_value=response.Response({'delete': 'called'}), ) with app.test_request_context(): logic_response = subscriptions.edit_subscription_for_identity( 'identity_id', 'approval', follow_all_resources, follow_resources ) assert logic_response assert logic_response.message == expected_message @pytest.mark.parametrize( ( 'has_notification_subscription_response_status', 'has_deleted_response_status', 'undelete', 'expected_response_status', ), [ (404, 404, True, 201), (404, 200, True, 201), (404, 200, False, 409), (200, None, True, 200), ], ) def test_create_notification_subscription_logic( mocker, app_context, has_notification_subscription_response_status, has_deleted_response_status, undelete, expected_response_status, ): """Test create_notification_subscription.""" patched_query = mocker.patch.object(subscriptions_model, 'has_notification_subscription') patched_query.side_effect = [ response.Response(status=has_notification_subscription_response_status), response.Response(status=has_deleted_response_status), ] mocker.patch.object( subscriptions_model, 'soft_undelete_notification_subscription', return_value=response.Response(status=expected_response_status), ) mocker.patch.object( subscriptions_model, 'create_notification_subscription', return_value=response.Response(status=expected_response_status), ) with app.test_request_context(): logic_response = subscriptions.subscribe_by_notification_type( 'InsightsProfile', 555, 'push_notifications', 'social_spike', 'GlobalParticipant', undelete, ) assert logic_response.status == expected_response_status @patch('notifications.models.subscriptions.fetch_ids') def test_resolve_node_id(mock_model): """Test pass through node id resolve method.""" subscriptions.resolve_node_ids('GlobalSoundRecording', 'isrc', 'xyz') assert mock_model.call_args_list == [call('GlobalSoundRecording', 'isrc', 'xyz')]