diff --git a/ckanext/dataset_subscriptions/tests/actions/test_phone_notifications.py b/ckanext/dataset_subscriptions/tests/actions/test_phone_notifications.py index a635bf1..af80cf2 100644 --- a/ckanext/dataset_subscriptions/tests/actions/test_phone_notifications.py +++ b/ckanext/dataset_subscriptions/tests/actions/test_phone_notifications.py @@ -4,14 +4,26 @@ from ckanext.dataset_subscriptions.tests import factories from ckanext.dataset_subscriptions.actions import phone_notifications from unittest import mock +import re + + +# Whatsapp messages must conform to preapproved templates created in Twilio. +# Copy templates here as a regex replacing placeholders e.g. {{1}} with (.*) +WHATSAPP_MESSAGE_TEMPLATES = [ + r"(.*) datasets that you are following have recently been updated in (.*)", + r"(.*) dataset that you are following has recently been updated in (.*)" +] + + +def _matches_whatsapp_template(message): + for template in WHATSAPP_MESSAGE_TEMPLATES: + if re.compile(template).search(message): + return True + return False @pytest.mark.ckan_config('ckan.plugins') -@pytest.mark.usefixtures("with_plugins") -@pytest.mark.usefixtures("clean_db") -def create_user_with_resources(with_activity, - sms_notifications_enabled, - whatsapp_notifications_enabled): +def create_user_with_resources(with_activity, sms_notifications_enabled, whatsapp_notifications_enabled): subscribed_user = factories.User( name='user1', activity_streams_sms_notifications=sms_notifications_enabled, @@ -36,46 +48,50 @@ def create_user_with_resources(with_activity, **dataset ) ckan_factories.Resource( - package_id=dataset['id'], - user=active_user + package_id=dataset['id'], + user=active_user ) return subscribed_user -@pytest.mark.usefixtures("clean_db") -@pytest.mark.usefixtures("with_plugins") -@pytest.mark.parametrize("notifications_enabled", [(False), (True)]) -def test_sms_notifications_disabled_enabled(notifications_enabled): - user = create_user_with_resources(True, notifications_enabled, False) - notifications = phone_notifications._sms_notifications_enabled(user, {}) - assert notifications == notifications_enabled - +@pytest.mark.usefixtures("with_plugins", "clean_db") +class TestPhoneNotifications(): -@pytest.mark.usefixtures("with_request_context") -@pytest.mark.usefixtures("clean_db") -@pytest.mark.usefixtures("with_plugins") -@mock.patch('ckanext.dataset_subscriptions.actions.phone_notifications.client.messages.create') -def test_if_sms_notifications_are_generated(create_message_mock, sysadmin_context): - create_user_with_resources(True, True, False) - expected_sid = 'SM87105da94bff44b999e4e6eb90d8eb6a' - create_message_mock.return_value.sid = expected_sid - sid = helpers.call_action("send_phone_notifications") - assert create_message_mock.called is True - assert sid[0] == expected_sid + @pytest.mark.parametrize("notifications_enabled", [(False), (True)]) + def test_sms_notifications_disabled_enabled(self, notifications_enabled): + user = create_user_with_resources(True, notifications_enabled, False) + notifications = phone_notifications._sms_notifications_enabled(user, {}) + assert notifications == notifications_enabled + @pytest.mark.usefixtures("with_request_context") + @mock.patch('ckanext.dataset_subscriptions.actions.phone_notifications.client.messages.create') + def test_if_sms_notifications_are_generated(self, create_message_mock, sysadmin_context): + create_user_with_resources(True, True, False) + expected_sid = 'SM87105da94bff44b999e4e6eb90d8eb6a' + create_message_mock.return_value.sid = expected_sid + sid = helpers.call_action("send_phone_notifications") + assert create_message_mock.called is True + assert sid[0] == expected_sid -@pytest.mark.usefixtures("with_request_context") -@pytest.mark.usefixtures("clean_db") -@pytest.mark.usefixtures("with_plugins") -@mock.patch('ckanext.dataset_subscriptions.actions.phone_notifications.client.messages.create') -def test_if_whatsapp_notifications_are_generated(create_message_mock, sysadmin_context): - create_user_with_resources(True, False, True) - expected_sid = 'SM87105da94bff44b999e4e6eb90d8eb6a' - create_message_mock.return_value.sid = expected_sid - sid = helpers.call_action("send_phone_notifications") - assert create_message_mock.called is True - assert sid[0] == expected_sid - call_args = dict(create_message_mock.call_args.kwargs.items()) - assert 'whatsapp:+' in call_args['to'] - assert 'whatsapp:+' in call_args['from_'] + @pytest.mark.usefixtures("with_request_context") + @mock.patch('ckanext.dataset_subscriptions.actions.phone_notifications.client.messages.create') + def test_if_whatsapp_notifications_are_generated(self, create_message_mock, sysadmin_context): + create_user_with_resources(True, False, True) + expected_sid = 'SM87105da94bff44b999e4e6eb90d8eb6a' + create_message_mock.return_value.sid = expected_sid + sid = helpers.call_action("send_phone_notifications") + assert create_message_mock.called is True + assert sid[0] == expected_sid + call_args = dict(create_message_mock.call_args.kwargs.items()) + assert 'whatsapp:+' in call_args['to'] + assert 'whatsapp:+' in call_args['from_'] + assert _matches_whatsapp_template(call_args['body']) + @pytest.mark.parametrize('recent_activities', [[1], [1, 2, 3, 4]]) + def test_whatsapp_message_complies_with_templates(self, recent_activities): + """ + Whatsapp messages must comply with a template preapproved through twilio + https://www.twilio.com/docs/whatsapp/tutorial/send-whatsapp-notification-messages-templates + """ + header = phone_notifications._create_message_header(recent_activities) + assert _matches_whatsapp_template(header) diff --git a/ckanext/dataset_subscriptions/tests/actions/test_user.py b/ckanext/dataset_subscriptions/tests/actions/test_user.py index 9c13712..d136b03 100644 --- a/ckanext/dataset_subscriptions/tests/actions/test_user.py +++ b/ckanext/dataset_subscriptions/tests/actions/test_user.py @@ -58,7 +58,7 @@ def test_user_validate_plugin_extras_valid_phonenumber(self, client_mock, sysadm helpers.call_action('user_create', context=sysadmin_context, **user_dict) @pytest.mark.parametrize('phonenumber, enable_sms, enable_whatsapp, expectation', [ - ("+44712345678", False, False, nullcontext(1)), + ("", False, False, nullcontext(1)), ("", False, True, pytest.raises(toolkit.ValidationError)), ("", True, False, pytest.raises(toolkit.ValidationError)), ("", True, True, pytest.raises(toolkit.ValidationError))