Merge branch 'master' into caching-with-redis

Conflicts:
	app/__init__.py
This commit is contained in:
Martyn Inglis
2016-11-23 09:12:11 +00:00
27 changed files with 364 additions and 129 deletions

View File

@@ -76,7 +76,7 @@ def test_should_process_sms_job(sample_job, mocker):
(str(sample_job.service_id),
"uuid",
"something_encrypted",
"2016-01-01T11:09:00.061258"),
"2016-01-01T11:09:00.061258Z"),
queue="db-sms"
)
job = jobs_dao.dao_get_job_by_id(sample_job.id)
@@ -104,7 +104,7 @@ def test_should_process_sms_job_into_research_mode_queue_if_research_mode_servic
(str(job.service_id),
"uuid",
"something_encrypted",
"2016-01-01T11:09:00.061258"),
"2016-01-01T11:09:00.061258Z"),
queue="research-mode"
)
@@ -133,7 +133,7 @@ def test_should_process_email_job_into_research_mode_queue_if_research_mode_serv
(str(job.service_id),
"uuid",
"something_encrypted",
"2016-01-01T11:09:00.061258"),
"2016-01-01T11:09:00.061258Z"),
queue="research-mode"
)
@@ -252,7 +252,7 @@ def test_should_process_email_job_if_exactly_on_send_limits(notify_db,
str(job.service_id),
"uuid",
"something_encrypted",
"2016-01-01T11:09:00.061258"
"2016-01-01T11:09:00.061258Z"
),
queue="db-email"
)
@@ -294,7 +294,7 @@ def test_should_process_email_job(sample_email_job, mocker):
str(sample_email_job.service_id),
"uuid",
"something_encrypted",
"2016-01-01T11:09:00.061258"
"2016-01-01T11:09:00.061258Z"
),
queue="db-email"
)

View File

@@ -29,6 +29,7 @@ from app.dao.api_key_dao import save_model_api_key
from app.dao.jobs_dao import dao_create_job
from app.dao.notifications_dao import dao_create_notification
from app.dao.invited_user_dao import save_invited_user
from app.dao.provider_rates_dao import create_provider_rates
from app.clients.sms.firetext import FiretextClient
@@ -409,7 +410,8 @@ def sample_notification(notify_db,
create=True,
personalisation=None,
api_key_id=None,
key_type=KEY_TYPE_NORMAL):
key_type=KEY_TYPE_NORMAL,
sent_by=None):
if created_at is None:
created_at = datetime.utcnow()
if service is None:
@@ -441,7 +443,8 @@ def sample_notification(notify_db,
'personalisation': personalisation,
'notification_type': template.template_type,
'api_key_id': api_key_id,
'key_type': key_type
'key_type': key_type,
'sent_by': sent_by
}
if job_row_number:
data['job_row_number'] = job_row_number
@@ -841,3 +844,12 @@ def sample_service_whitelist(notify_db, notify_db_session, service=None, email_a
notify_db.session.add(whitelisted_user)
notify_db.session.commit()
return whitelisted_user
@pytest.fixture(scope='function')
def sample_provider_rate(notify_db, notify_db_session, valid_from=None, rate=None, provider_identifier=None):
create_provider_rates(
provider_identifier=provider_identifier if provider_identifier is not None else 'mmg',
valid_from=valid_from if valid_from is not None else datetime.utcnow(),
rate=rate if rate is not None else 1,
)

View File

@@ -55,7 +55,7 @@ def test_create_invited_user(notify_api, sample_service, mocker, invitation_emai
(str(current_app.config['NOTIFY_SERVICE_ID']),
'some_uuid',
encryption.encrypt(message),
"2016-01-01T11:09:00.061258"),
"2016-01-01T11:09:00.061258Z"),
queue="notify")

View File

@@ -2,15 +2,25 @@ import os
from flask import json
import jsonschema
from jsonschema import Draft4Validator
def validate(json_string, schema_filename):
schema_dir = os.path.join(os.path.dirname(__file__), 'schemas')
def return_json_from_response(response):
return json.loads(response.get_data(as_text=True))
def validate_v0(json_to_validate, schema_filename):
schema_dir = os.path.join(os.path.dirname(__file__), 'schemas/v0')
resolver = jsonschema.RefResolver('file://' + schema_dir + '/', None)
with open(os.path.join(schema_dir, schema_filename)) as schema:
jsonschema.validate(
json.loads(json_string),
json_to_validate,
json.load(schema),
format_checker=jsonschema.FormatChecker(),
resolver=resolver
)
def validate(json_to_validate, schema):
validator = Draft4Validator(schema)
validator.validate(json_to_validate, schema)

View File

