mirror of
https://github.com/GSA/notifications-api.git
synced 2026-09-11 10:28:55 -04:00
+16
-3
@@ -1,3 +1,4 @@
|
|||||||
|
import uuid
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
@@ -10,6 +11,7 @@ from app.models import (
|
|||||||
JOB_STATUS_SCHEDULED, JOB_STATUS_PENDING,
|
JOB_STATUS_SCHEDULED, JOB_STATUS_PENDING,
|
||||||
LETTER_TYPE
|
LETTER_TYPE
|
||||||
)
|
)
|
||||||
|
from app.variables import LETTER_TEST_API_FILENAME
|
||||||
from app.statsd_decorators import statsd
|
from app.statsd_decorators import statsd
|
||||||
|
|
||||||
|
|
||||||
@@ -108,6 +110,8 @@ def dao_get_future_scheduled_job_by_id_and_service_id(job_id, service_id):
|
|||||||
|
|
||||||
|
|
||||||
def dao_create_job(job):
|
def dao_create_job(job):
|
||||||
|
if not job.id:
|
||||||
|
job.id = uuid.uuid4()
|
||||||
job_stats = JobStatistics(
|
job_stats = JobStatistics(
|
||||||
job_id=job.id,
|
job_id=job.id,
|
||||||
updated_at=datetime.utcnow()
|
updated_at=datetime.utcnow()
|
||||||
@@ -139,9 +143,18 @@ def dao_get_jobs_older_than_limited_by(job_types, older_than=7, limit_days=2):
|
|||||||
|
|
||||||
|
|
||||||
def dao_get_all_letter_jobs():
|
def dao_get_all_letter_jobs():
|
||||||
return db.session.query(Job).join(Job.template).filter(
|
return db.session.query(
|
||||||
Template.template_type == LETTER_TYPE
|
Job
|
||||||
).order_by(desc(Job.created_at)).all()
|
).join(
|
||||||
|
Job.template
|
||||||
|
).filter(
|
||||||
|
Template.template_type == LETTER_TYPE,
|
||||||
|
# test letter jobs (or from research mode services) are created with a different filename,
|
||||||
|
# exclude them so we don't see them on the send to CSV
|
||||||
|
Job.original_file_name != LETTER_TEST_API_FILENAME
|
||||||
|
).order_by(
|
||||||
|
desc(Job.created_at)
|
||||||
|
).all()
|
||||||
|
|
||||||
|
|
||||||
@statsd(namespace="dao")
|
@statsd(namespace="dao")
|
||||||
|
|||||||
@@ -338,7 +338,8 @@ def get_notifications_for_service(
|
|||||||
filters.append(Notification.created_at < older_than_created_at)
|
filters.append(Notification.created_at < older_than_created_at)
|
||||||
|
|
||||||
if not include_jobs or (key_type and key_type != KEY_TYPE_NORMAL):
|
if not include_jobs or (key_type and key_type != KEY_TYPE_NORMAL):
|
||||||
filters.append(Notification.job_id.is_(None))
|
# we can't say "job_id == None" here, because letters sent via the API still have a job_id :(
|
||||||
|
filters.append(Notification.api_key_id != None) # noqa
|
||||||
|
|
||||||
if key_type is not None:
|
if key_type is not None:
|
||||||
filters.append(Notification.key_type == key_type)
|
filters.append(Notification.key_type == key_type)
|
||||||
|
|||||||
@@ -207,14 +207,14 @@ def delete_service_and_all_associated_db_objects(service):
|
|||||||
_delete_commit(ProviderStatistics.query.filter_by(service=service))
|
_delete_commit(ProviderStatistics.query.filter_by(service=service))
|
||||||
_delete_commit(InvitedUser.query.filter_by(service=service))
|
_delete_commit(InvitedUser.query.filter_by(service=service))
|
||||||
_delete_commit(Permission.query.filter_by(service=service))
|
_delete_commit(Permission.query.filter_by(service=service))
|
||||||
_delete_commit(ApiKey.query.filter_by(service=service))
|
|
||||||
_delete_commit(ApiKey.get_history_model().query.filter_by(service_id=service.id))
|
|
||||||
_delete_commit(NotificationHistory.query.filter_by(service=service))
|
_delete_commit(NotificationHistory.query.filter_by(service=service))
|
||||||
_delete_commit(Notification.query.filter_by(service=service))
|
_delete_commit(Notification.query.filter_by(service=service))
|
||||||
_delete_commit(Job.query.filter_by(service=service))
|
_delete_commit(Job.query.filter_by(service=service))
|
||||||
_delete_commit(Template.query.filter_by(service=service))
|
_delete_commit(Template.query.filter_by(service=service))
|
||||||
_delete_commit(TemplateHistory.query.filter_by(service_id=service.id))
|
_delete_commit(TemplateHistory.query.filter_by(service_id=service.id))
|
||||||
_delete_commit(ServicePermission.query.filter_by(service_id=service.id))
|
_delete_commit(ServicePermission.query.filter_by(service_id=service.id))
|
||||||
|
_delete_commit(ApiKey.query.filter_by(service=service))
|
||||||
|
_delete_commit(ApiKey.get_history_model().query.filter_by(service_id=service.id))
|
||||||
|
|
||||||
verify_codes = VerifyCode.query.join(User).filter(User.id.in_([x.id for x in service.users]))
|
verify_codes = VerifyCode.query.join(User).filter(User.id.in_([x.id for x in service.users]))
|
||||||
list(map(db.session.delete, verify_codes))
|
list(map(db.session.delete, verify_codes))
|
||||||
|
|||||||
+19
-5
@@ -619,7 +619,7 @@ class JobStatus(db.Model):
|
|||||||
class Job(db.Model):
|
class Job(db.Model):
|
||||||
__tablename__ = 'jobs'
|
__tablename__ = 'jobs'
|
||||||
|
|
||||||
id = db.Column(UUID(as_uuid=True), primary_key=True)
|
id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||||
original_file_name = db.Column(db.String, nullable=False)
|
original_file_name = db.Column(db.String, nullable=False)
|
||||||
service_id = db.Column(UUID(as_uuid=True), db.ForeignKey('services.id'), index=True, unique=False, nullable=False)
|
service_id = db.Column(UUID(as_uuid=True), db.ForeignKey('services.id'), index=True, unique=False, nullable=False)
|
||||||
service = db.relationship('Service', backref=db.backref('jobs', lazy='dynamic'))
|
service = db.relationship('Service', backref=db.backref('jobs', lazy='dynamic'))
|
||||||
@@ -654,7 +654,7 @@ class Job(db.Model):
|
|||||||
unique=False,
|
unique=False,
|
||||||
nullable=True)
|
nullable=True)
|
||||||
created_by = db.relationship('User')
|
created_by = db.relationship('User')
|
||||||
created_by_id = db.Column(UUID(as_uuid=True), db.ForeignKey('users.id'), index=True, nullable=False)
|
created_by_id = db.Column(UUID(as_uuid=True), db.ForeignKey('users.id'), index=True, nullable=True)
|
||||||
scheduled_for = db.Column(
|
scheduled_for = db.Column(
|
||||||
db.DateTime,
|
db.DateTime,
|
||||||
index=True,
|
index=True,
|
||||||
@@ -891,7 +891,7 @@ class Notification(db.Model):
|
|||||||
@property
|
@property
|
||||||
def subject(self):
|
def subject(self):
|
||||||
from app.utils import get_template_instance
|
from app.utils import get_template_instance
|
||||||
if self.notification_type == EMAIL_TYPE:
|
if self.notification_type != SMS_TYPE:
|
||||||
template_object = get_template_instance(self.template.__dict__, self.personalisation)
|
template_object = get_template_instance(self.template.__dict__, self.personalisation)
|
||||||
return template_object.subject
|
return template_object.subject
|
||||||
|
|
||||||
@@ -971,10 +971,24 @@ class Notification(db.Model):
|
|||||||
"created_at": self.created_at.strftime(DATETIME_FORMAT),
|
"created_at": self.created_at.strftime(DATETIME_FORMAT),
|
||||||
"sent_at": self.sent_at.strftime(DATETIME_FORMAT) if self.sent_at else None,
|
"sent_at": self.sent_at.strftime(DATETIME_FORMAT) if self.sent_at else None,
|
||||||
"completed_at": self.completed_at(),
|
"completed_at": self.completed_at(),
|
||||||
"scheduled_for": convert_bst_to_utc(self.scheduled_notification.scheduled_for
|
"scheduled_for": (
|
||||||
).strftime(DATETIME_FORMAT) if self.scheduled_notification else None
|
convert_bst_to_utc(
|
||||||
|
self.scheduled_notification.scheduled_for
|
||||||
|
).strftime(DATETIME_FORMAT)
|
||||||
|
if self.scheduled_notification
|
||||||
|
else None
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.notification_type == LETTER_TYPE:
|
||||||
|
serialized['line_1'] = self.personalisation['address_line_1']
|
||||||
|
serialized['line_2'] = self.personalisation.get('address_line_2')
|
||||||
|
serialized['line_3'] = self.personalisation.get('address_line_3')
|
||||||
|
serialized['line_4'] = self.personalisation.get('address_line_4')
|
||||||
|
serialized['line_5'] = self.personalisation.get('address_line_5')
|
||||||
|
serialized['line_6'] = self.personalisation.get('address_line_6')
|
||||||
|
serialized['postcode'] = self.personalisation['postcode']
|
||||||
|
|
||||||
return serialized
|
return serialized
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
from app import create_random_identifier
|
||||||
|
from app.models import LETTER_TYPE, JOB_STATUS_READY_TO_SEND, Job
|
||||||
|
from app.dao.jobs_dao import dao_create_job
|
||||||
|
from app.notifications.process_notifications import persist_notification
|
||||||
|
from app.v2.errors import InvalidRequest
|
||||||
|
from app.variables import LETTER_API_FILENAME
|
||||||
|
|
||||||
|
|
||||||
|
def create_letter_api_job(template):
|
||||||
|
service = template.service
|
||||||
|
if not service.active:
|
||||||
|
raise InvalidRequest('Service {} is inactive'.format(service.id), 403)
|
||||||
|
if template.archived:
|
||||||
|
raise InvalidRequest('Template {} is deleted'.format(template.id), 400)
|
||||||
|
|
||||||
|
job = Job(
|
||||||
|
original_file_name=LETTER_API_FILENAME,
|
||||||
|
service=service,
|
||||||
|
template=template,
|
||||||
|
template_version=template.version,
|
||||||
|
notification_count=1,
|
||||||
|
job_status=JOB_STATUS_READY_TO_SEND,
|
||||||
|
created_by=None
|
||||||
|
)
|
||||||
|
dao_create_job(job)
|
||||||
|
return job
|
||||||
|
|
||||||
|
|
||||||
|
def create_letter_notification(letter_data, job, api_key):
|
||||||
|
notification = persist_notification(
|
||||||
|
template_id=job.template.id,
|
||||||
|
template_version=job.template.version,
|
||||||
|
# we only accept addresses_with_underscores from the API (from CSV we also accept dashes, spaces etc)
|
||||||
|
recipient=letter_data['personalisation']['address_line_1'],
|
||||||
|
service=job.service,
|
||||||
|
personalisation=letter_data['personalisation'],
|
||||||
|
notification_type=LETTER_TYPE,
|
||||||
|
api_key_id=api_key.id,
|
||||||
|
key_type=api_key.key_type,
|
||||||
|
job_id=job.id,
|
||||||
|
job_row_number=0,
|
||||||
|
reference=create_random_identifier(),
|
||||||
|
client_reference=letter_data.get('reference')
|
||||||
|
)
|
||||||
|
return notification
|
||||||
@@ -55,7 +55,7 @@ def persist_notification(
|
|||||||
created_by_id=None
|
created_by_id=None
|
||||||
):
|
):
|
||||||
notification_created_at = created_at or datetime.utcnow()
|
notification_created_at = created_at or datetime.utcnow()
|
||||||
if not notification_id and simulated:
|
if not notification_id:
|
||||||
notification_id = uuid.uuid4()
|
notification_id = uuid.uuid4()
|
||||||
notification = Notification(
|
notification = Notification(
|
||||||
id=notification_id,
|
id=notification_id,
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ uuid = {
|
|||||||
|
|
||||||
personalisation = {
|
personalisation = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"validationMessage": "should contain key value pairs",
|
|
||||||
"code": "1001", # yet to be implemented
|
"code": "1001", # yet to be implemented
|
||||||
"link": "link to our error documentation not yet implemented"
|
"link": "link to our error documentation not yet implemented"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ def url_with_token(data, url, config):
|
|||||||
def get_template_instance(template, values):
|
def get_template_instance(template, values):
|
||||||
from app.models import SMS_TYPE, EMAIL_TYPE, LETTER_TYPE
|
from app.models import SMS_TYPE, EMAIL_TYPE, LETTER_TYPE
|
||||||
return {
|
return {
|
||||||
SMS_TYPE: SMSMessageTemplate, EMAIL_TYPE: PlainTextEmailTemplate, LETTER_TYPE: LetterPreviewTemplate
|
SMS_TYPE: SMSMessageTemplate, EMAIL_TYPE: PlainTextEmailTemplate, LETTER_TYPE: PlainTextEmailTemplate
|
||||||
}[template['template_type']](template, values)
|
}[template['template_type']](template, values)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -29,10 +29,10 @@ class RateLimitError(InvalidRequest):
|
|||||||
|
|
||||||
|
|
||||||
class BadRequestError(InvalidRequest):
|
class BadRequestError(InvalidRequest):
|
||||||
status_code = 400
|
|
||||||
message = "An error occurred"
|
message = "An error occurred"
|
||||||
|
|
||||||
def __init__(self, fields=[], message=None):
|
def __init__(self, fields=[], message=None, status_code=400):
|
||||||
|
self.status_code = status_code
|
||||||
self.fields = fields
|
self.fields = fields
|
||||||
self.message = message if message else self.message
|
self.message = message if message else self.message
|
||||||
|
|
||||||
|
|||||||
@@ -228,7 +228,8 @@ post_letter_response = {
|
|||||||
"content": letter_content,
|
"content": letter_content,
|
||||||
"uri": {"type": "string", "format": "uri"},
|
"uri": {"type": "string", "format": "uri"},
|
||||||
"template": template,
|
"template": template,
|
||||||
"scheduled_for": {"type": ["string", "null"]}
|
# letters cannot be scheduled
|
||||||
|
"scheduled_for": {"type": "null"}
|
||||||
},
|
},
|
||||||
"required": ["id", "content", "uri", "template"]
|
"required": ["id", "content", "uri", "template"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,18 @@ from flask import request, jsonify, current_app, abort
|
|||||||
|
|
||||||
from app import api_user, authenticated_service
|
from app import api_user, authenticated_service
|
||||||
from app.config import QueueNames
|
from app.config import QueueNames
|
||||||
from app.models import SMS_TYPE, EMAIL_TYPE, LETTER_TYPE, PRIORITY
|
from app.dao.jobs_dao import dao_update_job
|
||||||
|
from app.models import SMS_TYPE, EMAIL_TYPE, LETTER_TYPE, PRIORITY, KEY_TYPE_TEST, KEY_TYPE_TEAM
|
||||||
|
from app.celery.tasks import build_dvla_file, update_job_to_sent_to_dvla
|
||||||
from app.notifications.process_notifications import (
|
from app.notifications.process_notifications import (
|
||||||
persist_notification,
|
persist_notification,
|
||||||
send_notification_to_queue,
|
send_notification_to_queue,
|
||||||
simulated_recipient,
|
simulated_recipient,
|
||||||
persist_scheduled_notification)
|
persist_scheduled_notification)
|
||||||
|
from app.notifications.process_letter_notifications import (
|
||||||
|
create_letter_api_job,
|
||||||
|
create_letter_notification
|
||||||
|
)
|
||||||
from app.notifications.validators import (
|
from app.notifications.validators import (
|
||||||
validate_and_format_recipient,
|
validate_and_format_recipient,
|
||||||
check_rate_limiting,
|
check_rate_limiting,
|
||||||
@@ -18,6 +24,7 @@ from app.notifications.validators import (
|
|||||||
validate_template
|
validate_template
|
||||||
)
|
)
|
||||||
from app.schema_validation import validate
|
from app.schema_validation import validate
|
||||||
|
from app.v2.errors import BadRequestError
|
||||||
from app.v2.notifications import v2_notification_blueprint
|
from app.v2.notifications import v2_notification_blueprint
|
||||||
from app.v2.notifications.notification_schemas import (
|
from app.v2.notifications.notification_schemas import (
|
||||||
post_sms_request,
|
post_sms_request,
|
||||||
@@ -29,6 +36,7 @@ from app.v2.notifications.create_response import (
|
|||||||
create_post_email_response_from_notification,
|
create_post_email_response_from_notification,
|
||||||
create_post_letter_response_from_notification
|
create_post_letter_response_from_notification
|
||||||
)
|
)
|
||||||
|
from app.variables import LETTER_TEST_API_FILENAME
|
||||||
|
|
||||||
|
|
||||||
@v2_notification_blueprint.route('/<notification_type>', methods=['POST'])
|
@v2_notification_blueprint.route('/<notification_type>', methods=['POST'])
|
||||||
@@ -58,10 +66,9 @@ def post_notification(notification_type):
|
|||||||
|
|
||||||
if notification_type == LETTER_TYPE:
|
if notification_type == LETTER_TYPE:
|
||||||
notification = process_letter_notification(
|
notification = process_letter_notification(
|
||||||
form=form,
|
letter_data=form,
|
||||||
api_key=api_user,
|
api_key=api_user,
|
||||||
template=template,
|
template=template,
|
||||||
service=authenticated_service,
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
notification = process_sms_or_email_notification(
|
notification = process_sms_or_email_notification(
|
||||||
@@ -140,10 +147,25 @@ def process_sms_or_email_notification(*, form, notification_type, api_key, templ
|
|||||||
return notification
|
return notification
|
||||||
|
|
||||||
|
|
||||||
def process_letter_notification(*, form, api_key, template, service):
|
def process_letter_notification(*, letter_data, api_key, template):
|
||||||
# create job
|
if api_key.key_type == KEY_TYPE_TEAM:
|
||||||
|
raise BadRequestError(message='Cannot send letters with a team api key', status_code=403)
|
||||||
|
|
||||||
# create notification
|
job = create_letter_api_job(template)
|
||||||
|
notification = create_letter_notification(letter_data, job, api_key)
|
||||||
|
|
||||||
# trigger build_dvla_file task
|
if api_key.service.research_mode or api_key.key_type == KEY_TYPE_TEST:
|
||||||
raise NotImplementedError
|
|
||||||
|
# distinguish real API jobs from test jobs by giving the test jobs a different filename
|
||||||
|
job.original_file_name = LETTER_TEST_API_FILENAME
|
||||||
|
dao_update_job(job)
|
||||||
|
|
||||||
|
update_job_to_sent_to_dvla.apply_async([str(job.id)], queue=QueueNames.RESEARCH_MODE)
|
||||||
|
else:
|
||||||
|
build_dvla_file.apply_async([str(job.id)], queue=QueueNames.JOBS)
|
||||||
|
|
||||||
|
current_app.logger.info("send job {} for api notification {} to build-dvla-file in the process-job queue".format(
|
||||||
|
job.id,
|
||||||
|
notification.id
|
||||||
|
))
|
||||||
|
return notification
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# all jobs for letters created via the api must have this filename
|
||||||
|
LETTER_API_FILENAME = 'letter submitted via api'
|
||||||
|
LETTER_TEST_API_FILENAME = 'test letter submitted via api'
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 0113_job_created_by_nullable
|
||||||
|
Revises: 0112_add_start_end_dates
|
||||||
|
Create Date: 2017-07-27 11:12:34.938086
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '0113_job_created_by_nullable'
|
||||||
|
down_revision = '0112_add_start_end_dates'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.alter_column('jobs', 'created_by_id', nullable=True)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# This will error if there are any jobs with no created_by - we'll have to decide how to handle those as and when
|
||||||
|
# we downgrade
|
||||||
|
op.alter_column('jobs', 'created_by_id', nullable=False)
|
||||||
+25
-16
@@ -39,7 +39,7 @@ from app.dao.invited_user_dao import save_invited_user
|
|||||||
from app.dao.provider_rates_dao import create_provider_rates
|
from app.dao.provider_rates_dao import create_provider_rates
|
||||||
from app.clients.sms.firetext import FiretextClient
|
from app.clients.sms.firetext import FiretextClient
|
||||||
from tests import create_authorization_header
|
from tests import create_authorization_header
|
||||||
from tests.app.db import create_user, create_template, create_notification
|
from tests.app.db import create_user, create_template, create_notification, create_api_key
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture
|
@pytest.yield_fixture
|
||||||
@@ -255,8 +255,8 @@ def sample_template_without_email_permission(notify_db, notify_db_session):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def sample_letter_template(sample_service):
|
def sample_letter_template(sample_service_full_permissions):
|
||||||
return create_template(sample_service, template_type=LETTER_TYPE)
|
return create_template(sample_service_full_permissions, template_type=LETTER_TYPE)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
@@ -397,17 +397,18 @@ def sample_email_job(notify_db,
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def sample_letter_job(sample_service, sample_letter_template):
|
def sample_letter_job(sample_letter_template):
|
||||||
|
service = sample_letter_template.service
|
||||||
data = {
|
data = {
|
||||||
'id': uuid.uuid4(),
|
'id': uuid.uuid4(),
|
||||||
'service_id': sample_service.id,
|
'service_id': service.id,
|
||||||
'service': sample_service,
|
'service': service,
|
||||||
'template_id': sample_letter_template.id,
|
'template_id': sample_letter_template.id,
|
||||||
'template_version': sample_letter_template.version,
|
'template_version': sample_letter_template.version,
|
||||||
'original_file_name': 'some.csv',
|
'original_file_name': 'some.csv',
|
||||||
'notification_count': 1,
|
'notification_count': 1,
|
||||||
'created_at': datetime.utcnow(),
|
'created_at': datetime.utcnow(),
|
||||||
'created_by': sample_service.created_by,
|
'created_by': service.created_by,
|
||||||
}
|
}
|
||||||
job = Job(**data)
|
job = Job(**data)
|
||||||
dao_create_job(job)
|
dao_create_job(job)
|
||||||
@@ -429,7 +430,7 @@ def sample_notification_with_job(
|
|||||||
sent_at=None,
|
sent_at=None,
|
||||||
billable_units=1,
|
billable_units=1,
|
||||||
personalisation=None,
|
personalisation=None,
|
||||||
api_key_id=None,
|
api_key=None,
|
||||||
key_type=KEY_TYPE_NORMAL
|
key_type=KEY_TYPE_NORMAL
|
||||||
):
|
):
|
||||||
if job is None:
|
if job is None:
|
||||||
@@ -448,7 +449,7 @@ def sample_notification_with_job(
|
|||||||
sent_at=sent_at,
|
sent_at=sent_at,
|
||||||
billable_units=billable_units,
|
billable_units=billable_units,
|
||||||
personalisation=personalisation,
|
personalisation=personalisation,
|
||||||
api_key_id=api_key_id,
|
api_key=api_key,
|
||||||
key_type=key_type
|
key_type=key_type
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -468,7 +469,7 @@ def sample_notification(
|
|||||||
sent_at=None,
|
sent_at=None,
|
||||||
billable_units=1,
|
billable_units=1,
|
||||||
personalisation=None,
|
personalisation=None,
|
||||||
api_key_id=None,
|
api_key=None,
|
||||||
key_type=KEY_TYPE_NORMAL,
|
key_type=KEY_TYPE_NORMAL,
|
||||||
sent_by=None,
|
sent_by=None,
|
||||||
client_reference=None,
|
client_reference=None,
|
||||||
@@ -483,6 +484,12 @@ def sample_notification(
|
|||||||
if template is None:
|
if template is None:
|
||||||
template = sample_template(notify_db, notify_db_session, service=service)
|
template = sample_template(notify_db, notify_db_session, service=service)
|
||||||
|
|
||||||
|
if job is None and api_key is None:
|
||||||
|
# we didn't specify in test - lets create it
|
||||||
|
api_key = ApiKey.query.filter(ApiKey.service == template.service, ApiKey.key_type == key_type).first()
|
||||||
|
if not api_key:
|
||||||
|
api_key = create_api_key(template.service, key_type=key_type)
|
||||||
|
|
||||||
notification_id = uuid.uuid4()
|
notification_id = uuid.uuid4()
|
||||||
|
|
||||||
if to_field:
|
if to_field:
|
||||||
@@ -507,8 +514,9 @@ def sample_notification(
|
|||||||
'billable_units': billable_units,
|
'billable_units': billable_units,
|
||||||
'personalisation': personalisation,
|
'personalisation': personalisation,
|
||||||
'notification_type': template.template_type,
|
'notification_type': template.template_type,
|
||||||
'api_key_id': api_key_id,
|
'api_key': api_key,
|
||||||
'key_type': key_type,
|
'api_key_id': api_key and api_key.id,
|
||||||
|
'key_type': api_key.key_type if api_key else key_type,
|
||||||
'sent_by': sent_by,
|
'sent_by': sent_by,
|
||||||
'updated_at': created_at if status in NOTIFICATION_STATUS_TYPES_COMPLETED else None,
|
'updated_at': created_at if status in NOTIFICATION_STATUS_TYPES_COMPLETED else None,
|
||||||
'client_reference': client_reference,
|
'client_reference': client_reference,
|
||||||
@@ -549,11 +557,12 @@ def sample_letter_notification(sample_letter_template):
|
|||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
def sample_notification_with_api_key(notify_db, notify_db_session):
|
def sample_notification_with_api_key(notify_db, notify_db_session):
|
||||||
notification = sample_notification(notify_db, notify_db_session)
|
notification = sample_notification(notify_db, notify_db_session)
|
||||||
notification.api_key_id = sample_api_key(
|
notification.api_key = sample_api_key(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
name='Test key'
|
name='Test key'
|
||||||
).id
|
)
|
||||||
|
notification.api_key_id = notification.api_key.id
|
||||||
return notification
|
return notification
|
||||||
|
|
||||||
|
|
||||||
@@ -1026,7 +1035,7 @@ def admin_request(client):
|
|||||||
headers=[('Content-Type', 'application/json'), create_authorization_header()]
|
headers=[('Content-Type', 'application/json'), create_authorization_header()]
|
||||||
)
|
)
|
||||||
json_resp = json.loads(resp.get_data(as_text=True))
|
json_resp = json.loads(resp.get_data(as_text=True))
|
||||||
assert resp.status_code == _expected_status
|
assert resp.status_code == _expected_status, json_resp
|
||||||
return json_resp
|
return json_resp
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -1036,7 +1045,7 @@ def admin_request(client):
|
|||||||
headers=[create_authorization_header()]
|
headers=[create_authorization_header()]
|
||||||
)
|
)
|
||||||
json_resp = json.loads(resp.get_data(as_text=True))
|
json_resp = json.loads(resp.get_data(as_text=True))
|
||||||
assert resp.status_code == _expected_status
|
assert resp.status_code == _expected_status, json_resp
|
||||||
return json_resp
|
return json_resp
|
||||||
|
|
||||||
return AdminRequest
|
return AdminRequest
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ from app.dao.notifications_dao import (
|
|||||||
dao_created_scheduled_notification, dao_get_scheduled_notifications, set_scheduled_notification_to_processed)
|
dao_created_scheduled_notification, dao_get_scheduled_notifications, set_scheduled_notification_to_processed)
|
||||||
|
|
||||||
from app.dao.services_dao import dao_update_service
|
from app.dao.services_dao import dao_update_service
|
||||||
from tests.app.db import create_notification
|
from tests.app.db import create_notification, create_api_key
|
||||||
from tests.app.conftest import (
|
from tests.app.conftest import (
|
||||||
sample_notification,
|
sample_notification,
|
||||||
sample_template,
|
sample_template,
|
||||||
@@ -117,14 +117,14 @@ def test_template_usage_should_ignore_test_keys(
|
|||||||
notify_db_session,
|
notify_db_session,
|
||||||
created_at=two_minutes_ago,
|
created_at=two_minutes_ago,
|
||||||
template=sms,
|
template=sms,
|
||||||
api_key_id=sample_team_api_key.id,
|
api_key=sample_team_api_key,
|
||||||
key_type=KEY_TYPE_TEAM)
|
key_type=KEY_TYPE_TEAM)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
created_at=one_minute_ago,
|
created_at=one_minute_ago,
|
||||||
template=sms,
|
template=sms,
|
||||||
api_key_id=sample_test_api_key.id,
|
api_key=sample_test_api_key,
|
||||||
key_type=KEY_TYPE_TEST)
|
key_type=KEY_TYPE_TEST)
|
||||||
|
|
||||||
results = dao_get_last_template_usage(sms.id)
|
results = dao_get_last_template_usage(sms.id)
|
||||||
@@ -169,11 +169,11 @@ def test_template_history_should_ignore_test_keys(
|
|||||||
sms = sample_template(notify_db, notify_db_session)
|
sms = sample_template(notify_db, notify_db_session)
|
||||||
|
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, template=sms, api_key_id=sample_api_key.id, key_type=KEY_TYPE_NORMAL)
|
notify_db, notify_db_session, template=sms, api_key=sample_api_key, key_type=KEY_TYPE_NORMAL)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, template=sms, api_key_id=sample_team_api_key.id, key_type=KEY_TYPE_TEAM)
|
notify_db, notify_db_session, template=sms, api_key=sample_team_api_key, key_type=KEY_TYPE_TEAM)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, template=sms, api_key_id=sample_test_api_key.id, key_type=KEY_TYPE_TEST)
|
notify_db, notify_db_session, template=sms, api_key=sample_test_api_key, key_type=KEY_TYPE_TEST)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, template=sms)
|
notify_db, notify_db_session, template=sms)
|
||||||
|
|
||||||
@@ -836,13 +836,16 @@ def test_get_notification_by_id(notify_db, notify_db_session, sample_template):
|
|||||||
assert notification_from_db.scheduled_notification.scheduled_for == datetime(2017, 5, 5, 14, 15)
|
assert notification_from_db.scheduled_notification.scheduled_for == datetime(2017, 5, 5, 14, 15)
|
||||||
|
|
||||||
|
|
||||||
def test_get_notifications_by_reference(notify_db, notify_db_session, sample_service):
|
def test_get_notifications_by_reference(sample_template):
|
||||||
client_reference = 'some-client-ref'
|
client_reference = 'some-client-ref'
|
||||||
assert len(Notification.query.all()) == 0
|
assert len(Notification.query.all()) == 0
|
||||||
sample_notification(notify_db, notify_db_session, client_reference=client_reference)
|
create_notification(sample_template, client_reference=client_reference)
|
||||||
sample_notification(notify_db, notify_db_session, client_reference=client_reference)
|
create_notification(sample_template, client_reference=client_reference)
|
||||||
sample_notification(notify_db, notify_db_session, client_reference='other-ref')
|
create_notification(sample_template, client_reference='other-ref')
|
||||||
all_notifications = get_notifications_for_service(sample_service.id, client_reference=client_reference).items
|
all_notifications = get_notifications_for_service(
|
||||||
|
sample_template.service_id,
|
||||||
|
client_reference=client_reference
|
||||||
|
).items
|
||||||
assert len(all_notifications) == 2
|
assert len(all_notifications) == 2
|
||||||
|
|
||||||
|
|
||||||
@@ -1066,22 +1069,22 @@ def test_should_not_delete_notification_history(notify_db, notify_db_session, sa
|
|||||||
|
|
||||||
|
|
||||||
@freeze_time("2016-01-10")
|
@freeze_time("2016-01-10")
|
||||||
def test_should_limit_notifications_return_by_day_limit_plus_one(notify_db, notify_db_session, sample_service):
|
def test_should_limit_notifications_return_by_day_limit_plus_one(sample_template):
|
||||||
assert len(Notification.query.all()) == 0
|
assert len(Notification.query.all()) == 0
|
||||||
|
|
||||||
# create one notification a day between 1st and 9th
|
# create one notification a day between 1st and 9th
|
||||||
for i in range(1, 11):
|
for i in range(1, 11):
|
||||||
past_date = '2016-01-{0:02d}'.format(i)
|
past_date = '2016-01-{0:02d}'.format(i)
|
||||||
with freeze_time(past_date):
|
with freeze_time(past_date):
|
||||||
sample_notification(notify_db, notify_db_session, created_at=datetime.utcnow(), status="failed")
|
create_notification(sample_template, created_at=datetime.utcnow(), status="failed")
|
||||||
|
|
||||||
all_notifications = Notification.query.all()
|
all_notifications = Notification.query.all()
|
||||||
assert len(all_notifications) == 10
|
assert len(all_notifications) == 10
|
||||||
|
|
||||||
all_notifications = get_notifications_for_service(sample_service.id, limit_days=10).items
|
all_notifications = get_notifications_for_service(sample_template.service_id, limit_days=10).items
|
||||||
assert len(all_notifications) == 10
|
assert len(all_notifications) == 10
|
||||||
|
|
||||||
all_notifications = get_notifications_for_service(sample_service.id, limit_days=1).items
|
all_notifications = get_notifications_for_service(sample_template.service_id, limit_days=1).items
|
||||||
assert len(all_notifications) == 2
|
assert len(all_notifications) == 2
|
||||||
|
|
||||||
|
|
||||||
@@ -1302,42 +1305,20 @@ def test_dao_timeout_notifications_doesnt_affect_letters(sample_letter_template)
|
|||||||
assert updated == 0
|
assert updated == 0
|
||||||
|
|
||||||
|
|
||||||
def test_should_return_notifications_excluding_jobs_by_default(notify_db, notify_db_session, sample_service):
|
def test_should_return_notifications_excluding_jobs_by_default(sample_template, sample_job, sample_api_key):
|
||||||
assert len(Notification.query.all()) == 0
|
with_job = create_notification(sample_template, job=sample_job)
|
||||||
|
without_job = create_notification(sample_template, api_key=sample_api_key)
|
||||||
|
|
||||||
job = sample_job(notify_db, notify_db_session)
|
include_jobs = get_notifications_for_service(sample_template.service_id, include_jobs=True).items
|
||||||
with_job = sample_notification(
|
assert len(include_jobs) == 2
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), status="delivered", job=job
|
|
||||||
)
|
|
||||||
without_job = sample_notification(
|
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), status="delivered"
|
|
||||||
)
|
|
||||||
|
|
||||||
all_notifications = Notification.query.all()
|
exclude_jobs_by_default = get_notifications_for_service(sample_template.service_id).items
|
||||||
assert len(all_notifications) == 2
|
assert len(exclude_jobs_by_default) == 1
|
||||||
|
assert exclude_jobs_by_default[0].id == without_job.id
|
||||||
|
|
||||||
all_notifications = get_notifications_for_service(sample_service.id).items
|
exclude_jobs_manually = get_notifications_for_service(sample_template.service_id, include_jobs=False).items
|
||||||
assert len(all_notifications) == 1
|
assert len(exclude_jobs_manually) == 1
|
||||||
assert all_notifications[0].id == without_job.id
|
assert exclude_jobs_manually[0].id == without_job.id
|
||||||
|
|
||||||
|
|
||||||
def test_should_return_notifications_including_jobs(notify_db, notify_db_session, sample_service):
|
|
||||||
assert len(Notification.query.all()) == 0
|
|
||||||
|
|
||||||
job = sample_job(notify_db, notify_db_session)
|
|
||||||
with_job = sample_notification(
|
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), status="delivered", job=job
|
|
||||||
)
|
|
||||||
|
|
||||||
all_notifications = Notification.query.all()
|
|
||||||
assert len(all_notifications) == 1
|
|
||||||
|
|
||||||
all_notifications = get_notifications_for_service(sample_service.id).items
|
|
||||||
assert len(all_notifications) == 0
|
|
||||||
|
|
||||||
all_notifications = get_notifications_for_service(sample_service.id, limit_days=1, include_jobs=True).items
|
|
||||||
assert len(all_notifications) == 1
|
|
||||||
assert all_notifications[0].id == with_job.id
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_notifications_created_by_api_or_csv_are_returned_correctly_excluding_test_key_notifications(
|
def test_get_notifications_created_by_api_or_csv_are_returned_correctly_excluding_test_key_notifications(
|
||||||
@@ -1353,15 +1334,15 @@ def test_get_notifications_created_by_api_or_csv_are_returned_correctly_excludin
|
|||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), job=sample_job
|
notify_db, notify_db_session, created_at=datetime.utcnow(), job=sample_job
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_api_key,
|
||||||
key_type=sample_api_key.key_type
|
key_type=sample_api_key.key_type
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_team_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_team_api_key,
|
||||||
key_type=sample_team_api_key.key_type
|
key_type=sample_team_api_key.key_type
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_test_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_test_api_key,
|
||||||
key_type=sample_test_api_key.key_type
|
key_type=sample_test_api_key.key_type
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1394,15 +1375,15 @@ def test_get_notifications_with_a_live_api_key_type(
|
|||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), job=sample_job
|
notify_db, notify_db_session, created_at=datetime.utcnow(), job=sample_job
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_api_key,
|
||||||
key_type=sample_api_key.key_type
|
key_type=sample_api_key.key_type
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_team_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_team_api_key,
|
||||||
key_type=sample_team_api_key.key_type
|
key_type=sample_team_api_key.key_type
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_test_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_test_api_key,
|
||||||
key_type=sample_test_api_key.key_type
|
key_type=sample_test_api_key.key_type
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1432,15 +1413,15 @@ def test_get_notifications_with_a_test_api_key_type(
|
|||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), job=sample_job
|
notify_db, notify_db_session, created_at=datetime.utcnow(), job=sample_job
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_api_key,
|
||||||
key_type=sample_api_key.key_type
|
key_type=sample_api_key.key_type
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_team_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_team_api_key,
|
||||||
key_type=sample_team_api_key.key_type
|
key_type=sample_team_api_key.key_type
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_test_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_test_api_key,
|
||||||
key_type=sample_test_api_key.key_type
|
key_type=sample_test_api_key.key_type
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1467,15 +1448,15 @@ def test_get_notifications_with_a_team_api_key_type(
|
|||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), job=sample_job
|
notify_db, notify_db_session, created_at=datetime.utcnow(), job=sample_job
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_api_key,
|
||||||
key_type=sample_api_key.key_type
|
key_type=sample_api_key.key_type
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_team_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_team_api_key,
|
||||||
key_type=sample_team_api_key.key_type
|
key_type=sample_team_api_key.key_type
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_test_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_test_api_key,
|
||||||
key_type=sample_test_api_key.key_type
|
key_type=sample_test_api_key.key_type
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1503,15 +1484,15 @@ def test_should_exclude_test_key_notifications_by_default(
|
|||||||
)
|
)
|
||||||
|
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_api_key,
|
||||||
key_type=sample_api_key.key_type
|
key_type=sample_api_key.key_type
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_team_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_team_api_key,
|
||||||
key_type=sample_team_api_key.key_type
|
key_type=sample_team_api_key.key_type
|
||||||
)
|
)
|
||||||
sample_notification(
|
sample_notification(
|
||||||
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key_id=sample_test_api_key.id,
|
notify_db, notify_db_session, created_at=datetime.utcnow(), api_key=sample_test_api_key,
|
||||||
key_type=sample_test_api_key.key_type
|
key_type=sample_test_api_key.key_type
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1784,13 +1765,15 @@ def test_dao_update_notifications_sent_to_dvla(notify_db, notify_db_session, sam
|
|||||||
assert history.updated_at
|
assert history.updated_at
|
||||||
|
|
||||||
|
|
||||||
def test_dao_update_notifications_sent_to_dvla_does_update_history_if_test_key(
|
def test_dao_update_notifications_sent_to_dvla_does_update_history_if_test_key(sample_letter_job):
|
||||||
notify_db, notify_db_session, sample_letter_template, sample_api_key):
|
api_key = create_api_key(sample_letter_job.service, key_type=KEY_TYPE_TEST)
|
||||||
job = sample_job(notify_db=notify_db, notify_db_session=notify_db_session, template=sample_letter_template)
|
|
||||||
notification = create_notification(
|
notification = create_notification(
|
||||||
template=sample_letter_template, job=job, api_key_id=sample_api_key.id, key_type='test')
|
sample_letter_job.template,
|
||||||
|
job=sample_letter_job,
|
||||||
|
api_key=api_key
|
||||||
|
)
|
||||||
|
|
||||||
updated_count = dao_update_notifications_sent_to_dvla(job_id=job.id, provider='some provider')
|
updated_count = dao_update_notifications_sent_to_dvla(job_id=sample_letter_job.id, provider='some provider')
|
||||||
|
|
||||||
assert updated_count == 1
|
assert updated_count == 1
|
||||||
updated_notification = Notification.query.get(notification.id)
|
updated_notification = Notification.query.get(notification.id)
|
||||||
@@ -1798,7 +1781,7 @@ def test_dao_update_notifications_sent_to_dvla_does_update_history_if_test_key(
|
|||||||
assert updated_notification.sent_by == 'some provider'
|
assert updated_notification.sent_by == 'some provider'
|
||||||
assert updated_notification.sent_at
|
assert updated_notification.sent_at
|
||||||
assert updated_notification.updated_at
|
assert updated_notification.updated_at
|
||||||
assert not NotificationHistory.query.get(notification.id)
|
assert NotificationHistory.query.count() == 0
|
||||||
|
|
||||||
|
|
||||||
def test_dao_get_notifications_by_to_field(sample_template):
|
def test_dao_get_notifications_by_to_field(sample_template):
|
||||||
|
|||||||
@@ -552,11 +552,11 @@ def test_fetch_stats_counts_should_ignore_team_key(
|
|||||||
sample_team_api_key
|
sample_team_api_key
|
||||||
):
|
):
|
||||||
# two created email, one failed email, and one created sms
|
# two created email, one failed email, and one created sms
|
||||||
create_notification(notify_db, notify_db_session, api_key_id=sample_api_key.id, key_type=sample_api_key.key_type)
|
create_notification(notify_db, notify_db_session, api_key=sample_api_key, key_type=sample_api_key.key_type)
|
||||||
create_notification(
|
create_notification(
|
||||||
notify_db, notify_db_session, api_key_id=sample_test_api_key.id, key_type=sample_test_api_key.key_type)
|
notify_db, notify_db_session, api_key=sample_test_api_key, key_type=sample_test_api_key.key_type)
|
||||||
create_notification(
|
create_notification(
|
||||||
notify_db, notify_db_session, api_key_id=sample_team_api_key.id, key_type=sample_team_api_key.key_type)
|
notify_db, notify_db_session, api_key=sample_team_api_key, key_type=sample_team_api_key.key_type)
|
||||||
create_notification(
|
create_notification(
|
||||||
notify_db, notify_db_session)
|
notify_db, notify_db_session)
|
||||||
|
|
||||||
@@ -757,24 +757,17 @@ def test_dao_suspend_service_marks_service_as_inactive_and_expires_api_keys(samp
|
|||||||
("8", "4", "2")]) # a date range that starts more than 7 days ago
|
("8", "4", "2")]) # a date range that starts more than 7 days ago
|
||||||
def test_fetch_stats_by_date_range_for_all_services_returns_test_notifications(notify_db,
|
def test_fetch_stats_by_date_range_for_all_services_returns_test_notifications(notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
sample_api_key,
|
|
||||||
start_delta,
|
start_delta,
|
||||||
end_delta,
|
end_delta,
|
||||||
expected):
|
expected):
|
||||||
result_one = create_notification(notify_db, notify_db_session, created_at=datetime.now(),
|
create_noti = functools.partial(create_notification, notify_db, notify_db_session)
|
||||||
api_key_id=sample_api_key.id, key_type='test')
|
result_one = create_noti(created_at=datetime.now(), key_type='test')
|
||||||
create_notification(notify_db, notify_db_session, created_at=datetime.now() - timedelta(days=2),
|
create_noti(created_at=datetime.now() - timedelta(days=2), key_type='test')
|
||||||
api_key_id=sample_api_key.id, key_type='test')
|
create_noti(created_at=datetime.now() - timedelta(days=3), key_type='test')
|
||||||
create_notification(notify_db, notify_db_session, created_at=datetime.now() - timedelta(days=3),
|
create_noti(created_at=datetime.now() - timedelta(days=4), key_type='normal')
|
||||||
api_key_id=sample_api_key.id, key_type='test')
|
create_noti(created_at=datetime.now() - timedelta(days=4), key_type='test')
|
||||||
create_notification(notify_db, notify_db_session, created_at=datetime.now() - timedelta(days=4),
|
create_noti(created_at=datetime.now() - timedelta(days=8), key_type='test')
|
||||||
api_key_id=sample_api_key.id, key_type='normal')
|
create_noti(created_at=datetime.now() - timedelta(days=8), key_type='normal')
|
||||||
create_notification(notify_db, notify_db_session, created_at=datetime.now() - timedelta(days=4),
|
|
||||||
api_key_id=sample_api_key.id, key_type='test')
|
|
||||||
create_notification(notify_db, notify_db_session, created_at=datetime.now() - timedelta(days=8),
|
|
||||||
api_key_id=sample_api_key.id, key_type='test')
|
|
||||||
create_notification(notify_db, notify_db_session, created_at=datetime.now() - timedelta(days=8),
|
|
||||||
api_key_id=sample_api_key.id, key_type='normal')
|
|
||||||
|
|
||||||
start_date = (datetime.utcnow() - timedelta(days=int(start_delta))).date()
|
start_date = (datetime.utcnow() - timedelta(days=int(start_delta))).date()
|
||||||
end_date = (datetime.utcnow() - timedelta(days=int(end_delta))).date()
|
end_date = (datetime.utcnow() - timedelta(days=int(end_delta))).date()
|
||||||
|
|||||||
+36
-7
@@ -5,6 +5,7 @@ from app import db
|
|||||||
from app.dao.jobs_dao import dao_create_job
|
from app.dao.jobs_dao import dao_create_job
|
||||||
from app.dao.service_inbound_api_dao import save_service_inbound_api
|
from app.dao.service_inbound_api_dao import save_service_inbound_api
|
||||||
from app.models import (
|
from app.models import (
|
||||||
|
ApiKey,
|
||||||
Service,
|
Service,
|
||||||
User,
|
User,
|
||||||
Template,
|
Template,
|
||||||
@@ -50,7 +51,9 @@ def create_service(
|
|||||||
service_id=None,
|
service_id=None,
|
||||||
restricted=False,
|
restricted=False,
|
||||||
service_permissions=[EMAIL_TYPE, SMS_TYPE],
|
service_permissions=[EMAIL_TYPE, SMS_TYPE],
|
||||||
sms_sender='testing'
|
sms_sender='testing',
|
||||||
|
research_mode=False,
|
||||||
|
active=True,
|
||||||
):
|
):
|
||||||
service = Service(
|
service = Service(
|
||||||
name=service_name,
|
name=service_name,
|
||||||
@@ -58,9 +61,13 @@ def create_service(
|
|||||||
restricted=restricted,
|
restricted=restricted,
|
||||||
email_from=service_name.lower().replace(' ', '.'),
|
email_from=service_name.lower().replace(' ', '.'),
|
||||||
created_by=user or create_user(),
|
created_by=user or create_user(),
|
||||||
sms_sender=sms_sender
|
sms_sender=sms_sender,
|
||||||
)
|
)
|
||||||
dao_create_service(service, service.created_by, service_id, service_permissions=service_permissions)
|
dao_create_service(service, service.created_by, service_id, service_permissions=service_permissions)
|
||||||
|
|
||||||
|
service.active = active
|
||||||
|
service.research_mode = research_mode
|
||||||
|
|
||||||
return service
|
return service
|
||||||
|
|
||||||
|
|
||||||
@@ -97,7 +104,7 @@ def create_notification(
|
|||||||
updated_at=None,
|
updated_at=None,
|
||||||
billable_units=1,
|
billable_units=1,
|
||||||
personalisation=None,
|
personalisation=None,
|
||||||
api_key_id=None,
|
api_key=None,
|
||||||
key_type=KEY_TYPE_NORMAL,
|
key_type=KEY_TYPE_NORMAL,
|
||||||
sent_by=None,
|
sent_by=None,
|
||||||
client_reference=None,
|
client_reference=None,
|
||||||
@@ -114,14 +121,20 @@ def create_notification(
|
|||||||
sent_at = sent_at or datetime.utcnow()
|
sent_at = sent_at or datetime.utcnow()
|
||||||
updated_at = updated_at or datetime.utcnow()
|
updated_at = updated_at or datetime.utcnow()
|
||||||
|
|
||||||
|
if job is None and api_key is None:
|
||||||
|
# we didn't specify in test - lets create it
|
||||||
|
api_key = ApiKey.query.filter(ApiKey.service == template.service, ApiKey.key_type == key_type).first()
|
||||||
|
if not api_key:
|
||||||
|
api_key = create_api_key(template.service, key_type=key_type)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'id': uuid.uuid4(),
|
'id': uuid.uuid4(),
|
||||||
'to': to_field,
|
'to': to_field,
|
||||||
'job_id': job.id if job else None,
|
'job_id': job and job.id,
|
||||||
'job': job,
|
'job': job,
|
||||||
'service_id': template.service.id,
|
'service_id': template.service.id,
|
||||||
'service': template.service,
|
'service': template.service,
|
||||||
'template_id': template.id if template else None,
|
'template_id': template and template.id,
|
||||||
'template': template,
|
'template': template,
|
||||||
'template_version': template.version,
|
'template_version': template.version,
|
||||||
'status': status,
|
'status': status,
|
||||||
@@ -131,8 +144,9 @@ def create_notification(
|
|||||||
'billable_units': billable_units,
|
'billable_units': billable_units,
|
||||||
'personalisation': personalisation,
|
'personalisation': personalisation,
|
||||||
'notification_type': template.template_type,
|
'notification_type': template.template_type,
|
||||||
'api_key_id': api_key_id,
|
'api_key': api_key,
|
||||||
'key_type': key_type,
|
'api_key_id': api_key and api_key.id,
|
||||||
|
'key_type': api_key.key_type if api_key else key_type,
|
||||||
'sent_by': sent_by,
|
'sent_by': sent_by,
|
||||||
'updated_at': updated_at,
|
'updated_at': updated_at,
|
||||||
'client_reference': client_reference,
|
'client_reference': client_reference,
|
||||||
@@ -247,3 +261,18 @@ def create_rate(start_date, value, notification_type):
|
|||||||
db.session.add(rate)
|
db.session.add(rate)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return rate
|
return rate
|
||||||
|
|
||||||
|
|
||||||
|
def create_api_key(service, key_type=KEY_TYPE_NORMAL):
|
||||||
|
id_ = uuid.uuid4()
|
||||||
|
api_key = ApiKey(
|
||||||
|
service=service,
|
||||||
|
name='{} api key {}'.format(key_type, id_),
|
||||||
|
created_by=service.created_by,
|
||||||
|
key_type=key_type,
|
||||||
|
id=id_,
|
||||||
|
secret=uuid.uuid4()
|
||||||
|
)
|
||||||
|
db.session.add(api_key)
|
||||||
|
db.session.commit()
|
||||||
|
return api_key
|
||||||
|
|||||||
@@ -276,7 +276,6 @@ def test_create_job_returns_400_if_missing_data(notify_api, sample_template, moc
|
|||||||
assert resp_json['result'] == 'error'
|
assert resp_json['result'] == 'error'
|
||||||
assert 'Missing data for required field.' in resp_json['message']['original_file_name']
|
assert 'Missing data for required field.' in resp_json['message']['original_file_name']
|
||||||
assert 'Missing data for required field.' in resp_json['message']['notification_count']
|
assert 'Missing data for required field.' in resp_json['message']['notification_count']
|
||||||
assert 'Missing data for required field.' in resp_json['message']['id']
|
|
||||||
|
|
||||||
|
|
||||||
def test_create_job_returns_404_if_template_does_not_exist(notify_api, sample_service, mocker):
|
def test_create_job_returns_404_if_template_does_not_exist(notify_api, sample_service, mocker):
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import uuid
|
|||||||
|
|
||||||
from flask import json
|
from flask import json
|
||||||
|
|
||||||
|
from app.variables import LETTER_TEST_API_FILENAME
|
||||||
|
|
||||||
from tests import create_authorization_header
|
from tests import create_authorization_header
|
||||||
|
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ def test_send_letter_jobs_throws_validation_error(client, mocker):
|
|||||||
assert not mock_celery.called
|
assert not mock_celery.called
|
||||||
|
|
||||||
|
|
||||||
def test_send_letter_jobs_throws_validation_error(client, sample_letter_job):
|
def test_get_letter_jobs_excludes_non_letter_jobs(client, sample_letter_job, sample_job):
|
||||||
auth_header = create_authorization_header()
|
auth_header = create_authorization_header()
|
||||||
response = client.get(
|
response = client.get(
|
||||||
path='/letter-jobs',
|
path='/letter-jobs',
|
||||||
@@ -53,3 +55,11 @@ def test_send_letter_jobs_throws_validation_error(client, sample_letter_job):
|
|||||||
assert json_resp['data'][0]['id'] == str(sample_letter_job.id)
|
assert json_resp['data'][0]['id'] == str(sample_letter_job.id)
|
||||||
assert json_resp['data'][0]['service_name']['name'] == sample_letter_job.service.name
|
assert json_resp['data'][0]['service_name']['name'] == sample_letter_job.service.name
|
||||||
assert json_resp['data'][0]['job_status'] == 'pending'
|
assert json_resp['data'][0]['job_status'] == 'pending'
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_letter_jobs_excludes_test_jobs(admin_request, sample_letter_job):
|
||||||
|
sample_letter_job.original_file_name = LETTER_TEST_API_FILENAME
|
||||||
|
|
||||||
|
json_resp = admin_request.get('letter-job.get_letter_jobs')
|
||||||
|
|
||||||
|
assert len(json_resp['data']) == 0
|
||||||
|
|||||||
@@ -572,128 +572,119 @@ def test_should_not_send_sms_if_team_api_key_and_not_a_service_user(notify_api,
|
|||||||
] == json_resp['message']['to']
|
] == json_resp['message']['to']
|
||||||
|
|
||||||
|
|
||||||
def test_should_send_email_if_team_api_key_and_a_service_user(notify_api, sample_email_template, fake_uuid, mocker):
|
def test_should_send_email_if_team_api_key_and_a_service_user(client, sample_email_template, fake_uuid, mocker):
|
||||||
with notify_api.test_request_context(), notify_api.test_client() as client:
|
mocker.patch('app.celery.provider_tasks.deliver_email.apply_async')
|
||||||
mocker.patch('app.celery.provider_tasks.deliver_email.apply_async')
|
mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid)
|
||||||
mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid)
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'to': sample_email_template.service.created_by.email_address,
|
'to': sample_email_template.service.created_by.email_address,
|
||||||
'template': sample_email_template.id
|
'template': sample_email_template.id
|
||||||
}
|
}
|
||||||
api_key = ApiKey(service=sample_email_template.service,
|
auth_header = create_authorization_header(service_id=sample_email_template.service_id, key_type=KEY_TYPE_TEAM)
|
||||||
name='team_key',
|
|
||||||
created_by=sample_email_template.created_by,
|
|
||||||
key_type=KEY_TYPE_TEAM)
|
|
||||||
save_model_api_key(api_key)
|
|
||||||
auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id))
|
|
||||||
|
|
||||||
response = client.post(
|
response = client.post(
|
||||||
path='/notifications/email',
|
path='/notifications/email',
|
||||||
data=json.dumps(data),
|
data=json.dumps(data),
|
||||||
headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))])
|
headers=[('Content-Type', 'application/json'), auth_header])
|
||||||
|
|
||||||
app.celery.provider_tasks.deliver_email.apply_async.assert_called_once_with(
|
app.celery.provider_tasks.deliver_email.apply_async.assert_called_once_with(
|
||||||
[fake_uuid],
|
[fake_uuid],
|
||||||
queue='send-email-tasks'
|
queue='send-email-tasks'
|
||||||
)
|
)
|
||||||
assert response.status_code == 201
|
assert response.status_code == 201
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('restricted', [True, False])
|
@pytest.mark.parametrize('restricted', [True, False])
|
||||||
@pytest.mark.parametrize('limit', [0, 1])
|
@pytest.mark.parametrize('limit', [0, 1])
|
||||||
def test_should_send_sms_to_anyone_with_test_key(
|
def test_should_send_sms_to_anyone_with_test_key(
|
||||||
notify_api, sample_template, mocker, restricted, limit, fake_uuid
|
client, sample_template, mocker, restricted, limit, fake_uuid
|
||||||
):
|
):
|
||||||
with notify_api.test_request_context(), notify_api.test_client() as client:
|
mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
|
||||||
mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
|
mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid)
|
||||||
mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid)
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'to': '07811111111',
|
'to': '07811111111',
|
||||||
'template': sample_template.id
|
'template': sample_template.id
|
||||||
}
|
}
|
||||||
sample_template.service.restricted = restricted
|
sample_template.service.restricted = restricted
|
||||||
sample_template.service.message_limit = limit
|
sample_template.service.message_limit = limit
|
||||||
api_key = ApiKey(
|
api_key = ApiKey(
|
||||||
service=sample_template.service,
|
service=sample_template.service,
|
||||||
name='test_key',
|
name='test_key',
|
||||||
created_by=sample_template.created_by,
|
created_by=sample_template.created_by,
|
||||||
key_type=KEY_TYPE_TEST
|
key_type=KEY_TYPE_TEST
|
||||||
)
|
)
|
||||||
save_model_api_key(api_key)
|
save_model_api_key(api_key)
|
||||||
auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id))
|
auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id))
|
||||||
|
|
||||||
response = client.post(
|
response = client.post(
|
||||||
path='/notifications/sms',
|
path='/notifications/sms',
|
||||||
data=json.dumps(data),
|
data=json.dumps(data),
|
||||||
headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]
|
headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]
|
||||||
)
|
)
|
||||||
app.celery.provider_tasks.deliver_sms.apply_async.assert_called_once_with(
|
app.celery.provider_tasks.deliver_sms.apply_async.assert_called_once_with(
|
||||||
[fake_uuid], queue='research-mode-tasks'
|
[fake_uuid], queue='research-mode-tasks'
|
||||||
)
|
)
|
||||||
assert response.status_code == 201
|
assert response.status_code == 201
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('restricted', [True, False])
|
@pytest.mark.parametrize('restricted', [True, False])
|
||||||
@pytest.mark.parametrize('limit', [0, 1])
|
@pytest.mark.parametrize('limit', [0, 1])
|
||||||
def test_should_send_email_to_anyone_with_test_key(
|
def test_should_send_email_to_anyone_with_test_key(
|
||||||
notify_api, sample_email_template, mocker, restricted, limit, fake_uuid
|
client, sample_email_template, mocker, restricted, limit, fake_uuid
|
||||||
):
|
):
|
||||||
with notify_api.test_request_context(), notify_api.test_client() as client:
|
mocker.patch('app.celery.provider_tasks.deliver_email.apply_async')
|
||||||
mocker.patch('app.celery.provider_tasks.deliver_email.apply_async')
|
mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid)
|
||||||
mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid)
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'to': 'anyone123@example.com',
|
'to': 'anyone123@example.com',
|
||||||
'template': sample_email_template.id
|
'template': sample_email_template.id
|
||||||
}
|
}
|
||||||
sample_email_template.service.restricted = restricted
|
sample_email_template.service.restricted = restricted
|
||||||
sample_email_template.service.message_limit = limit
|
sample_email_template.service.message_limit = limit
|
||||||
api_key = ApiKey(
|
api_key = ApiKey(
|
||||||
service=sample_email_template.service,
|
service=sample_email_template.service,
|
||||||
name='test_key',
|
name='test_key',
|
||||||
created_by=sample_email_template.created_by,
|
created_by=sample_email_template.created_by,
|
||||||
key_type=KEY_TYPE_TEST
|
key_type=KEY_TYPE_TEST
|
||||||
)
|
)
|
||||||
save_model_api_key(api_key)
|
save_model_api_key(api_key)
|
||||||
auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id))
|
auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id))
|
||||||
|
|
||||||
response = client.post(
|
response = client.post(
|
||||||
path='/notifications/email',
|
path='/notifications/email',
|
||||||
data=json.dumps(data),
|
data=json.dumps(data),
|
||||||
headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]
|
headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]
|
||||||
)
|
)
|
||||||
|
|
||||||
app.celery.provider_tasks.deliver_email.apply_async.assert_called_once_with(
|
app.celery.provider_tasks.deliver_email.apply_async.assert_called_once_with(
|
||||||
[fake_uuid], queue='research-mode-tasks'
|
[fake_uuid], queue='research-mode-tasks'
|
||||||
)
|
)
|
||||||
assert response.status_code == 201
|
assert response.status_code == 201
|
||||||
|
|
||||||
|
|
||||||
def test_should_send_sms_if_team_api_key_and_a_service_user(notify_api, sample_template, fake_uuid, mocker):
|
def test_should_send_sms_if_team_api_key_and_a_service_user(client, sample_template, fake_uuid, mocker):
|
||||||
with notify_api.test_request_context(), notify_api.test_client() as client:
|
mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
|
||||||
mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
|
mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid)
|
||||||
mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid)
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'to': sample_template.service.created_by.mobile_number,
|
'to': sample_template.service.created_by.mobile_number,
|
||||||
'template': sample_template.id
|
'template': sample_template.id
|
||||||
}
|
}
|
||||||
api_key = ApiKey(service=sample_template.service,
|
api_key = ApiKey(service=sample_template.service,
|
||||||
name='team_key',
|
name='team_key',
|
||||||
created_by=sample_template.created_by,
|
created_by=sample_template.created_by,
|
||||||
key_type=KEY_TYPE_TEAM)
|
key_type=KEY_TYPE_TEAM)
|
||||||
save_model_api_key(api_key)
|
save_model_api_key(api_key)
|
||||||
auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id))
|
auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id))
|
||||||
|
|
||||||
response = client.post(
|
response = client.post(
|
||||||
path='/notifications/sms',
|
path='/notifications/sms',
|
||||||
data=json.dumps(data),
|
data=json.dumps(data),
|
||||||
headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))])
|
headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))])
|
||||||
|
|
||||||
app.celery.provider_tasks.deliver_sms.apply_async.assert_called_once_with([fake_uuid], queue='send-sms-tasks')
|
app.celery.provider_tasks.deliver_sms.apply_async.assert_called_once_with([fake_uuid], queue='send-sms-tasks')
|
||||||
assert response.status_code == 201
|
assert response.status_code == 201
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('template_type,queue_name', [
|
@pytest.mark.parametrize('template_type,queue_name', [
|
||||||
@@ -710,7 +701,8 @@ def test_should_persist_notification(
|
|||||||
queue_name
|
queue_name
|
||||||
):
|
):
|
||||||
mocked = mocker.patch('app.celery.provider_tasks.deliver_{}.apply_async'.format(template_type))
|
mocked = mocker.patch('app.celery.provider_tasks.deliver_{}.apply_async'.format(template_type))
|
||||||
mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid)
|
mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid)
|
||||||
|
|
||||||
template = sample_template if template_type == SMS_TYPE else sample_email_template
|
template = sample_template if template_type == SMS_TYPE else sample_email_template
|
||||||
to = sample_template.service.created_by.mobile_number if template_type == SMS_TYPE \
|
to = sample_template.service.created_by.mobile_number if template_type == SMS_TYPE \
|
||||||
else sample_email_template.service.created_by.email_address
|
else sample_email_template.service.created_by.email_address
|
||||||
@@ -757,7 +749,8 @@ def test_should_delete_notification_and_return_error_if_sqs_fails(
|
|||||||
'app.celery.provider_tasks.deliver_{}.apply_async'.format(template_type),
|
'app.celery.provider_tasks.deliver_{}.apply_async'.format(template_type),
|
||||||
side_effect=Exception("failed to talk to SQS")
|
side_effect=Exception("failed to talk to SQS")
|
||||||
)
|
)
|
||||||
mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid)
|
mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid)
|
||||||
|
|
||||||
template = sample_template if template_type == SMS_TYPE else sample_email_template
|
template = sample_template if template_type == SMS_TYPE else sample_email_template
|
||||||
to = sample_template.service.created_by.mobile_number if template_type == SMS_TYPE \
|
to = sample_template.service.created_by.mobile_number if template_type == SMS_TYPE \
|
||||||
else sample_email_template.service.created_by.email_address
|
else sample_email_template.service.created_by.email_address
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from app.dao.services_dao import dao_archive_service
|
||||||
|
from app.models import Job
|
||||||
|
from app.models import JOB_STATUS_READY_TO_SEND
|
||||||
|
from app.models import LETTER_TYPE
|
||||||
|
from app.models import Notification
|
||||||
|
from app.notifications.process_letter_notifications import create_letter_api_job
|
||||||
|
from app.notifications.process_letter_notifications import create_letter_notification
|
||||||
|
from app.v2.errors import InvalidRequest
|
||||||
|
from app.variables import LETTER_API_FILENAME
|
||||||
|
|
||||||
|
from tests.app.db import create_service
|
||||||
|
from tests.app.db import create_template
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_job_rejects_inactive_service(notify_db_session):
|
||||||
|
service = create_service()
|
||||||
|
template = create_template(service, template_type=LETTER_TYPE)
|
||||||
|
dao_archive_service(service.id)
|
||||||
|
|
||||||
|
with pytest.raises(InvalidRequest) as exc_info:
|
||||||
|
create_letter_api_job(template)
|
||||||
|
|
||||||
|
assert exc_info.value.message == 'Service {} is inactive'.format(service.id)
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_job_rejects_archived_template(sample_letter_template):
|
||||||
|
sample_letter_template.archived = True
|
||||||
|
|
||||||
|
with pytest.raises(InvalidRequest) as exc_info:
|
||||||
|
create_letter_api_job(sample_letter_template)
|
||||||
|
|
||||||
|
assert exc_info.value.message == 'Template {} is deleted'.format(sample_letter_template.id)
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_job_creates_job(sample_letter_template):
|
||||||
|
job = create_letter_api_job(sample_letter_template)
|
||||||
|
|
||||||
|
assert job == Job.query.one()
|
||||||
|
assert job.original_file_name == LETTER_API_FILENAME
|
||||||
|
assert job.service == sample_letter_template.service
|
||||||
|
assert job.template_id == sample_letter_template.id
|
||||||
|
assert job.template_version == sample_letter_template.version
|
||||||
|
assert job.notification_count == 1
|
||||||
|
assert job.job_status == JOB_STATUS_READY_TO_SEND
|
||||||
|
assert job.created_by is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_letter_notification_creates_notification(sample_letter_job, sample_api_key):
|
||||||
|
data = {
|
||||||
|
'personalisation': {
|
||||||
|
'address_line_1': 'The Queen',
|
||||||
|
'address_line_2': 'Buckingham Palace',
|
||||||
|
'postcode': 'SW1 1AA',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notification = create_letter_notification(data, sample_letter_job, sample_api_key)
|
||||||
|
|
||||||
|
assert notification == Notification.query.one()
|
||||||
|
assert notification.job == sample_letter_job
|
||||||
|
assert notification.template == sample_letter_job.template
|
||||||
|
assert notification.api_key == sample_api_key
|
||||||
|
assert notification.notification_type == LETTER_TYPE
|
||||||
|
assert notification.key_type == sample_api_key.key_type
|
||||||
|
assert notification.job_row_number == 0
|
||||||
|
assert notification.reference is not None
|
||||||
|
assert notification.client_reference is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_letter_notification_sets_reference(sample_letter_job, sample_api_key):
|
||||||
|
data = {
|
||||||
|
'personalisation': {
|
||||||
|
'address_line_1': 'The Queen',
|
||||||
|
'address_line_2': 'Buckingham Palace',
|
||||||
|
'postcode': 'SW1 1AA',
|
||||||
|
},
|
||||||
|
'reference': 'foo'
|
||||||
|
}
|
||||||
|
|
||||||
|
notification = create_letter_notification(data, sample_letter_job, sample_api_key)
|
||||||
|
|
||||||
|
assert notification.client_reference == 'foo'
|
||||||
@@ -9,51 +9,53 @@ from app.dao.notifications_dao import dao_update_notification
|
|||||||
from app.dao.api_key_dao import save_model_api_key
|
from app.dao.api_key_dao import save_model_api_key
|
||||||
from app.dao.templates_dao import dao_update_template
|
from app.dao.templates_dao import dao_update_template
|
||||||
from app.models import ApiKey, KEY_TYPE_NORMAL, KEY_TYPE_TEAM, KEY_TYPE_TEST
|
from app.models import ApiKey, KEY_TYPE_NORMAL, KEY_TYPE_TEAM, KEY_TYPE_TEST
|
||||||
|
|
||||||
from tests import create_authorization_header
|
from tests import create_authorization_header
|
||||||
from tests.app.conftest import sample_notification as create_sample_notification
|
from tests.app.conftest import sample_notification as create_sample_notification
|
||||||
|
from tests.app.db import create_notification, create_api_key
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('type', ('email', 'sms'))
|
@pytest.mark.parametrize('type', ('email', 'sms'))
|
||||||
def test_get_notification_by_id(client, sample_notification, sample_email_notification, type):
|
def test_get_notification_by_id(client, sample_notification, sample_email_notification, type):
|
||||||
if type == 'email':
|
if type == 'email':
|
||||||
notification_to_get = sample_email_notification
|
notification_to_get = sample_email_notification
|
||||||
if type == 'sms':
|
if type == 'sms':
|
||||||
notification_to_get = sample_notification
|
notification_to_get = sample_notification
|
||||||
|
|
||||||
auth_header = create_authorization_header(service_id=notification_to_get.service_id)
|
auth_header = create_authorization_header(service_id=notification_to_get.service_id)
|
||||||
response = client.get(
|
response = client.get(
|
||||||
'/notifications/{}'.format(notification_to_get.id),
|
'/notifications/{}'.format(notification_to_get.id),
|
||||||
headers=[auth_header])
|
headers=[auth_header])
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
notification = json.loads(response.get_data(as_text=True))['data']['notification']
|
notification = json.loads(response.get_data(as_text=True))['data']['notification']
|
||||||
assert notification['status'] == 'created'
|
assert notification['status'] == 'created'
|
||||||
assert notification['template'] == {
|
assert notification['template'] == {
|
||||||
'id': str(notification_to_get.template.id),
|
'id': str(notification_to_get.template.id),
|
||||||
'name': notification_to_get.template.name,
|
'name': notification_to_get.template.name,
|
||||||
'template_type': notification_to_get.template.template_type,
|
'template_type': notification_to_get.template.template_type,
|
||||||
'version': 1
|
'version': 1
|
||||||
}
|
}
|
||||||
assert notification['to'] == notification_to_get.to
|
assert notification['to'] == notification_to_get.to
|
||||||
assert notification['service'] == str(notification_to_get.service_id)
|
assert notification['service'] == str(notification_to_get.service_id)
|
||||||
assert notification['body'] == notification_to_get.template.content
|
assert notification['body'] == notification_to_get.template.content
|
||||||
assert notification.get('subject', None) == notification_to_get.subject
|
assert notification.get('subject', None) == notification_to_get.subject
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("id", ["1234-badly-formatted-id-7890", "0"])
|
@pytest.mark.parametrize("id", ["1234-badly-formatted-id-7890", "0"])
|
||||||
@pytest.mark.parametrize('type', ('email', 'sms'))
|
@pytest.mark.parametrize('type', ('email', 'sms'))
|
||||||
def test_get_notification_by_invalid_id(client, sample_notification, sample_email_notification, id, type):
|
def test_get_notification_by_invalid_id(client, sample_notification, sample_email_notification, id, type):
|
||||||
if type == 'email':
|
if type == 'email':
|
||||||
notification_to_get = sample_email_notification
|
notification_to_get = sample_email_notification
|
||||||
if type == 'sms':
|
if type == 'sms':
|
||||||
notification_to_get = sample_notification
|
notification_to_get = sample_notification
|
||||||
auth_header = create_authorization_header(service_id=notification_to_get.service_id)
|
auth_header = create_authorization_header(service_id=notification_to_get.service_id)
|
||||||
|
|
||||||
response = client.get(
|
response = client.get(
|
||||||
'/notifications/{}'.format(id),
|
'/notifications/{}'.format(id),
|
||||||
headers=[auth_header])
|
headers=[auth_header])
|
||||||
|
|
||||||
assert response.status_code == 405
|
assert response.status_code == 405
|
||||||
|
|
||||||
|
|
||||||
def test_get_notifications_empty_result(client, sample_api_key):
|
def test_get_notifications_empty_result(client, sample_api_key):
|
||||||
@@ -156,7 +158,7 @@ def test_normal_api_key_returns_notifications_created_from_jobs_and_from_api(
|
|||||||
api_notification = create_sample_notification(
|
api_notification = create_sample_notification(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
api_key_id=sample_api_key.id
|
api_key=sample_api_key
|
||||||
)
|
)
|
||||||
api_notification.job = None
|
api_notification.job = None
|
||||||
|
|
||||||
@@ -200,19 +202,19 @@ def test_get_all_notifications_only_returns_notifications_of_matching_type(
|
|||||||
normal_notification = create_sample_notification(
|
normal_notification = create_sample_notification(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
api_key_id=normal_api_key.id,
|
api_key=normal_api_key,
|
||||||
key_type=KEY_TYPE_NORMAL
|
key_type=KEY_TYPE_NORMAL
|
||||||
)
|
)
|
||||||
team_notification = create_sample_notification(
|
team_notification = create_sample_notification(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
api_key_id=team_api_key.id,
|
api_key=team_api_key,
|
||||||
key_type=KEY_TYPE_TEAM
|
key_type=KEY_TYPE_TEAM
|
||||||
)
|
)
|
||||||
test_notification = create_sample_notification(
|
test_notification = create_sample_notification(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
api_key_id=test_api_key.id,
|
api_key=test_api_key,
|
||||||
key_type=KEY_TYPE_TEST
|
key_type=KEY_TYPE_TEST
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -236,54 +238,18 @@ def test_get_all_notifications_only_returns_notifications_of_matching_type(
|
|||||||
@pytest.mark.parametrize('key_type', [KEY_TYPE_NORMAL, KEY_TYPE_TEAM, KEY_TYPE_TEST])
|
@pytest.mark.parametrize('key_type', [KEY_TYPE_NORMAL, KEY_TYPE_TEAM, KEY_TYPE_TEST])
|
||||||
def test_no_api_keys_return_job_notifications_by_default(
|
def test_no_api_keys_return_job_notifications_by_default(
|
||||||
client,
|
client,
|
||||||
notify_db,
|
sample_template,
|
||||||
notify_db_session,
|
|
||||||
sample_service,
|
|
||||||
sample_job,
|
sample_job,
|
||||||
key_type
|
key_type
|
||||||
):
|
):
|
||||||
team_api_key = ApiKey(service=sample_service,
|
team_api_key = create_api_key(sample_template.service, KEY_TYPE_TEAM)
|
||||||
name='team_api_key',
|
normal_api_key = create_api_key(sample_template.service, KEY_TYPE_NORMAL)
|
||||||
created_by=sample_service.created_by,
|
test_api_key = create_api_key(sample_template.service, KEY_TYPE_TEST)
|
||||||
key_type=KEY_TYPE_TEAM)
|
|
||||||
save_model_api_key(team_api_key)
|
|
||||||
|
|
||||||
normal_api_key = ApiKey(service=sample_service,
|
job_notification = create_notification(sample_template, job=sample_job)
|
||||||
name='normal_api_key',
|
normal_notification = create_notification(sample_template, api_key=normal_api_key)
|
||||||
created_by=sample_service.created_by,
|
team_notification = create_notification(sample_template, api_key=team_api_key)
|
||||||
key_type=KEY_TYPE_NORMAL)
|
test_notification = create_notification(sample_template, api_key=test_api_key)
|
||||||
save_model_api_key(normal_api_key)
|
|
||||||
|
|
||||||
test_api_key = ApiKey(service=sample_service,
|
|
||||||
name='test_api_key',
|
|
||||||
created_by=sample_service.created_by,
|
|
||||||
key_type=KEY_TYPE_TEST)
|
|
||||||
save_model_api_key(test_api_key)
|
|
||||||
|
|
||||||
job_notification = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
api_key_id=normal_api_key.id,
|
|
||||||
job=sample_job
|
|
||||||
)
|
|
||||||
normal_notification = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
api_key_id=normal_api_key.id,
|
|
||||||
key_type=KEY_TYPE_NORMAL
|
|
||||||
)
|
|
||||||
team_notification = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
api_key_id=team_api_key.id,
|
|
||||||
key_type=KEY_TYPE_TEAM
|
|
||||||
)
|
|
||||||
test_notification = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
api_key_id=test_api_key.id,
|
|
||||||
key_type=KEY_TYPE_TEST
|
|
||||||
)
|
|
||||||
|
|
||||||
notification_objs = {
|
notification_objs = {
|
||||||
KEY_TYPE_NORMAL: normal_notification,
|
KEY_TYPE_NORMAL: normal_notification,
|
||||||
@@ -336,25 +302,24 @@ def test_only_normal_api_keys_can_return_job_notifications(
|
|||||||
job_notification = create_sample_notification(
|
job_notification = create_sample_notification(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
api_key_id=normal_api_key.id,
|
|
||||||
job=sample_job
|
job=sample_job
|
||||||
)
|
)
|
||||||
normal_notification = create_sample_notification(
|
normal_notification = create_sample_notification(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
api_key_id=normal_api_key.id,
|
api_key=normal_api_key,
|
||||||
key_type=KEY_TYPE_NORMAL
|
key_type=KEY_TYPE_NORMAL
|
||||||
)
|
)
|
||||||
team_notification = create_sample_notification(
|
team_notification = create_sample_notification(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
api_key_id=team_api_key.id,
|
api_key=team_api_key,
|
||||||
key_type=KEY_TYPE_TEAM
|
key_type=KEY_TYPE_TEAM
|
||||||
)
|
)
|
||||||
test_notification = create_sample_notification(
|
test_notification = create_sample_notification(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
api_key_id=test_api_key.id,
|
api_key=test_api_key,
|
||||||
key_type=KEY_TYPE_TEST
|
key_type=KEY_TYPE_TEST
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -505,20 +470,10 @@ def test_filter_by_template_type(client, notify_db, notify_db_session, sample_te
|
|||||||
|
|
||||||
|
|
||||||
def test_filter_by_multiple_template_types(client,
|
def test_filter_by_multiple_template_types(client,
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
sample_template,
|
sample_template,
|
||||||
sample_email_template):
|
sample_email_template):
|
||||||
notification_1 = create_sample_notification(
|
notification_1 = create_notification(sample_template)
|
||||||
notify_db,
|
notification_2 = create_notification(sample_email_template)
|
||||||
notify_db_session,
|
|
||||||
service=sample_email_template.service,
|
|
||||||
template=sample_template)
|
|
||||||
notification_2 = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
service=sample_email_template.service,
|
|
||||||
template=sample_email_template)
|
|
||||||
|
|
||||||
auth_header = create_authorization_header(service_id=sample_email_template.service_id)
|
auth_header = create_authorization_header(service_id=sample_email_template.service_id)
|
||||||
|
|
||||||
@@ -529,23 +484,12 @@ def test_filter_by_multiple_template_types(client,
|
|||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
notifications = json.loads(response.get_data(as_text=True))
|
notifications = json.loads(response.get_data(as_text=True))
|
||||||
assert len(notifications['notifications']) == 2
|
assert len(notifications['notifications']) == 2
|
||||||
set(['sms', 'email']) == set(
|
assert {'sms', 'email'} == set(x['template']['template_type'] for x in notifications['notifications'])
|
||||||
[x['template']['template_type'] for x in notifications['notifications']])
|
|
||||||
|
|
||||||
|
|
||||||
def test_filter_by_status(client, notify_db, notify_db_session, sample_email_template):
|
def test_filter_by_status(client, sample_email_template):
|
||||||
notification_1 = create_sample_notification(
|
notification_1 = create_notification(sample_email_template, status="delivered")
|
||||||
notify_db,
|
notification_2 = create_notification(sample_email_template)
|
||||||
notify_db_session,
|
|
||||||
service=sample_email_template.service,
|
|
||||||
template=sample_email_template,
|
|
||||||
status="delivered")
|
|
||||||
|
|
||||||
notification_2 = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
service=sample_email_template.service,
|
|
||||||
template=sample_email_template)
|
|
||||||
|
|
||||||
auth_header = create_authorization_header(service_id=sample_email_template.service_id)
|
auth_header = create_authorization_header(service_id=sample_email_template.service_id)
|
||||||
|
|
||||||
@@ -559,58 +503,27 @@ def test_filter_by_status(client, notify_db, notify_db_session, sample_email_tem
|
|||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
def test_filter_by_multiple_statuss(client,
|
def test_filter_by_multiple_statuses(client, sample_email_template):
|
||||||
notify_db,
|
notification_1 = create_notification(sample_email_template, status="delivered")
|
||||||
notify_db_session,
|
notification_2 = create_notification(sample_email_template, status='sending')
|
||||||
sample_email_template):
|
|
||||||
notification_1 = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
service=sample_email_template.service,
|
|
||||||
template=sample_email_template,
|
|
||||||
status="delivered")
|
|
||||||
|
|
||||||
notification_2 = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
service=sample_email_template.service,
|
|
||||||
template=sample_email_template,
|
|
||||||
status='sending')
|
|
||||||
|
|
||||||
auth_header = create_authorization_header(service_id=sample_email_template.service_id)
|
auth_header = create_authorization_header(service_id=sample_email_template.service_id)
|
||||||
|
|
||||||
response = client.get(
|
response = client.get(
|
||||||
'/notifications?status=delivered&status=sending',
|
'/notifications?status=delivered&status=sending',
|
||||||
headers=[auth_header])
|
headers=[auth_header]
|
||||||
|
)
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
notifications = json.loads(response.get_data(as_text=True))
|
notifications = json.loads(response.get_data(as_text=True))
|
||||||
assert len(notifications['notifications']) == 2
|
assert len(notifications['notifications']) == 2
|
||||||
set(['delivered', 'sending']) == set(
|
assert {'delivered', 'sending'} == set(x['status'] for x in notifications['notifications'])
|
||||||
[x['status'] for x in notifications['notifications']])
|
|
||||||
|
|
||||||
|
|
||||||
def test_filter_by_status_and_template_type(client,
|
def test_filter_by_status_and_template_type(client, sample_template, sample_email_template):
|
||||||
notify_db,
|
notification_1 = create_notification(sample_template)
|
||||||
notify_db_session,
|
notification_2 = create_notification(sample_email_template)
|
||||||
sample_template,
|
notification_3 = create_notification(sample_email_template, status="delivered")
|
||||||
sample_email_template):
|
|
||||||
notification_1 = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
service=sample_email_template.service,
|
|
||||||
template=sample_template)
|
|
||||||
notification_2 = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
service=sample_email_template.service,
|
|
||||||
template=sample_email_template)
|
|
||||||
notification_3 = create_sample_notification(
|
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
service=sample_email_template.service,
|
|
||||||
template=sample_email_template,
|
|
||||||
status="delivered")
|
|
||||||
|
|
||||||
auth_header = create_authorization_header(service_id=sample_email_template.service_id)
|
auth_header = create_authorization_header(service_id=sample_email_template.service_id)
|
||||||
|
|
||||||
@@ -625,15 +538,9 @@ def test_filter_by_status_and_template_type(client,
|
|||||||
assert notifications['notifications'][0]['status'] == 'delivered'
|
assert notifications['notifications'][0]['status'] == 'delivered'
|
||||||
|
|
||||||
|
|
||||||
def test_get_notification_by_id_returns_merged_template_content(notify_db,
|
def test_get_notification_by_id_returns_merged_template_content(client, sample_template_with_placeholders):
|
||||||
notify_db_session,
|
|
||||||
client,
|
|
||||||
sample_template_with_placeholders):
|
|
||||||
|
|
||||||
sample_notification = create_sample_notification(notify_db,
|
sample_notification = create_notification(sample_template_with_placeholders, personalisation={"name": "world"})
|
||||||
notify_db_session,
|
|
||||||
template=sample_template_with_placeholders,
|
|
||||||
personalisation={"name": "world"})
|
|
||||||
|
|
||||||
auth_header = create_authorization_header(service_id=sample_notification.service_id)
|
auth_header = create_authorization_header(service_id=sample_notification.service_id)
|
||||||
|
|
||||||
@@ -649,15 +556,13 @@ def test_get_notification_by_id_returns_merged_template_content(notify_db,
|
|||||||
|
|
||||||
|
|
||||||
def test_get_notification_by_id_returns_merged_template_content_for_email(
|
def test_get_notification_by_id_returns_merged_template_content_for_email(
|
||||||
notify_db,
|
|
||||||
notify_db_session,
|
|
||||||
client,
|
client,
|
||||||
sample_email_template_with_placeholders
|
sample_email_template_with_placeholders
|
||||||
):
|
):
|
||||||
sample_notification = create_sample_notification(notify_db,
|
sample_notification = create_notification(
|
||||||
notify_db_session,
|
sample_email_template_with_placeholders,
|
||||||
template=sample_email_template_with_placeholders,
|
personalisation={"name": "world"}
|
||||||
personalisation={"name": "world"})
|
)
|
||||||
auth_header = create_authorization_header(service_id=sample_notification.service_id)
|
auth_header = create_authorization_header(service_id=sample_notification.service_id)
|
||||||
|
|
||||||
response = client.get(
|
response = client.get(
|
||||||
|
|||||||
@@ -1362,24 +1362,20 @@ def test_get_all_notifications_for_service_including_ones_made_by_jobs(
|
|||||||
|
|
||||||
|
|
||||||
def test_get_only_api_created_notifications_for_service(
|
def test_get_only_api_created_notifications_for_service(
|
||||||
client,
|
admin_request,
|
||||||
notify_db,
|
sample_job,
|
||||||
notify_db_session,
|
sample_template
|
||||||
sample_service
|
|
||||||
):
|
):
|
||||||
with_job = sample_notification_with_job(notify_db, notify_db_session, service=sample_service)
|
with_job = create_notification(sample_template, job=sample_job)
|
||||||
without_job = create_sample_notification(notify_db, notify_db_session, service=sample_service)
|
without_job = create_notification(sample_template)
|
||||||
|
|
||||||
auth_header = create_authorization_header()
|
resp = admin_request.get(
|
||||||
|
'service.get_all_notifications_for_service',
|
||||||
response = client.get(
|
service_id=sample_template.service_id,
|
||||||
path='/service/{}/notifications?include_jobs=false'.format(sample_service.id),
|
include_jobs=False
|
||||||
headers=[auth_header])
|
)
|
||||||
|
|
||||||
resp = json.loads(response.get_data(as_text=True))
|
|
||||||
assert len(resp['notifications']) == 1
|
assert len(resp['notifications']) == 1
|
||||||
assert resp['notifications'][0]['id'] == str(without_job.id)
|
assert resp['notifications'][0]['id'] == str(without_job.id)
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
def test_set_sms_sender_for_service(client, sample_service):
|
def test_set_sms_sender_for_service(client, sample_service):
|
||||||
|
|||||||
+46
-9
@@ -6,6 +6,7 @@ from app import encryption
|
|||||||
from app.models import (
|
from app.models import (
|
||||||
ServiceWhitelist,
|
ServiceWhitelist,
|
||||||
Notification,
|
Notification,
|
||||||
|
SMS_TYPE,
|
||||||
MOBILE_TYPE,
|
MOBILE_TYPE,
|
||||||
EMAIL_TYPE,
|
EMAIL_TYPE,
|
||||||
NOTIFICATION_CREATED,
|
NOTIFICATION_CREATED,
|
||||||
@@ -18,6 +19,7 @@ from tests.app.conftest import (
|
|||||||
sample_template as create_sample_template,
|
sample_template as create_sample_template,
|
||||||
sample_notification_with_job as create_sample_notification_with_job
|
sample_notification_with_job as create_sample_notification_with_job
|
||||||
)
|
)
|
||||||
|
from tests.app.db import create_notification
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('mobile_number', [
|
@pytest.mark.parametrize('mobile_number', [
|
||||||
@@ -148,21 +150,56 @@ def test_notification_for_csv_returns_bst_correctly(notify_db, notify_db_session
|
|||||||
assert serialized['created_at'] == 'Monday 27 March 2017 at 00:01'
|
assert serialized['created_at'] == 'Monday 27 March 2017 at 00:01'
|
||||||
|
|
||||||
|
|
||||||
def test_notification_personalisation_getter_returns_empty_dict_from_None(sample_notification):
|
def test_notification_personalisation_getter_returns_empty_dict_from_None():
|
||||||
sample_notification._personalisation = None
|
noti = Notification()
|
||||||
assert sample_notification.personalisation == {}
|
noti._personalisation = None
|
||||||
|
assert noti.personalisation == {}
|
||||||
|
|
||||||
|
|
||||||
def test_notification_personalisation_getter_always_returns_empty_dict(sample_notification):
|
def test_notification_personalisation_getter_always_returns_empty_dict():
|
||||||
sample_notification._personalisation = encryption.encrypt({})
|
noti = Notification()
|
||||||
assert sample_notification.personalisation == {}
|
noti._personalisation = encryption.encrypt({})
|
||||||
|
assert noti.personalisation == {}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('input_value', [
|
@pytest.mark.parametrize('input_value', [
|
||||||
None,
|
None,
|
||||||
{}
|
{}
|
||||||
])
|
])
|
||||||
def test_notification_personalisation_setter_always_sets_empty_dict(sample_notification, input_value):
|
def test_notification_personalisation_setter_always_sets_empty_dict(input_value):
|
||||||
sample_notification.personalisation = input_value
|
noti = Notification()
|
||||||
|
noti.personalisation = input_value
|
||||||
|
|
||||||
assert sample_notification._personalisation == encryption.encrypt({})
|
assert noti._personalisation == encryption.encrypt({})
|
||||||
|
|
||||||
|
|
||||||
|
def test_notification_subject_is_none_for_sms():
|
||||||
|
assert Notification(notification_type=SMS_TYPE).subject is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_notification_subject_fills_in_placeholders_for_email(sample_email_template_with_placeholders):
|
||||||
|
noti = create_notification(sample_email_template_with_placeholders, personalisation={'name': 'hello'})
|
||||||
|
assert noti.subject == 'hello'
|
||||||
|
|
||||||
|
|
||||||
|
def test_notification_subject_fills_in_placeholders_for_letter(sample_letter_template):
|
||||||
|
sample_letter_template.subject = '((name))'
|
||||||
|
noti = create_notification(sample_letter_template, personalisation={'name': 'hello'})
|
||||||
|
assert noti.subject == 'hello'
|
||||||
|
|
||||||
|
|
||||||
|
def test_letter_notification_serializes_with_address(client, sample_letter_notification):
|
||||||
|
sample_letter_notification.personalisation = {
|
||||||
|
'address_line_1': 'foo',
|
||||||
|
'address_line_3': 'bar',
|
||||||
|
'address_line_5': None,
|
||||||
|
'postcode': 'SW1 1AA'
|
||||||
|
}
|
||||||
|
res = sample_letter_notification.serialize()
|
||||||
|
assert res['line_1'] == 'foo'
|
||||||
|
assert res['line_2'] is None
|
||||||
|
assert res['line_3'] == 'bar'
|
||||||
|
assert res['line_4'] is None
|
||||||
|
assert res['line_5'] is None
|
||||||
|
assert res['line_6'] is None
|
||||||
|
assert res['postcode'] == 'SW1 1AA'
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ def test_post_sms_schema_with_personalisation_that_is_not_a_dict():
|
|||||||
error = json.loads(str(e.value))
|
error = json.loads(str(e.value))
|
||||||
assert len(error.get('errors')) == 1
|
assert len(error.get('errors')) == 1
|
||||||
assert error['errors'] == [{'error': 'ValidationError',
|
assert error['errors'] == [{'error': 'ValidationError',
|
||||||
'message': "personalisation should contain key value pairs"}]
|
'message': "personalisation not_a_dict is not of type object"}]
|
||||||
assert error.get('status_code') == 400
|
assert error.get('status_code') == 400
|
||||||
assert len(error.keys()) == 2
|
assert len(error.keys()) == 2
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,34 @@
|
|||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from flask import url_for, json
|
from flask import json
|
||||||
|
from flask import url_for
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from app.models import Job, Notification, SMS_TYPE, EMAIL_TYPE, LETTER_TYPE
|
from app.models import EMAIL_TYPE
|
||||||
|
from app.models import Job
|
||||||
|
from app.models import KEY_TYPE_NORMAL
|
||||||
|
from app.models import KEY_TYPE_TEAM
|
||||||
|
from app.models import KEY_TYPE_TEST
|
||||||
|
from app.models import LETTER_TYPE
|
||||||
|
from app.models import Notification
|
||||||
|
from app.models import SMS_TYPE
|
||||||
from app.v2.errors import RateLimitError
|
from app.v2.errors import RateLimitError
|
||||||
|
from app.variables import LETTER_TEST_API_FILENAME
|
||||||
|
from app.variables import LETTER_API_FILENAME
|
||||||
|
|
||||||
from tests import create_authorization_header
|
from tests import create_authorization_header
|
||||||
from tests.app.db import create_service, create_template
|
from tests.app.db import create_service
|
||||||
|
from tests.app.db import create_template
|
||||||
|
|
||||||
|
|
||||||
pytestmark = pytest.mark.skip('Leters not currently implemented')
|
def letter_request(client, data, service_id, key_type=KEY_TYPE_NORMAL, _expected_status=201):
|
||||||
|
|
||||||
|
|
||||||
def letter_request(client, data, service_id, _expected_status=201):
|
|
||||||
resp = client.post(
|
resp = client.post(
|
||||||
url_for('v2_notifications.post_notification', notification_type='letter'),
|
url_for('v2_notifications.post_notification', notification_type='letter'),
|
||||||
data=json.dumps(data),
|
data=json.dumps(data),
|
||||||
headers=[('Content-Type', 'application/json'), create_authorization_header(service_id=service_id)]
|
headers=[
|
||||||
|
('Content-Type', 'application/json'),
|
||||||
|
create_authorization_header(service_id=service_id, key_type=key_type)
|
||||||
|
]
|
||||||
)
|
)
|
||||||
json_resp = json.loads(resp.get_data(as_text=True))
|
json_resp = json.loads(resp.get_data(as_text=True))
|
||||||
assert resp.status_code == _expected_status, json_resp
|
assert resp.status_code == _expected_status, json_resp
|
||||||
@@ -45,7 +55,8 @@ def test_post_letter_notification_returns_201(client, sample_letter_template, mo
|
|||||||
resp_json = letter_request(client, data, service_id=sample_letter_template.service_id)
|
resp_json = letter_request(client, data, service_id=sample_letter_template.service_id)
|
||||||
|
|
||||||
job = Job.query.one()
|
job = Job.query.one()
|
||||||
notification = Notification.query.all()
|
assert job.original_file_name == LETTER_API_FILENAME
|
||||||
|
notification = Notification.query.one()
|
||||||
notification_id = notification.id
|
notification_id = notification.id
|
||||||
assert resp_json['id'] == str(notification_id)
|
assert resp_json['id'] == str(notification_id)
|
||||||
assert resp_json['reference'] == reference
|
assert resp_json['reference'] == reference
|
||||||
@@ -62,51 +73,33 @@ def test_post_letter_notification_returns_201(client, sample_letter_template, mo
|
|||||||
)
|
)
|
||||||
assert not resp_json['scheduled_for']
|
assert not resp_json['scheduled_for']
|
||||||
|
|
||||||
mocked.assert_called_once_with((str(job.id), ), queue='job-tasks')
|
mocked.assert_called_once_with([str(job.id)], queue='job-tasks')
|
||||||
|
|
||||||
|
|
||||||
def test_post_letter_notification_returns_400_and_missing_template(
|
def test_post_letter_notification_returns_400_and_missing_template(
|
||||||
client,
|
client,
|
||||||
sample_service
|
sample_service_full_permissions
|
||||||
):
|
):
|
||||||
data = {
|
data = {
|
||||||
'template_id': str(uuid.uuid4()),
|
'template_id': str(uuid.uuid4()),
|
||||||
'personalisation': {'address_line_1': '', 'postcode': ''}
|
'personalisation': {'address_line_1': '', 'postcode': ''}
|
||||||
}
|
}
|
||||||
|
|
||||||
error_json = letter_request(client, data, service_id=sample_service.id, _expected_status=400)
|
error_json = letter_request(client, data, service_id=sample_service_full_permissions.id, _expected_status=400)
|
||||||
|
|
||||||
assert error_json['status_code'] == 400
|
assert error_json['status_code'] == 400
|
||||||
assert error_json['errors'] == [{'error': 'BadRequestError', 'message': 'Template not found'}]
|
assert error_json['errors'] == [{'error': 'BadRequestError', 'message': 'Template not found'}]
|
||||||
|
|
||||||
|
|
||||||
def test_post_notification_returns_403_and_well_formed_auth_error(
|
|
||||||
client,
|
|
||||||
sample_letter_template
|
|
||||||
):
|
|
||||||
data = {
|
|
||||||
'template_id': str(sample_letter_template.id),
|
|
||||||
'personalisation': {'address_line_1': '', 'postcode': ''}
|
|
||||||
}
|
|
||||||
|
|
||||||
error_json = letter_request(client, data, service_id=sample_letter_template.service_id, _expected_status=401)
|
|
||||||
|
|
||||||
assert error_json['status_code'] == 401
|
|
||||||
assert error_json['errors'] == [{
|
|
||||||
'error': 'AuthError',
|
|
||||||
'message': 'Unauthorized, authentication token must be provided'
|
|
||||||
}]
|
|
||||||
|
|
||||||
|
|
||||||
def test_notification_returns_400_for_schema_problems(
|
def test_notification_returns_400_for_schema_problems(
|
||||||
client,
|
client,
|
||||||
sample_service
|
sample_service_full_permissions
|
||||||
):
|
):
|
||||||
data = {
|
data = {
|
||||||
'personalisation': {'address_line_1': '', 'postcode': ''}
|
'personalisation': {'address_line_1': '', 'postcode': ''}
|
||||||
}
|
}
|
||||||
|
|
||||||
error_json = letter_request(client, data, service_id=sample_service.id, _expected_status=400)
|
error_json = letter_request(client, data, service_id=sample_service_full_permissions.id, _expected_status=400)
|
||||||
|
|
||||||
assert error_json['status_code'] == 400
|
assert error_json['status_code'] == 400
|
||||||
assert error_json['errors'] == [{
|
assert error_json['errors'] == [{
|
||||||
@@ -115,6 +108,27 @@ def test_notification_returns_400_for_schema_problems(
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
|
|
||||||
|
def test_notification_returns_400_if_address_doesnt_have_underscores(
|
||||||
|
client,
|
||||||
|
sample_letter_template
|
||||||
|
):
|
||||||
|
data = {
|
||||||
|
'template_id': str(sample_letter_template.id),
|
||||||
|
'personalisation': {
|
||||||
|
'address line 1': 'Her Royal Highness Queen Elizabeth II',
|
||||||
|
'postcode': 'SW1 1AA',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_json = letter_request(client, data, service_id=sample_letter_template.service_id, _expected_status=400)
|
||||||
|
|
||||||
|
assert error_json['status_code'] == 400
|
||||||
|
assert error_json['errors'] == [{
|
||||||
|
'error': 'ValidationError',
|
||||||
|
'message': 'personalisation address_line_1 is a required property'
|
||||||
|
}]
|
||||||
|
|
||||||
|
|
||||||
def test_returns_a_429_limit_exceeded_if_rate_limit_exceeded(
|
def test_returns_a_429_limit_exceeded_if_rate_limit_exceeded(
|
||||||
client,
|
client,
|
||||||
sample_letter_template,
|
sample_letter_template,
|
||||||
@@ -160,7 +174,55 @@ def test_post_letter_notification_returns_403_if_not_allowed_to_send_notificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
error_json = letter_request(client, data, service_id=service.id, _expected_status=400)
|
error_json = letter_request(client, data, service_id=service.id, _expected_status=400)
|
||||||
assert error_json['status_code'] == 403
|
assert error_json['status_code'] == 400
|
||||||
assert error_json['errors'] == [
|
assert error_json['errors'] == [
|
||||||
{'error': 'BadRequestError', 'message': 'Cannot send letters'}
|
{'error': 'BadRequestError', 'message': 'Cannot send letters'}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('research_mode, key_type', [
|
||||||
|
(True, KEY_TYPE_NORMAL),
|
||||||
|
(False, KEY_TYPE_TEST)
|
||||||
|
])
|
||||||
|
def test_post_letter_notification_doesnt_queue_task(
|
||||||
|
client,
|
||||||
|
notify_db_session,
|
||||||
|
mocker,
|
||||||
|
research_mode,
|
||||||
|
key_type
|
||||||
|
):
|
||||||
|
real_task = mocker.patch('app.celery.tasks.build_dvla_file.apply_async')
|
||||||
|
fake_task = mocker.patch('app.celery.tasks.update_job_to_sent_to_dvla.apply_async')
|
||||||
|
|
||||||
|
service = create_service(research_mode=research_mode, service_permissions=[LETTER_TYPE])
|
||||||
|
template = create_template(service, template_type=LETTER_TYPE)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'template_id': str(template.id),
|
||||||
|
'personalisation': {'address_line_1': 'Foo', 'postcode': 'Bar'}
|
||||||
|
}
|
||||||
|
|
||||||
|
letter_request(client, data, service_id=service.id, key_type=key_type)
|
||||||
|
|
||||||
|
job = Job.query.one()
|
||||||
|
assert job.original_file_name == LETTER_TEST_API_FILENAME
|
||||||
|
assert not real_task.called
|
||||||
|
fake_task.assert_called_once_with([str(job.id)], queue='research-mode-tasks')
|
||||||
|
|
||||||
|
|
||||||
|
def test_post_letter_notification_doesnt_accept_team_key(client, sample_letter_template):
|
||||||
|
data = {
|
||||||
|
'template_id': str(sample_letter_template.id),
|
||||||
|
'personalisation': {'address_line_1': 'Foo', 'postcode': 'Bar'}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_json = letter_request(
|
||||||
|
client,
|
||||||
|
data,
|
||||||
|
sample_letter_template.service_id,
|
||||||
|
key_type=KEY_TYPE_TEAM,
|
||||||
|
_expected_status=403
|
||||||
|
)
|
||||||
|
|
||||||
|
assert error_json['status_code'] == 403
|
||||||
|
assert error_json['errors'] == [{'error': 'BadRequestError', 'message': 'Cannot send letters with a team api key'}]
|
||||||
|
|||||||
@@ -80,10 +80,12 @@ def test_post_notification_returns_400_and_missing_template(client, sample_servi
|
|||||||
"message": 'Template not found'}]
|
"message": 'Template not found'}]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("notification_type, key_send_to, send_to",
|
@pytest.mark.parametrize("notification_type, key_send_to, send_to", [
|
||||||
[("sms", "phone_number", "+447700900855"),
|
("sms", "phone_number", "+447700900855"),
|
||||||
("email", "email_address", "sample@email.com")])
|
("email", "email_address", "sample@email.com"),
|
||||||
def test_post_notification_returns_403_and_well_formed_auth_error(client, sample_template,
|
("letter", "personalisation", {"address_line_1": "The queen", "postcode": "SW1 1AA"})
|
||||||
|
])
|
||||||
|
def test_post_notification_returns_401_and_well_formed_auth_error(client, sample_template,
|
||||||
notification_type, key_send_to, send_to):
|
notification_type, key_send_to, send_to):
|
||||||
data = {
|
data = {
|
||||||
key_send_to: send_to,
|
key_send_to: send_to,
|
||||||
|
|||||||
@@ -51,11 +51,18 @@ valid_json_post_args = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
invalid_json_post_args = [
|
invalid_json_post_args = [
|
||||||
({"id": "invalid_uuid", "personalisation": {"key": "value"}}, ["id is not a valid UUID"]),
|
(
|
||||||
({"id": str(uuid.uuid4()), "personalisation": "invalid_personalisation"},
|
{"id": "invalid_uuid", "personalisation": {"key": "value"}},
|
||||||
["personalisation should contain key value pairs"]),
|
["id is not a valid UUID"]
|
||||||
({"personalisation": "invalid_personalisation"},
|
),
|
||||||
["id is a required property", "personalisation should contain key value pairs"])
|
(
|
||||||
|
{"id": str(uuid.uuid4()), "personalisation": ['a', 'b']},
|
||||||
|
["personalisation [a, b] is not of type object"]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{"personalisation": "invalid_personalisation"},
|
||||||
|
["id is a required property", "personalisation invalid_personalisation is not of type object"]
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
valid_json_post_response = {
|
valid_json_post_response = {
|
||||||
|
|||||||
Reference in New Issue
Block a user