import json from flask import url_for from core_notifications.consts import SendingTaskStatus from tests.core_notifications.factories import TemplateFactory class TestEmailSend: def test_failure_authentication(self, app): url = url_for("api_v1.email_send") with app.test_client() as client: resp = client.post(url) assert resp.status_code == 401 def test_failure_authorization(self, app, authenticated): url = url_for("api_v1.email_send") with app.test_client() as client: resp = client.post(url) assert resp.status_code == 401 def test_success(self, app, mocker, faker, authorized_app): test_body = [ { "to": "test1@example.com", "subject": "some title", "body": "Hello world!", "campaign_id": "test_id", "track_clicks": True, }, { "subject": "some title", "to": ["test2@example.com", "test3@example.com"], "body": "Hello world!", "track_clicks": True, }, { "to": "test1@example.com", "subject": "some title", "body": "Hello world!", "cc": "test_cc1@example.com", "track_clicks": True, }, { "subject": "some title", "to": ["test2@example.com", "test3@example.com"], "body": "Hello world!", "cc": "test_cc1@example.com", "track_clicks": True, }, { "to": "test1@example.com", "subject": "some title", "body": "Hello world!", "cc": None, "track_clicks": True, }, { "subject": "some title", "to": ["test2@example.com", "test3@example.com"], "body": "Hello world!", "track_clicks": True, }, { "to": "test1@example.com", "subject": "some title", "body": "Hello world!", "cc": ["test_cc1@example.com", "test_cc2@example.com"], "track_clicks": True, }, { "to": "test_with_attachments@example.com", "subject": "some title", "body": "Please, check attachments", "track_clicks": True, "attachments": [ { "filename": "some_name.csv", "filetype": "text/csv", "base64_data": "some_data", } ], }, ] results_data = [ {"test1@example.com": faker.pystr()}, { "test2@example.com": faker.pystr(), "test3@example.com": faker.pystr(), }, {"test1@example.com": faker.pystr()}, { "test2@example.com": faker.pystr(), "test3@example.com": faker.pystr(), }, {"test1@example.com": faker.pystr()}, { "test2@example.com": faker.pystr(), "test3@example.com": faker.pystr(), }, {"test1@example.com": faker.pystr()}, {"test_with_attachments@example.com": faker.pystr()}, ] mocked_schedule_emails_batch = mocker.patch( "core_notifications.services.schedule_emails_batch" ) mocked_schedule_emails_batch.return_value = results_data url = url_for("api_v1.email_send") with app.test_client() as client: resp = client.post( url, data=json.dumps(test_body), content_type="application/json", ) assert mocked_schedule_emails_batch.call_args_list == [ mocker.call(test_body) ] assert resp.json == results_data def test_failure_validation_wrong_email(self, app, mocker, authorized_app): test_body = [ { "to": "test1_example.com", "subject": "some title", "body": "Hello world!", }, { "subject": "some title", "to": ["test2_example.com", "test3_example.com"], "body": "Hello world!", }, ] expected_response = { "detail": "The request was well-formed but was " "unable to be followed due to semantic errors.", "extra": { "json": { "0": { "to": [ "Not a valid email address: " "test1_example.com" ] }, "1": { "to": [ "Not a valid email address: " "test2_example.com" ] }, } }, "status_code": 422, } mocked_schedule_emails_batch = mocker.patch( "core_notifications.services.schedule_emails_batch" ) url = url_for("api_v1.email_send") with app.test_client() as client: resp = client.post( url, data=json.dumps(test_body), content_type="application/json", ) assert resp.json == expected_response assert not mocked_schedule_emails_batch.called def test_failure_validation_empty_fields( self, app, mocker, authorized_app ): test_body = [ {}, ] expected_response = { "detail": "The request was well-formed but was " "unable to be followed due to semantic errors.", "extra": { "json": { "0": { "to": ["Missing data for required field."], } } }, "status_code": 422, } mocked_schedule_emails_batch = mocker.patch( "core_notifications.services.schedule_emails_batch" ) url = url_for("api_v1.email_send") with app.test_client() as client: resp = client.post( url, data=json.dumps(test_body), content_type="application/json", ) assert resp.json == expected_response assert not mocked_schedule_emails_batch.called def test_failure_validation_no_template_or_body( self, app, mocker, faker, authorized_app ): test_body = [ {"to": faker.email(), "subject": faker.pystr()}, ] expected_response = { "detail": "The request was well-formed but was " "unable to be followed due to semantic errors.", "extra": { "json": { "0": { "_schema": ["Body or template is required"], } } }, "status_code": 422, } mocked_schedule_emails_batch = mocker.patch( "core_notifications.services.schedule_emails_batch" ) url = url_for("api_v1.email_send") with app.test_client() as client: resp = client.post( url, data=json.dumps(test_body), content_type="application/json", ) assert resp.json == expected_response assert not mocked_schedule_emails_batch.called def test_failure_validation_no_template_or_subject( self, app, mocker, faker, authorized_app ): test_body = [ {"to": faker.email(), "body": faker.pystr()}, ] expected_response = { "detail": "The request was well-formed but was " "unable to be followed due to semantic errors.", "extra": { "json": { "0": { "_schema": ["Subject or template is required"], } } }, "status_code": 422, } mocked_schedule_emails_batch = mocker.patch( "core_notifications.services.schedule_emails_batch" ) url = url_for("api_v1.email_send") with app.test_client() as client: resp = client.post( url, data=json.dumps(test_body), content_type="application/json", ) assert resp.json == expected_response assert not mocked_schedule_emails_batch.called def test_failure_validation_wrong_template( self, app, mocker, faker, db_session, authorized_app ): test_body = [ { "to": faker.email(), "template": {"id": 0, "context": {}}, }, ] expected_response = { "detail": "The request was well-formed but was " "unable to be followed due to semantic errors.", "extra": { "json": { "0": { "template": {"id": ["The template does not exist"]}, } } }, "status_code": 422, } mocked_schedule_emails_batch = mocker.patch( "core_notifications.services.schedule_emails_batch" ) url = url_for("api_v1.email_send") with app.test_client() as client: resp = client.post( url, data=json.dumps(test_body), content_type="application/json", ) assert resp.json == expected_response assert not mocked_schedule_emails_batch.called def test_failure_validation_inactive_template( self, app, mocker, faker, db_session, authorized_app ): template = TemplateFactory.build() db_session.add(template) db_session.commit() test_body = [ { "to": faker.email(), "template": {"id": template.id, "context": {}}, }, ] expected_response = { "detail": "The request was well-formed but was " "unable to be followed due to semantic errors.", "extra": { "json": { "0": { "template": {"id": ["The template is not active"]}, } } }, "status_code": 422, } mocked_schedule_emails_batch = mocker.patch( "core_notifications.services.schedule_emails_batch" ) url = url_for("api_v1.email_send") assert not template.is_active with app.test_client() as client: resp = client.post( url, data=json.dumps(test_body), content_type="application/json", ) assert resp.json == expected_response assert not mocked_schedule_emails_batch.called class TestStatus: def test_failure_authentication(self, app): url = url_for("api_v1.get_status", task_id=1) with app.test_client() as client: resp = client.get(url) assert resp.status_code == 401 def test_failure_authorization(self, app, authenticated): url = url_for("api_v1.get_status", task_id=1) with app.test_client() as client: resp = client.get(url) assert resp.status_code == 401 def test_success(self, app, mocker, faker, authorized_app): test_id = faker.pystr() mocked_get_sending_status = mocker.patch( "core_notifications.services.get_sending_status" ) mocked_get_sending_status.return_value = SendingTaskStatus.SUCCESS url = url_for("api_v1.get_status", task_id=test_id) with app.test_client() as client: resp = client.get(url) assert mocked_get_sending_status.call_args_list == [ mocker.call(test_id) ] assert resp.json == {"status": SendingTaskStatus.SUCCESS.value} def test_failure_no_task(self, app, mocker, faker, authorized_app): test_id = faker.pystr() mocked_get_sending_status = mocker.patch( "core_notifications.services.get_sending_status" ) mocked_get_sending_status.return_value = None url = url_for("api_v1.get_status", task_id=test_id) with app.test_client() as client: resp = client.get(url) assert mocked_get_sending_status.call_args_list == [ mocker.call(test_id) ] assert resp.json == { "detail": "The task is not found.", "status_code": 404, }