From dbc57e3b583e38f5f593b950a0371e923344d039 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Fri, 3 Jun 2016 15:15:46 +0100 Subject: [PATCH 1/2] [WIP] use send_sms task to send sms code. Tests are broken because the template data for the Notify service is being delete after every test. Need a way to seed the data for the test. --- app/user/rest.py | 31 ++++++++++++------ tests/app/user/test_rest_verify.py | 50 ++++++++++++++++++++++-------- 2 files changed, 58 insertions(+), 23 deletions(-) diff --git a/app/user/rest.py b/app/user/rest.py index 2d46d2d7a..1850c1c04 100644 --- a/app/user/rest.py +++ b/app/user/rest.py @@ -1,8 +1,8 @@ import json +import uuid from datetime import datetime from flask import (jsonify, request, abort, Blueprint, current_app) -from app import encryption - +from app import encryption, DATETIME_FORMAT from app.dao.users_dao import ( get_model_users, save_model_user, @@ -11,12 +11,12 @@ from app.dao.users_dao import ( use_user_code, increment_failed_login_count, reset_failed_login_count, - get_user_by_email + get_user_by_email, + create_secret_code ) - from app.dao.permissions_dao import permission_dao from app.dao.services_dao import dao_fetch_service_by_id - +from app.dao.templates_dao import dao_get_template_by_id from app.schemas import ( email_data_request_schema, user_schema, @@ -26,7 +26,7 @@ from app.schemas import ( ) from app.celery.tasks import ( - send_sms_code, + send_sms, email_reset_password, email_registration_verification ) @@ -123,14 +123,26 @@ def send_user_sms_code(user_id): if errors: return jsonify(result="error", message=errors), 400 - from app.dao.users_dao import create_secret_code secret_code = create_secret_code() create_user_code(user_to_send_to, secret_code, 'sms') mobile = user_to_send_to.mobile_number if verify_code.get('to', None) is None else verify_code.get('to') - verification_message = {'to': mobile, 'secret_code': secret_code} + sms_code_template_id = current_app.config['SMS_CODE_TEMPLATE_ID'] + sms_code_template = dao_get_template_by_id(sms_code_template_id) + verification_message = encryption.encrypt({ + 'template': sms_code_template_id, + 'template_version': sms_code_template.version, + 'to': mobile, + 'personalisation': { + 'verify_code': secret_code + } - send_sms_code.apply_async([encryption.encrypt(verification_message)], queue='sms-code') + }) + send_sms.apply_async([current_app.config['NOTIFY_SERVICE_ID'], + str(uuid.uuid4()), + verification_message, + datetime.utcnow().strftime(DATETIME_FORMAT) + ], queue='sms-code') return jsonify({}), 204 @@ -142,7 +154,6 @@ def send_user_email_verification(user_id): if errors: return jsonify(result="error", message=errors), 400 - from app.dao.users_dao import create_secret_code secret_code = create_secret_code() create_user_code(user_to_send_to, secret_code, 'email') diff --git a/tests/app/user/test_rest_verify.py b/tests/app/user/test_rest_verify.py index c426a3469..b437aee3c 100644 --- a/tests/app/user/test_rest_verify.py +++ b/tests/app/user/test_rest_verify.py @@ -6,8 +6,7 @@ from datetime import ( timedelta ) -from flask import url_for - +from flask import url_for, current_app from app.models import ( VerifyCode, User @@ -215,10 +214,13 @@ def test_user_verify_password_missing_password(notify_api, assert 'Required field missing data' in json_resp['message']['password'] +@freeze_time("2016-01-01 11:09:00.061258") def test_send_user_sms_code(notify_api, - sample_sms_code, - mock_celery_send_sms_code, - mock_encryption): + notify_db, + notify_db_session, + sample_user, + mock_encryption, + mocker): """ Tests POST endpoint /user//sms-code """ @@ -226,34 +228,56 @@ def test_send_user_sms_code(notify_api, with notify_api.test_client() as client: data = json.dumps({}) auth_header = create_authorization_header() + mocker.patch('app.celery.tasks.send_sms.apply_async') + mocker.patch('uuid.uuid4', return_value='some_uuid') # for the notification id resp = client.post( - url_for('user.send_user_sms_code', user_id=sample_sms_code.user.id), + url_for('user.send_user_sms_code', user_id=sample_user.id), data=data, headers=[('Content-Type', 'application/json'), auth_header]) assert resp.status_code == 204 - app.celery.tasks.send_sms_code.apply_async.assert_called_once_with(['something_encrypted'], - queue='sms-code') + app.celery.tasks.send_sms.apply_async.assert_called_once_with( + ([current_app.config['NOTIFY_SERVICE_ID'], + "some_uuid", + "something_encrypted", + "2016-01-01T11:09:00.061258"]), + queue="sms-code" + ) +@freeze_time("2016-01-01 11:09:00.061258") def test_send_user_code_for_sms_with_optional_to_field(notify_api, - sample_sms_code, + sample_user, mock_secret_code, - mock_celery_send_sms_code): + mocker): """ Tests POST endpoint '//code' successful sms with optional to field """ with notify_api.test_request_context(): with notify_api.test_client() as client: + mocker.patch('app.celery.tasks.send_sms.apply_async') + mocker.patch('uuid.uuid4', return_value='some_uuid') # for the notification id data = json.dumps({'to': '+441119876757'}) auth_header = create_authorization_header() resp = client.post( - url_for('user.send_user_sms_code', user_id=sample_sms_code.user.id), + url_for('user.send_user_sms_code', user_id=sample_user.id), data=data, headers=[('Content-Type', 'application/json'), auth_header]) assert resp.status_code == 204 - encrypted = encryption.encrypt({'to': '+441119876757', 'secret_code': '11111'}) - app.celery.tasks.send_sms_code.apply_async.assert_called_once_with([encrypted], queue='sms-code') + encrypted = encryption.encrypt({'template': current_app.config['SMS_CODE_TEMPLATE_ID'], + 'template_version': 1, + 'to': '+441119876757', + 'personalisation': { + 'verify_code': '11111' + } + }) + app.celery.tasks.send_sms.apply_async.assert_called_once_with( + ([current_app.config['NOTIFY_SERVICE_ID'], + "some_uuid", + encrypted, + "2016-01-01T11:09:00.061258"]), + queue="sms-code" + ) def test_send_sms_code_returns_404_for_bad_input_data(notify_api, notify_db, notify_db_session): From be9fde1420f7e8c46318c1f204d19f183cdba53d Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Mon, 6 Jun 2016 11:51:12 +0100 Subject: [PATCH 2/2] Fix tests for sending sms codes. Since the unit tests delete the data in between tests I need to add the template data for the test for send sms code. --- tests/app/conftest.py | 44 ++++++++++++++++++++++++------ tests/app/user/test_rest_verify.py | 27 ++++++++++++------ 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/tests/app/conftest.py b/tests/app/conftest.py index 8dc6cae4b..27ef72278 100644 --- a/tests/app/conftest.py +++ b/tests/app/conftest.py @@ -4,6 +4,7 @@ import uuid from datetime import (datetime, date) import pytest +from flask import current_app from app import db from app.models import ( @@ -307,15 +308,6 @@ def sample_email_job(notify_db, return job -@pytest.fixture(scope='function') -def mock_secret_code(mocker): - def _create(): - return '11111' - - mock_class = mocker.patch('app.dao.users_dao.create_secret_code', side_effect=_create) - return mock_class - - @pytest.fixture(scope='function') def sample_notification(notify_db, notify_db_session, @@ -563,3 +555,37 @@ def mock_mmg_client(mocker, statsd_client=None): }) client.init_app(current_app, statsd_client) return client + + +@pytest.fixture(scope='function') +def sms_code_template(notify_db, + notify_db_session): + user = sample_user(notify_db, notify_db_session) + service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID']) + if not service: + data = { + 'id': current_app.config['NOTIFY_SERVICE_ID'], + 'name': 'Notify Service', + 'message_limit': 1000, + 'active': True, + 'restricted': False, + 'email_from': 'notify.service', + 'created_by': user + } + service = Service(**data) + db.session.add(service) + + template = Template.query.get(current_app.config['SMS_CODE_TEMPLATE_ID']) + if not template: + data = { + 'id': current_app.config['SMS_CODE_TEMPLATE_ID'], + 'name': 'Sms code template', + 'template_type': 'sms', + 'content': '((verify_code))', + 'service': service, + 'created_by': user, + 'archived': False + } + template = Template(**data) + db.session.add(template) + return template diff --git a/tests/app/user/test_rest_verify.py b/tests/app/user/test_rest_verify.py index b437aee3c..3ca379171 100644 --- a/tests/app/user/test_rest_verify.py +++ b/tests/app/user/test_rest_verify.py @@ -216,18 +216,18 @@ def test_user_verify_password_missing_password(notify_api, @freeze_time("2016-01-01 11:09:00.061258") def test_send_user_sms_code(notify_api, - notify_db, - notify_db_session, sample_user, - mock_encryption, + sms_code_template, mocker): """ Tests POST endpoint /user//sms-code """ + with notify_api.test_request_context(): with notify_api.test_client() as client: data = json.dumps({}) auth_header = create_authorization_header() + mocked = mocker.patch('app.user.rest.create_secret_code', return_value='11111') mocker.patch('app.celery.tasks.send_sms.apply_async') mocker.patch('uuid.uuid4', return_value='some_uuid') # for the notification id resp = client.post( @@ -235,10 +235,18 @@ def test_send_user_sms_code(notify_api, data=data, headers=[('Content-Type', 'application/json'), auth_header]) assert resp.status_code == 204 + assert mocked.call_count == 1 + encrypted = encryption.encrypt({'template': current_app.config['SMS_CODE_TEMPLATE_ID'], + 'template_version': 1, + 'to': sample_user.mobile_number, + 'personalisation': { + 'verify_code': '11111' + } + }) app.celery.tasks.send_sms.apply_async.assert_called_once_with( ([current_app.config['NOTIFY_SERVICE_ID'], "some_uuid", - "something_encrypted", + encrypted, "2016-01-01T11:09:00.061258"]), queue="sms-code" ) @@ -247,15 +255,17 @@ def test_send_user_sms_code(notify_api, @freeze_time("2016-01-01 11:09:00.061258") def test_send_user_code_for_sms_with_optional_to_field(notify_api, sample_user, - mock_secret_code, + sms_code_template, + mock_encryption, mocker): """ - Tests POST endpoint '//code' successful sms with optional to field - """ + Tests POST endpoint '//code' successful sms with optional to field + """ with notify_api.test_request_context(): with notify_api.test_client() as client: - mocker.patch('app.celery.tasks.send_sms.apply_async') + mocked = mocker.patch('app.user.rest.create_secret_code', return_value='11111') mocker.patch('uuid.uuid4', return_value='some_uuid') # for the notification id + mocker.patch('app.celery.tasks.send_sms.apply_async') data = json.dumps({'to': '+441119876757'}) auth_header = create_authorization_header() resp = client.post( @@ -271,6 +281,7 @@ def test_send_user_code_for_sms_with_optional_to_field(notify_api, 'verify_code': '11111' } }) + assert mocked.call_count == 1 app.celery.tasks.send_sms.apply_async.assert_called_once_with( ([current_app.config['NOTIFY_SERVICE_ID'], "some_uuid",