@@ -1,59 +1,65 @@
from . import validate
from . import return_json_from_response, validate_v0, validate
from app.models import ApiKey, KEY_TYPE_NORMAL
from app.dao.notifications_dao import dao_update_notification
from app.dao.api_key_dao import save_model_api_key
from app.v2.notifications.notification_schemas import get_notification_response
from tests import create_authorization_header
def test_get_api_sms_contract(client, sample_notification):
api_key = ApiKey(service=sample_notification.service,
name='api_key',
created_by=sample_notification.service.created_by,
key_type=KEY_TYPE_NORMAL)
save_model_api_key(api_key)
sample_notification.job = None
sample_notification.api_key = api_key
sample_notification.key_type = KEY_TYPE_NORMAL
dao_update_notification(sample_notification)
auth_header = create_authorization_header(service_id=sample_notification.service_id)
response = client.get('/notifications/{}'.format(sample_notification.id), headers=[auth_header])
def _get_notification(client, notification, url):
save_model_api_key(ApiKey(
service=notification.service,
name='api_key',
created_by=notification.service.created_by,
key_type=KEY_TYPE_NORMAL
))
auth_header = create_authorization_header(service_id=notification.service_id)
return client.get(url, headers=[auth_header])
validate(response.get_data(as_text=True), 'GET_notification_return_sms.json')
def test_get_v2_sms_contract(client, sample_notification):
response_json = return_json_from_response(_get_notification(
client, sample_notification, '/v2/notifications/{}'.format(sample_notification.id)
))
validate(response_json, get_notification_response)
def test_get_v2_email_contract(client, sample_email_notification):
response_json = return_json_from_response(_get_notification(
client, sample_email_notification, '/v2/notifications/{}'.format(sample_email_notification.id)
))
validate(response_json, get_notification_response)
def test_get_api_sms_contract(client, sample_notification):
response_json = return_json_from_response(_get_notification(
client, sample_notification, '/notifications/{}'.format(sample_notification.id)
))
validate_v0(response_json, 'GET_notification_return_sms.json')
def test_get_api_email_contract(client, sample_email_notification):
api_key = ApiKey(service=sample_email_notification.service,
name='api_key',
created_by=sample_email_notification.service.created_by,
key_type=KEY_TYPE_NORMAL)
save_model_api_key(api_key)
sample_email_notification.job = None
sample_email_notification.api_key = api_key
sample_email_notification.key_type = KEY_TYPE_NORMAL
dao_update_notification(sample_email_notification)
auth_header = create_authorization_header(service_id=sample_email_notification.service_id)
response = client.get('/notifications/{}'.format(sample_email_notification.id), headers=[auth_header])
validate(response.get_data(as_text=True), 'GET_notification_return_email.json')
response_json = return_json_from_response(_get_notification(
client, sample_email_notification, '/notifications/{}'.format(sample_email_notification.id)
))
validate_v0(response_json, 'GET_notification_return_email.json')
def test_get_job_sms_contract(client, sample_notification):
auth_header = create_authorization_header(service_id=sample_notification.service_id)
response = client.get('/notifications/{}'.format(sample_notification.id), headers=[auth_header])
validate(response.get_data(as_text=True), 'GET_notification_return_sms.json')
response_json = return_json_from_response(_get_notification(
client, sample_notification, '/notifications/{}'.format(sample_notification.id)
))
validate_v0(response_json, 'GET_notification_return_sms.json')
def test_get_job_email_contract(client, sample_email_notification):
auth_header = create_authorization_header(service_id=sample_email_notification.service_id)
response = client.get('/notifications/{}'.format(sample_email_notification.id), headers=[auth_header])
validate(response.get_data(as_text=True), 'GET_notification_return_email.json')
response_json = return_json_from_response(_get_notification(
client, sample_email_notification, '/notifications/{}'.format(sample_email_notification.id)
))
validate_v0(response_json, 'GET_notification_return_email.json')
def test_get_notifications_contract(client, sample_notification, sample_email_notification):
auth_header = create_authorization_header(service_id=sample_notification.service_id)
response = client.get('/notifications', headers=[auth_header])
validate(response.get_data(as_text=True), 'GET_notifications_return.json')
response_json = return_json_from_response(_get_notification(
client, sample_notification, '/notifications'
))
validate_v0(response_json, 'GET_notifications_return.json')

View File

