"""Test logic related to emails.""" from unittest.mock import Mock from unittest.mock import MagicMock from _pytest.monkeypatch import monkeypatch as MonkeyPatch import boto from boto import exception from faker import Faker from flask import g import pytest from auth.logic import email_service from auth.logic.email_service import deliver_email from auth.logic.email_service import forgot_password_notification from tests.fixtures import flask_global monkeypatch = MonkeyPatch() def setup_function(function): """Invoke for every test function. Args: function (callable): the function that will run the test. """ flask_global.mock(monkeypatch) def teardown_function(function): """Invoke everytime a test function has completed. Args: function (callable): the function that has run. """ monkeypatch.undo() @pytest.fixture def user_email_param(clean=True): """Return mock user with random email.""" fake = Faker() user = Mock() user.email = fake.email() return user @pytest.fixture def token_email_param(): """Return random sha1 token for testing.""" fake = Faker() token = fake.sha1() return token def test_delivers_ses_email(monkeypatch, user_email_param, token_email_param): """Test successful delivery of SES email with forgot password data.""" ses = Mock() monkeypatch.setattr(boto, 'connect_ses', MagicMock(return_value=ses)) email = forgot_password_notification(user_email_param, token_email_param) result = deliver_email(email) assert boto.connect_ses.called assert ses.send_email.called call_args = ses.send_email.call_args assert call_args[0][0] == 'donotreply@theorchard.com' assert call_args[0][1] == email_service.EMAIL_TITLE_FORGOTTEN_PASSWORD assert call_args[0][2] == user_email_param.email assert result def test_logs_no_auth_handler_found( user_email_param, token_email_param, monkeypatch): """Test error logging if NoAuthHandlerFound exception is raised by boto.""" ses = Mock() monkeypatch.setattr(boto, 'connect_ses', MagicMock(return_value=ses)) monkeypatch.setattr(ses, 'send_email', MagicMock( side_effect=exception.NoAuthHandlerFound)) email = forgot_password_notification(user_email_param, token_email_param) result = deliver_email(email) assert g.log.critical.called assert not result assert result.status == 500 assert ( result.errors.get('message') == email_service.MESSAGE_SES_AUTH_FAILED) def test_logs_boto_server_error( user_email_param, token_email_param, monkeypatch): """Test error logging if BotoServerError exception is raised by boto.""" ses = Mock() monkeypatch.setattr(boto, 'connect_ses', MagicMock(return_value=ses)) failure = exception.BotoServerError( 'InvalidInstance', 'Invalid instance', body='InvalidInstance') monkeypatch.setattr(ses, 'send_email', MagicMock(side_effect=failure)) email = forgot_password_notification(user_email_param, token_email_param) result = deliver_email(email) assert g.log.error.called assert result.status == 500 def test_logs_general_exceptions( user_email_param, token_email_param, monkeypatch): """Test error logging if general exception is raised.""" ses = Mock() monkeypatch.setattr(boto, 'connect_ses', MagicMock(return_value=ses)) monkeypatch.setattr(ses, 'send_email', MagicMock(side_effect=Exception)) email = forgot_password_notification(user_email_param, token_email_param) result = deliver_email(email) assert g.log.error.called assert result.status == 500 def test_generates_forgot_password_message( user_email_param, token_email_param): """Test that forgot password notification. Test that forgot password notification generates an Email object with the correct subject, sender and body information. """ email = forgot_password_notification(user_email_param, token_email_param) assert user_email_param.email == email.to assert 'donotreply@theorchard.com' == email.sender assert email_service.EMAIL_TITLE_FORGOTTEN_PASSWORD == email.subject assert token_email_param in email.text_body assert token_email_param in email.html_body