diff --git a/Makefile b/Makefile index 6574c6181..e168fe649 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,6 @@ bootstrap: ## Set up everything to run the app poetry install --sync --no-root poetry run pre-commit install createdb notification_api || true - createdb test_notification_api || true (poetry run flask db upgrade) || true .PHONY: bootstrap-with-docker diff --git a/app/dao/notifications_dao.py b/app/dao/notifications_dao.py index f00ae4a9b..4c884ae8b 100644 --- a/app/dao/notifications_dao.py +++ b/app/dao/notifications_dao.py @@ -15,6 +15,7 @@ from app.utils import ( escape_special_characters, get_midnight_in_utc, + hilite, midnight_n_days_ago, ) from notifications_utils.international_billing_rates import INTERNATIONAL_BILLING_RATES @@ -53,6 +54,7 @@ def dao_get_last_date_template_was_used(template_id, service_id): @autocommit def dao_create_notification(notification): + print(hilite("about to add noti to db")) if not notification.id: # need to populate defaulted fields before we create the notification history object notification.id = create_uuid() @@ -71,6 +73,7 @@ def dao_create_notification(notification): notification.to = "1" notification.normalised_to = "1" db.session.add(notification) + print(hilite("added noti to db")) def country_records_delivery(phone_prefix): @@ -671,3 +674,10 @@ def get_service_ids_with_notifications_on_date(notification_type, date): union(notification_table_query, ft_status_table_query).subquery() ).distinct() } + + +def dao_get_notification_message_parts_by_job_id(job_id): + total_message_parts = db.session.query( + functions.sum(Notification.message_parts.label("message_parts")) + ).filter(Notification.job_id == job_id) + return total_message_parts diff --git a/app/job/rest.py b/app/job/rest.py index 85414a29c..f4ea3ba30 100644 --- a/app/job/rest.py +++ b/app/job/rest.py @@ -108,7 +108,6 @@ def get_all_notifications_for_service_job(service_id, job_id): notifications = notification_with_template_schema.dump( paginated_notifications.items, many=True ) - return ( jsonify( notifications=notifications, @@ -204,17 +203,23 @@ def create_job(service_id): dao_create_job(job) + job_json = job_schema.dump(job) + job_json["statistics"] = [] + + return jsonify(data=job_json), 201 + + +@job_blueprint.route("//start-job", methods=["POST"]) +def start_job(service_id, job_id): + job = dao_get_job_by_service_id_and_job_id(service_id, job_id) + data = request.get_json() sender_id = data.get("sender_id") # Kick off job in tasks.py if job.job_status == JobStatus.PENDING: process_job.apply_async( [str(job.id)], {"sender_id": sender_id}, queue=QueueNames.JOBS ) - - job_json = job_schema.dump(job) - job_json["statistics"] = [] - - return jsonify(data=job_json), 201 + return {}, 201 @job_blueprint.route("/scheduled-job-stats", methods=["GET"]) diff --git a/app/models.py b/app/models.py index 71eea3295..227a0a108 100644 --- a/app/models.py +++ b/app/models.py @@ -1503,6 +1503,7 @@ class Notification(db.Model): created_at = db.Column(db.DateTime, index=True, unique=False, nullable=False) sent_at = db.Column(db.DateTime, index=False, unique=False, nullable=True) sent_by = db.Column(db.String, nullable=True) + message_parts = db.Column(db.Integer, nullable=True) updated_at = db.Column( db.DateTime, index=False, @@ -1743,6 +1744,7 @@ def serialize(self): "sent_at": get_dt_string_or_none(self.sent_at), "completed_at": self.completed_at(), "scheduled_for": None, + "message_parts": self.message_parts, } return serialized diff --git a/app/notifications/process_notifications.py b/app/notifications/process_notifications.py index 8f542d31a..f386d0708 100644 --- a/app/notifications/process_notifications.py +++ b/app/notifications/process_notifications.py @@ -10,8 +10,10 @@ dao_create_notification, dao_delete_notifications_by_id, ) +from app.dao.templates_dao import dao_get_template_by_id_and_service_id from app.enums import KeyType, NotificationStatus, NotificationType from app.models import Notification +from app.utils import hilite from app.v2.errors import BadRequestError from notifications_utils.recipients import ( format_email_address, @@ -22,6 +24,7 @@ def create_content_for_notification(template, personalisation): + print(f"enter create_content_for_notification {template.id} {personalisation}") if template.template_type == NotificationType.EMAIL: template_object = PlainTextEmailTemplate( { @@ -31,6 +34,7 @@ def create_content_for_notification(template, personalisation): }, personalisation, ) + print("created email template object") if template.template_type == NotificationType.SMS: template_object = SMSMessageTemplate( { @@ -50,6 +54,7 @@ def check_placeholders(template_object): message = "Missing personalisation: {}".format( ", ".join(template_object.missing_data) ) + print(f"GOING TO RAISE BAD REQUEST ERROR WITH {message}") raise BadRequestError(fields=[{"template": message}], message=message) @@ -105,6 +110,8 @@ def persist_notification( document_download_count=document_download_count, updated_at=updated_at, ) + print(hilite(f"personalisation? {personalisation}")) + print(hilite(f"notification? {notification}")) if notification_type == NotificationType.SMS: formatted_recipient = validate_and_format_phone_number( @@ -117,6 +124,7 @@ def persist_notification( notification.rate_multiplier = recipient_info.billable_units elif notification_type == NotificationType.EMAIL: + print(hilite("inside elif for email type")) current_app.logger.info( f"Persisting notification with type: {NotificationType.EMAIL}" ) @@ -125,11 +133,29 @@ def persist_notification( format_email_address(notification.to), ex=1800, ) - + print(hilite(f"simulated? {simulated}")) # if simulated create a Notification model to return but do not persist the Notification to the dB if not simulated: current_app.logger.info("Firing dao_create_notification") - dao_create_notification(notification) + print( + f"LOOK UP TEMPLATE WITH TEMPLATE_ID {template_id} and service_id {service.id}" + ) + template = dao_get_template_by_id_and_service_id(template_id, service.id) + print(hilite(f"created template?: {template} personalization {notification.personalisation}")) + template_object = create_content_for_notification( + template, notification.personalisation + ) + print(hilite(f"template object? {template_object}")) + if isinstance(template_object, SMSMessageTemplate): + print(f"MESSAGE PARTS {template_object.fragment_count}") + notification.message_parts = template_object.fragment_count + print("GOING TO CREATE NOTIFICATION") + try: + dao_create_notification(notification) + except BaseException as be: + print(be) + + print(hilite("created notification?")) if key_type != KeyType.TEST and current_app.config["REDIS_ENABLED"]: current_app.logger.info( "Redis enabled, querying cache key for service id: {}".format( diff --git a/app/notifications/rest.py b/app/notifications/rest.py index 9c5806ede..848b5e5a3 100644 --- a/app/notifications/rest.py +++ b/app/notifications/rest.py @@ -233,3 +233,11 @@ def create_template_object_for_notification(template, personalisation): errors = {"content": [message]} raise InvalidRequest(errors, status_code=400) return template_object + + +@notifications.route("/notifications//message_parts", methods=["GET"]) +def get_batch_notification_message_parts_by_job_id(job_id): + total_message_parts = ( + notifications_dao.dao_get_notification_message_parts_by_job_id(job_id=job_id) + ) + return jsonify(total_message_parts=total_message_parts), 200 diff --git a/app/organization/invite_rest.py b/app/organization/invite_rest.py index f87605435..360d85d26 100644 --- a/app/organization/invite_rest.py +++ b/app/organization/invite_rest.py @@ -27,6 +27,7 @@ post_update_invited_org_user_status_schema, ) from app.schema_validation import validate +from app.utils import hilite from notifications_utils.url_safe_token import check_token, generate_token organization_invite_blueprint = Blueprint("organization_invite", __name__) @@ -38,20 +39,21 @@ "/organization//invite", methods=["POST"] ) def invite_user_to_org(organization_id): + print(hilite("top of org method")) data = request.get_json() validate(data, post_create_invited_org_user_status_schema) - + print(hilite(f"got the data: {data}")) invited_org_user = InvitedOrganizationUser( email_address=data["email_address"], invited_by_id=data["invited_by"], organization_id=organization_id, ) save_invited_org_user(invited_org_user) - + print(hilite("saved the data")) template = dao_get_template_by_id( current_app.config["ORGANIZATION_INVITATION_EMAIL_TEMPLATE_ID"] ) - + print(hilite("got the template")) token = generate_token( str(invited_org_user.email_address), current_app.config["SECRET_KEY"], @@ -70,19 +72,29 @@ def invite_user_to_org(organization_id): "organization_name": invited_org_user.organization.name, "url": url, } + print(hilite(f"personalisation: {personalisation}")) + db_personalisation = personalisation + if db_personalisation.get("phone_number"): + del db_personalisation["phone_number"] + if db_personalisation.get("email_address"): + del db_personalisation["email_address"] + # try: saved_notification = persist_notification( template_id=template.id, template_version=template.version, recipient=invited_org_user.email_address, service=template.service, - personalisation={}, + personalisation=db_personalisation, notification_type=NotificationType.EMAIL, api_key_id=None, key_type=KeyType.NORMAL, reply_to_text=invited_org_user.invited_by.email_address, ) - + # except BaseException as be: + # print(hilite(be)) + print(hilite(f"saved notification: {saved_notification}")) saved_notification.personalisation = personalisation + print(hilite(f"saved notification after personalisation: {saved_notification}")) redis_store.set( f"email-personalisation-{saved_notification.id}", json.dumps(personalisation), @@ -90,7 +102,7 @@ def invite_user_to_org(organization_id): ) send_notification_to_queue(saved_notification, queue=QueueNames.NOTIFY) - + print(hilite("sent notification to queue")) return jsonify(data=invited_org_user.serialize()), 201 diff --git a/app/organization/rest.py b/app/organization/rest.py index 8da757cbc..705058ab7 100644 --- a/app/organization/rest.py +++ b/app/organization/rest.py @@ -200,13 +200,17 @@ def send_notifications_on_mou_signed(organization_id): def _send_notification(template_id, recipient, personalisation): template = dao_get_template_by_id(template_id) - + db_personalisation = personalisation + if db_personalisation.get("phone_number"): + del db_personalisation["phone_number"] + if db_personalisation.get("email_address"): + del db_personalisation["email_address"] saved_notification = persist_notification( template_id=template.id, template_version=template.version, recipient=recipient, service=notify_service, - personalisation={}, + personalisation=db_personalisation, notification_type=template.template_type, api_key_id=None, key_type=KeyType.NORMAL, diff --git a/app/service/sender.py b/app/service/sender.py index 4b954f60b..a7cec6c84 100644 --- a/app/service/sender.py +++ b/app/service/sender.py @@ -11,12 +11,15 @@ persist_notification, send_notification_to_queue, ) +from app.utils import hilite def send_notification_to_service_users( service_id, template_id, personalisation=None, include_user_fields=None ): + print(f"SERVICE ID {service_id} TEMPLATE_ID {template_id}") personalisation = personalisation or {} + print(hilite(f"personalisation {personalisation}")) include_user_fields = include_user_fields or [] template = dao_get_template_by_id(template_id) service = dao_fetch_service_by_id(service_id) @@ -25,6 +28,7 @@ def send_notification_to_service_users( for user in active_users: personalisation = _add_user_fields(user, personalisation, include_user_fields) + print(hilite(f"next personalisation {personalisation}")) notification = persist_notification( template_id=template.id, template_version=template.version, @@ -40,6 +44,7 @@ def send_notification_to_service_users( key_type=KeyType.NORMAL, reply_to_text=notify_service.get_default_reply_to_email_address(), ) + print(hilite("Persisted notification!")) send_notification_to_queue(notification, queue=QueueNames.NOTIFY) diff --git a/app/service_invite/rest.py b/app/service_invite/rest.py index 02899d3e9..3a12f83f7 100644 --- a/app/service_invite/rest.py +++ b/app/service_invite/rest.py @@ -75,12 +75,18 @@ def _create_service_invite(invited_user, invite_link_host): "url": url, } + db_personalisation = personalisation + if db_personalisation.get("phone_number"): + del db_personalisation["phone_number"] + if db_personalisation.get("email_address"): + del db_personalisation["email_address"] + saved_notification = persist_notification( template_id=template.id, template_version=template.version, recipient=invited_user.email_address, service=service, - personalisation={}, + personalisation=db_personalisation, notification_type=NotificationType.EMAIL, api_key_id=None, key_type=KeyType.NORMAL, diff --git a/app/user/rest.py b/app/user/rest.py index ea2da8eee..a48ffc136 100644 --- a/app/user/rest.py +++ b/app/user/rest.py @@ -386,6 +386,10 @@ def send_user_confirm_new_email(user_id): current_app.config["CHANGE_EMAIL_CONFIRMATION_TEMPLATE_ID"] ) service = Service.query.get(current_app.config["NOTIFY_SERVICE_ID"]) + # TODO writing this personalization to the db adds a little PII + # to the notifications table, but it will be purged after 7 days. + # If we don't want it to go into the db at all, we would need to + # turn this into a job and retrieve it from S3. personalisation = { "name": user_to_send_to.name, "url": _create_confirmation_url( @@ -398,7 +402,7 @@ def send_user_confirm_new_email(user_id): template_version=template.version, recipient=email["email"], service=service, - personalisation={}, + personalisation=personalisation, notification_type=template.template_type, api_key_id=None, key_type=KeyType.NORMAL, @@ -437,17 +441,19 @@ def send_new_user_email_verification(user_id): base_url=request_json.get("admin_base_url"), ), } + print("TRY TO SAVE NOTI") saved_notification = persist_notification( template_id=template.id, template_version=template.version, recipient=user_to_send_to.email_address, service=service, - personalisation={}, + personalisation=personalisation, notification_type=template.template_type, api_key_id=None, key_type=KeyType.NORMAL, reply_to_text=service.get_default_reply_to_email_address(), ) + print("SAVED THE NOTIFICATION") saved_notification.personalisation = personalisation redis_store.set( @@ -460,6 +466,7 @@ def send_new_user_email_verification(user_id): json.dumps(personalisation), ex=60 * 60, ) + print("SET REDIS") current_app.logger.info("Sending notification to queue") send_notification_to_queue(saved_notification, queue=QueueNames.NOTIFY) diff --git a/migrations/versions/0336_broadcast_msg_content_2.py b/migrations/versions/0336_broadcast_msg_content_2.py index a42cbc24e..014059d00 100644 --- a/migrations/versions/0336_broadcast_msg_content_2.py +++ b/migrations/versions/0336_broadcast_msg_content_2.py @@ -8,10 +8,11 @@ import sqlalchemy as sa from alembic import op -from notifications_utils.template import BroadcastMessageTemplate from sqlalchemy.dialects import postgresql from sqlalchemy.orm.session import Session +from notifications_utils.template import BroadcastMessageTemplate + revision = "0336_broadcast_msg_content_2" down_revision = "0335_broadcast_msg_content" diff --git a/migrations/versions/0412_add_message_parts.py b/migrations/versions/0412_add_message_parts.py new file mode 100644 index 000000000..5b52e2700 --- /dev/null +++ b/migrations/versions/0412_add_message_parts.py @@ -0,0 +1,21 @@ +""" + +Revision ID: 0412_add_message_parts +Revises: 0411_add_login_uuid + +""" + +import sqlalchemy as sa +from alembic import op +from flask import current_app + +down_revision = "0411_add_login_uuid" +revision = "0412_add_message_parts" + + +def upgrade(): + op.execute("ALTER TABLE notifications ADD COLUMN message_parts integer") + + +def downgrade(): + op.execute("ALTER TABLE notifications DROP COLUMN message_parts integer") diff --git a/notifications_utils/recipients.py b/notifications_utils/recipients.py index 0d8536c33..68e2cb101 100644 --- a/notifications_utils/recipients.py +++ b/notifications_utils/recipients.py @@ -17,9 +17,7 @@ strip_and_remove_obscure_whitespace, ) from notifications_utils.insensitive_dict import InsensitiveDict -from notifications_utils.international_billing_rates import ( - INTERNATIONAL_BILLING_RATES, -) +from notifications_utils.international_billing_rates import INTERNATIONAL_BILLING_RATES from notifications_utils.postal_address import ( address_line_7_key, address_lines_1_to_6_and_postcode_keys, diff --git a/notifications_utils/template.py b/notifications_utils/template.py index 302fd3899..ec112173f 100644 --- a/notifications_utils/template.py +++ b/notifications_utils/template.py @@ -43,10 +43,7 @@ notify_letter_preview_markdown, notify_plain_text_email_markdown, ) -from notifications_utils.postal_address import ( - PostalAddress, - address_lines_1_to_7_keys, -) +from notifications_utils.postal_address import PostalAddress, address_lines_1_to_7_keys from notifications_utils.sanitise_text import SanitiseSMS from notifications_utils.take import Take from notifications_utils.template_change import TemplateChange diff --git a/poetry.lock b/poetry.lock index ad8fafa23..983f545f4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiohttp" @@ -2079,13 +2079,9 @@ files = [ {file = "lxml-5.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:edcfa83e03370032a489430215c1e7783128808fd3e2e0a3225deee278585196"}, {file = "lxml-5.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:28bf95177400066596cdbcfc933312493799382879da504633d16cf60bba735b"}, {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a745cc98d504d5bd2c19b10c79c61c7c3df9222629f1b6210c0368177589fb8"}, - {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b590b39ef90c6b22ec0be925b211298e810b4856909c8ca60d27ffbca6c12e6"}, {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b336b0416828022bfd5a2e3083e7f5ba54b96242159f83c7e3eebaec752f1716"}, - {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:c2faf60c583af0d135e853c86ac2735ce178f0e338a3c7f9ae8f622fd2eb788c"}, {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:4bc6cb140a7a0ad1f7bc37e018d0ed690b7b6520ade518285dc3171f7a117905"}, - {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7ff762670cada8e05b32bf1e4dc50b140790909caa8303cfddc4d702b71ea184"}, {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:57f0a0bbc9868e10ebe874e9f129d2917750adf008fe7b9c1598c0fbbfdde6a6"}, - {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:a6d2092797b388342c1bc932077ad232f914351932353e2e8706851c870bca1f"}, {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:60499fe961b21264e17a471ec296dcbf4365fbea611bf9e303ab69db7159ce61"}, {file = "lxml-5.2.2-cp37-cp37m-win32.whl", hash = "sha256:d9b342c76003c6b9336a80efcc766748a333573abf9350f4094ee46b006ec18f"}, {file = "lxml-5.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b16db2770517b8799c79aa80f4053cd6f8b716f21f8aca962725a9565ce3ee40"}, @@ -2474,6 +2470,7 @@ files = [ {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, + {file = "msgpack-1.0.8-py3-none-any.whl", hash = "sha256:24f727df1e20b9876fa6e95f840a2a2651e34c0ad147676356f4bf5fbb0206ca"}, {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, ] @@ -3459,7 +3456,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, diff --git a/tests/app/job/test_rest.py b/tests/app/job/test_rest.py index 670a02ca3..a99c4ab23 100644 --- a/tests/app/job/test_rest.py +++ b/tests/app/job/test_rest.py @@ -80,8 +80,17 @@ def test_cant_cancel_normal_job(client, sample_job, mocker): assert mock_update.call_count == 0 -def test_create_unscheduled_job(client, sample_template, mocker, fake_uuid): +def test_start_job(client, mocker, fake_uuid): + mocker.patch("app.job.rest.dao_get_job_by_service_id_and_job_id") mocker.patch("app.celery.tasks.process_job.apply_async") + client.post(f"/{fake_uuid}/start-job") + + app.celery.tasks.process_job.apply_async.assert_called_once_with( + ([str(fake_uuid)]), {"sender_id": None}, queue="job-tasks" + ) + + +def test_create_unscheduled_job(client, sample_template, mocker, fake_uuid): mocker.patch( "app.job.rest.get_job_metadata_from_s3", return_value={ @@ -102,10 +111,6 @@ def test_create_unscheduled_job(client, sample_template, mocker, fake_uuid): response = client.post(path, data=json.dumps(data), headers=headers) assert response.status_code == 201 - app.celery.tasks.process_job.apply_async.assert_called_once_with( - ([str(fake_uuid)]), {"sender_id": None}, queue="job-tasks" - ) - resp_json = json.loads(response.get_data(as_text=True)) assert resp_json["data"]["id"] == fake_uuid @@ -121,7 +126,6 @@ def test_create_unscheduled_job(client, sample_template, mocker, fake_uuid): def test_create_unscheduled_job_with_sender_id_in_metadata( client, sample_template, mocker, fake_uuid ): - mocker.patch("app.celery.tasks.process_job.apply_async") mocker.patch( "app.job.rest.get_job_metadata_from_s3", return_value={ @@ -143,12 +147,6 @@ def test_create_unscheduled_job_with_sender_id_in_metadata( response = client.post(path, data=json.dumps(data), headers=headers) assert response.status_code == 201 - app.celery.tasks.process_job.apply_async.assert_called_once_with( - ([str(fake_uuid)]), - {"sender_id": fake_uuid}, - queue="job-tasks", - ) - @freeze_time("2016-01-01 12:00:00.000000") def test_create_scheduled_job(client, sample_template, mocker, fake_uuid): diff --git a/tests/app/organization/test_invite_rest.py b/tests/app/organization/test_invite_rest.py index 71e8c12ad..b5f434888 100644 --- a/tests/app/organization/test_invite_rest.py +++ b/tests/app/organization/test_invite_rest.py @@ -7,6 +7,7 @@ from app.enums import InvitedUserStatus from app.models import Notification +from app.utils import hilite from notifications_utils.url_safe_token import generate_token from tests import create_admin_authorization_header from tests.app.db import create_invited_org_user @@ -46,7 +47,7 @@ def test_create_invited_org_user( organization=str(sample_organization.id), email_address=email_address, invited_by=str(sample_user.id), - **extra_args + **extra_args, ) json_resp = admin_request.post( @@ -55,7 +56,7 @@ def test_create_invited_org_user( _data=data, _expected_status=201, ) - + print(hilite(f"{json_resp}")) assert json_resp["data"]["organization"] == str(sample_organization.id) assert json_resp["data"]["email_address"] == email_address assert json_resp["data"]["invited_by"] == str(sample_user.id) diff --git a/tests/app/service/test_sender.py b/tests/app/service/test_sender.py index caae265c8..6895ea615 100644 --- a/tests/app/service/test_sender.py +++ b/tests/app/service/test_sender.py @@ -5,6 +5,7 @@ from app.enums import NotificationType, TemplateType from app.models import Notification from app.service.sender import send_notification_to_service_users +from app.utils import hilite from tests.app.db import create_service, create_template, create_user @@ -16,9 +17,10 @@ def test_send_notification_to_service_users_persists_notifications_correctly( ): mocker.patch("app.service.sender.send_notification_to_queue") - template = create_template(sample_service, template_type=notification_type) + template = create_template(notify_service, template_type=notification_type) + print(hilite(f"heres my template? {template.id} service_id {notify_service.id}")) send_notification_to_service_users( - service_id=sample_service.id, template_id=template.id + service_id=notify_service.id, template_id=template.id ) notification = Notification.query.one() @@ -40,9 +42,9 @@ def test_send_notification_to_service_users_sends_to_queue( ): send_mock = mocker.patch("app.service.sender.send_notification_to_queue") - template = create_template(sample_service, template_type=NotificationType.EMAIL) + template = create_template(notify_service, template_type=NotificationType.EMAIL) send_notification_to_service_users( - service_id=sample_service.id, template_id=template.id + service_id=notify_service.id, template_id=template.id ) assert send_mock.called diff --git a/tests/app/user/test_rest.py b/tests/app/user/test_rest.py index a388d264e..031b894cd 100644 --- a/tests/app/user/test_rest.py +++ b/tests/app/user/test_rest.py @@ -632,137 +632,6 @@ def test_remove_user_folder_permissions(admin_request, sample_user, sample_servi assert service_user.folders == [] -@freeze_time("2016-01-01 11:09:00.061258") -def test_send_user_reset_password_should_send_reset_password_link( - admin_request, sample_user, mocker, password_reset_email_template -): - mocked = mocker.patch("app.celery.provider_tasks.deliver_email.apply_async") - data = {"email": sample_user.email_address} - notify_service = password_reset_email_template.service - - admin_request.post( - "user.send_user_reset_password", - _data=data, - _expected_status=204, - ) - - notification = Notification.query.first() - mocked.assert_called_once_with( - [str(notification.id)], queue="notify-internal-tasks" - ) - assert ( - notification.reply_to_text - == notify_service.get_default_reply_to_email_address() - ) - - -@pytest.mark.parametrize( - "data, expected_url", - ( - ( - { - "email": "notify@digital.fake.gov", - }, - ("http://localhost:6012/new-password/"), - ), - ( - { - "email": "notify@digital.fake.gov", - "admin_base_url": "https://different.example.com", - }, - ("https://different.example.com/new-password/"), - ), - ), -) -@freeze_time("2016-01-01 11:09:00.061258") -def test_send_user_reset_password_should_use_provided_base_url( - admin_request, - sample_user, - password_reset_email_template, - mocker, - data, - expected_url, -): - mocker.patch("app.celery.provider_tasks.deliver_email.apply_async") - - admin_request.post( - "user.send_user_reset_password", - _data=data, - _expected_status=204, - ) - - assert Notification.query.first().personalisation["url"].startswith(expected_url) - - -@freeze_time("2016-01-01 11:09:00.061258") -def test_send_user_reset_password_reset_password_link_contains_redirect_link_if_present_in_request( - admin_request, sample_user, mocker, password_reset_email_template -): - mocked = mocker.patch("app.celery.provider_tasks.deliver_email.apply_async") - data = {"email": sample_user.email_address, "next": "blob"} - - admin_request.post( - "user.send_user_reset_password", - _data=data, - _expected_status=204, - ) - - notification = Notification.query.first() - assert "?next=blob" in notification.content - mocked.assert_called_once_with( - [str(notification.id)], queue="notify-internal-tasks" - ) - - -def test_send_user_reset_password_should_return_400_when_email_is_missing( - admin_request, mocker -): - mocked = mocker.patch("app.celery.provider_tasks.deliver_email.apply_async") - data = {} - - json_resp = admin_request.post( - "user.send_user_reset_password", - _data=data, - _expected_status=400, - ) - assert json_resp["message"] == {"email": ["Missing data for required field."]} - assert mocked.call_count == 0 - - -def test_send_user_reset_password_should_return_400_when_user_doesnot_exist( - admin_request, mocker -): - mocked = mocker.patch("app.celery.provider_tasks.deliver_email.apply_async") - bad_email_address = "bad@email.gov.uk" - data = {"email": bad_email_address} - - json_resp = admin_request.post( - "user.send_user_reset_password", - _data=data, - _expected_status=404, - ) - - assert json_resp["message"] == "No result found" - assert mocked.call_count == 0 - - -def test_send_user_reset_password_should_return_400_when_data_is_not_email_address( - admin_request, mocker -): - mocked = mocker.patch("app.celery.provider_tasks.deliver_email.apply_async") - bad_email_address = "bad.email.gov.uk" - data = {"email": bad_email_address} - - json_resp = admin_request.post( - "user.send_user_reset_password", - _data=data, - _expected_status=400, - ) - - assert json_resp["message"] == {"email": ["Not a valid email address"]} - assert mocked.call_count == 0 - - def test_send_already_registered_email( admin_request, sample_user, already_registered_template, mocker ): diff --git a/tests/app/v2/notifications/test_get_notifications.py b/tests/app/v2/notifications/test_get_notifications.py index dd597404d..76e7b16c4 100644 --- a/tests/app/v2/notifications/test_get_notifications.py +++ b/tests/app/v2/notifications/test_get_notifications.py @@ -74,6 +74,7 @@ def test_get_notification_by_id_returns_200( "scheduled_for": None, "provider_response": None, "carrier": None, + "message_parts": None, } assert json_response == expected_response @@ -135,6 +136,7 @@ def test_get_notification_by_id_with_placeholders_returns_200( "scheduled_for": None, "provider_response": None, "carrier": None, + "message_parts": None, } assert json_response == expected_response