@@ -1,44 +1,39 @@
from flask import json
from . import validate
from . import return_json_from_response, validate_v0
from tests import create_authorization_header
def _post_notification(client, template, url, to):
data = {
'to': to,
'template': str(template.id)
}
auth_header = create_authorization_header(service_id=template.service_id)
return client.post(
path=url,
data=json.dumps(data),
headers=[('Content-Type', 'application/json'), auth_header]
)
def test_post_sms_contract(client, mocker, sample_template):
mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
mocker.patch('app.encryption.encrypt', return_value="something_encrypted")
data = {
'to': '07700 900 855',
'template': str(sample_template.id)
}
auth_header = create_authorization_header(service_id=sample_template.service_id)
response = client.post(
path='/notifications/sms',
data=json.dumps(data),
headers=[('Content-Type', 'application/json'), auth_header]
)
validate(response.get_data(as_text=True), 'POST_notification_return_sms.json')
response_json = return_json_from_response(_post_notification(
client, sample_template, url='/notifications/sms', to='07700 900 855'
))
validate_v0(response_json, 'POST_notification_return_sms.json')
def test_post_email_contract(client, mocker, sample_email_template):
mocker.patch('app.celery.provider_tasks.deliver_email.apply_async')
mocker.patch('app.encryption.encrypt', return_value="something_encrypted")
data = {
'to': 'foo@bar.com',
'template': str(sample_email_template.id)
}
auth_header = create_authorization_header(service_id=sample_email_template.service_id)
response = client.post(
path='/notifications/email',
data=json.dumps(data),
headers=[('Content-Type', 'application/json'), auth_header]
)
validate(response.get_data(as_text=True), 'POST_notification_return_email.json')
response_json = return_json_from_response(_post_notification(
client, sample_email_template, url='/notifications/email', to='foo@bar.com'
))
validate_v0(response_json, 'POST_notification_return_email.json')

View File

@@ -1,9 +1,7 @@
import uuid
import pytest
from datetime import datetime
import pytest
from app import DATETIME_FORMAT
from tests.app.conftest import sample_notification, sample_provider_rate
from app.models import (
Notification,
ServiceWhitelist,
@@ -37,3 +35,29 @@ def test_should_build_service_whitelist_from_email_address(email_address):
def test_should_not_build_service_whitelist_from_invalid_contact(recipient_type, contact):
with pytest.raises(ValueError):
ServiceWhitelist.from_string('service_id', recipient_type, contact)
@pytest.mark.parametrize('provider, billable_units, expected_cost', [
('mmg', 1, 3.5),
('firetext', 2, 5),
('ses', 0, 0)
])
def test_calculate_cost_from_notification_billable_units(
notify_db, notify_db_session, provider, billable_units, expected_cost
):
provider_rates = [
('mmg', datetime(2016, 7, 1), 1.5),
('firetext', datetime(2016, 7, 1), 2.5),
('mmg', datetime.utcnow(), 3.5),
]
for provider_identifier, valid_from, rate in provider_rates:
sample_provider_rate(
notify_db,
notify_db_session,
provider_identifier=provider_identifier,
valid_from=valid_from,
rate=rate
)
notification = sample_notification(notify_db, notify_db_session, billable_units=billable_units, sent_by=provider)
assert notification.cost() == expected_cost

View File

@@ -445,7 +445,7 @@ def test_send_user_reset_password_should_send_reset_password_link(notify_api,
[str(current_app.config['NOTIFY_SERVICE_ID']),
'some_uuid',
app.encryption.encrypt(message),
"2016-01-01T11:09:00.061258"],
"2016-01-01T11:09:00.061258Z"],
queue="notify")
@@ -525,7 +525,7 @@ def test_send_already_registered_email(notify_api, sample_user, already_register
(str(current_app.config['NOTIFY_SERVICE_ID']),
'some_uuid',
app.encryption.encrypt(message),
"2016-01-01T11:09:00.061258"),
"2016-01-01T11:09:00.061258Z"),
queue="notify")
@@ -573,7 +573,7 @@ def test_send_user_confirm_new_email_returns_204(notify_api, sample_user, change
str(current_app.config['NOTIFY_SERVICE_ID']),
"some_uuid",
app.encryption.encrypt(message),
"2016-01-01T11:09:00.061258"), queue="notify")
"2016-01-01T11:09:00.061258Z"), queue="notify")
def test_send_user_confirm_new_email_returns_400_when_email_missing(notify_api, sample_user, mocker):

View File

@@ -248,7 +248,7 @@ def test_send_user_sms_code(notify_api,
([current_app.config['NOTIFY_SERVICE_ID'],
"some_uuid",
encrypted,
"2016-01-01T11:09:00.061258"]),
"2016-01-01T11:09:00.061258Z"]),
queue="notify"
)
@@ -288,7 +288,7 @@ def test_send_user_code_for_sms_with_optional_to_field(notify_api,
([current_app.config['NOTIFY_SERVICE_ID'],
"some_uuid",
encrypted,
"2016-01-01T11:09:00.061258"]),
"2016-01-01T11:09:00.061258Z"]),
queue="notify"
)
@@ -343,7 +343,7 @@ def test_send_user_email_verification(notify_api,
(str(current_app.config['NOTIFY_SERVICE_ID']),
'some_uuid',
encryption.encrypt(message),
"2016-01-01T11:09:00.061258"),
"2016-01-01T11:09:00.061258Z"),
queue="notify")

