mirror of
https://github.com/GSA/notifications-api.git
synced 2026-08-05 22:20:49 -04:00
Merge branch 'master' into caching-with-redis
Conflicts: app/__init__.py
This commit is contained in:
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
|
||||
46
tests/app/v2/notifications/test_get_notifications.py
Normal file
46
tests/app/v2/notifications/test_get_notifications.py
Normal 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
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user