View File

@@ -0,0 +1,46 @@
import json
from app import DATETIME_FORMAT
from tests import create_authorization_header
def test_get_notification_by_id_returns_200(client, sample_notification):
auth_header = create_authorization_header(service_id=sample_notification.service_id)
response = client.get(
path='/v2/notifications/{}'.format(sample_notification.id),
headers=[('Content-Type', 'application/json'), auth_header])
assert response.status_code == 200
assert response.headers['Content-type'] == 'application/json'
json_response = json.loads(response.get_data(as_text=True))
expected_template_response = {
'id': '{}'.format(sample_notification.serialize()['template']['id']),
'version': sample_notification.serialize()['template']['version'],
'uri': sample_notification.serialize()['template']['uri']
}
expected_response = {
'id': '{}'.format(sample_notification.id),
'reference': None,
'email_address': None,
'phone_number': '{}'.format(sample_notification.to),
'line_1': None,
'line_2': None,
'line_3': None,
'line_4': None,
'line_5': None,
'line_6': None,
'postcode': None,
'cost': sample_notification.cost(),
'type': '{}'.format(sample_notification.notification_type),
'status': '{}'.format(sample_notification.status),
'template': expected_template_response,
'created_at': sample_notification.created_at.strftime(DATETIME_FORMAT),
'sent_at': sample_notification.sent_at,
'completed_at': sample_notification.completed_at()
}
assert json_response == expected_response

View File

@@ -3,10 +3,10 @@ import uuid
import pytest
from flask import json
from jsonschema import ValidationError
from notifications_utils.recipients import InvalidPhoneError, InvalidEmailError
from app.v2.notifications.notification_schemas import post_sms_request, post_sms_response, post_email_request, \
post_email_response
from app.v2.notifications.notification_schemas import (
post_sms_request, post_sms_response, post_email_request, post_email_response
)
from app.schema_validation import validate
valid_json = {"phone_number": "07515111111",

View File

@@ -6,15 +6,17 @@ from app.models import Notification
from tests import create_authorization_header
def test_post_sms_notification_returns_201(notify_api, sample_template, mocker):
@pytest.mark.parametrize("reference", [None, "reference_from_client"])
def test_post_sms_notification_returns_201(notify_api, sample_template, mocker, reference):
with notify_api.test_request_context():
with notify_api.test_client() as client:
mocked = mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
data = {
'phone_number': '+447700900855',
'template_id': str(sample_template.id),
'reference': 'reference_from_client'
'template_id': str(sample_template.id)
}
if reference:
data.update({"reference": reference})
auth_header = create_authorization_header(service_id=sample_template.service_id)
response = client.post(
@@ -27,8 +29,8 @@ def test_post_sms_notification_returns_201(notify_api, sample_template, mocker):
notifications = Notification.query.all()
assert len(notifications) == 1
notification_id = notifications[0].id
assert resp_json['id'] is not None
assert resp_json['reference'] == 'reference_from_client'
assert resp_json['id'] == str(notification_id)
assert resp_json['reference'] == reference
assert resp_json['content']['body'] == sample_template.content
assert resp_json['content']['from_number'] == sample_template.service.sms_sender
assert 'v2/notifications/{}'.format(notification_id) in resp_json['uri']
@@ -105,13 +107,15 @@ def test_post_sms_notification_returns_400_and_for_schema_problems(notify_api, s
}]
def test_post_email_notification_returns_201(client, sample_email_template, mocker):
@pytest.mark.parametrize("reference", [None, "reference_from_client"])
def test_post_email_notification_returns_201(client, sample_email_template, mocker, reference):
mocked = mocker.patch('app.celery.provider_tasks.deliver_email.apply_async')
data = {
"reference": "reference from caller",
"email_address": sample_email_template.service.users[0].email_address,
"template_id": sample_email_template.id,
}
if reference:
data.update({"reference": reference})
auth_header = create_authorization_header(service_id=sample_email_template.service_id)
response = client.post(
path="v2/notifications/email",
@@ -121,7 +125,7 @@ def test_post_email_notification_returns_201(client, sample_email_template, mock
resp_json = json.loads(response.get_data(as_text=True))
notification = Notification.query.first()
assert resp_json['id'] == str(notification.id)
assert resp_json['reference'] == "reference from caller"
assert resp_json['reference'] == reference
assert notification.reference is None
assert resp_json['content']['body'] == sample_email_template.content
assert resp_json['content']['subject'] == sample_email_template.subject