♻️(backend) refacto email invitation
Remove email invitation from Invitation model to be able to use it in other context. We add it in utils.py instead, and it will be called from the viewset. We add the document_id to link to the document from the mail.
This commit is contained in:
@@ -100,6 +100,8 @@ def test_api_document_invitations__create__privileged_members(
|
||||
"role": invited,
|
||||
}
|
||||
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
response = client.post(
|
||||
@@ -110,6 +112,12 @@ def test_api_document_invitations__create__privileged_members(
|
||||
if is_allowed:
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
assert models.Invitation.objects.count() == 1
|
||||
|
||||
assert len(mail.outbox) == 1
|
||||
email = mail.outbox[0]
|
||||
assert email.to == ["guest@example.com"]
|
||||
email_content = " ".join(email.body.split())
|
||||
assert "Invitation to join Docs!" in email_content
|
||||
else:
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert models.Invitation.objects.exists() is False
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
"""
|
||||
Unit tests for the Invitation model
|
||||
"""
|
||||
|
||||
import smtplib
|
||||
import time
|
||||
from logging import Logger
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.core import exceptions, mail
|
||||
from django.core import exceptions
|
||||
|
||||
import pytest
|
||||
from faker import Faker
|
||||
@@ -168,97 +164,6 @@ def test_models_invitation__new_user__user_creation_constant_num_queries(
|
||||
models.User.objects.create(email=user_email, password="!")
|
||||
|
||||
|
||||
def test_models_document_invitations_email():
|
||||
"""Check email invitation during invitation creation."""
|
||||
member_access = factories.UserDocumentAccessFactory(role="reader")
|
||||
document = member_access.document
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
factories.UserDocumentAccessFactory(document=document)
|
||||
issuer = factories.UserFactory(language="en-us")
|
||||
invitation = factories.InvitationFactory(
|
||||
document=document, email="john@people.com", issuer=issuer
|
||||
)
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 1
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
email = mail.outbox[0]
|
||||
|
||||
assert email.to == [invitation.email]
|
||||
assert email.subject == "Invitation to join Docs!"
|
||||
|
||||
email_content = " ".join(email.body.split())
|
||||
assert "Invitation to join Docs!" in email_content
|
||||
assert "[//example.com]" in email_content
|
||||
|
||||
|
||||
def test_models_document_invitations_email_language_fr():
|
||||
"""Check email invitation during invitation creation."""
|
||||
member_access = factories.UserDocumentAccessFactory(role="reader")
|
||||
document = member_access.document
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
factories.UserDocumentAccessFactory(document=document)
|
||||
issuer = factories.UserFactory(language="fr-fr")
|
||||
invitation = factories.InvitationFactory(
|
||||
document=document, email="john@people.com", issuer=issuer
|
||||
)
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 1
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
email = mail.outbox[0]
|
||||
|
||||
assert email.to == [invitation.email]
|
||||
|
||||
email_content = " ".join(email.body.split())
|
||||
assert "Invitation à rejoindre Docs !" in email_content
|
||||
assert "[//example.com]" in email_content
|
||||
|
||||
|
||||
@mock.patch(
|
||||
"django.core.mail.send_mail",
|
||||
side_effect=smtplib.SMTPException("Error SMTPException"),
|
||||
)
|
||||
@mock.patch.object(Logger, "error")
|
||||
def test_models_document_invitations_email_failed(mock_logger, _mock_send_mail):
|
||||
"""Check invitation behavior when an SMTP error occurs during invitation creation."""
|
||||
|
||||
member_access = factories.UserDocumentAccessFactory(role="reader")
|
||||
document = member_access.document
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
factories.UserDocumentAccessFactory(document=document)
|
||||
|
||||
# No error should be raised
|
||||
invitation = factories.InvitationFactory(document=document, email="john@people.com")
|
||||
|
||||
# No email has been sent
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
# Logger should be called
|
||||
mock_logger.assert_called_once()
|
||||
|
||||
(
|
||||
_,
|
||||
email,
|
||||
exception,
|
||||
) = mock_logger.call_args.args
|
||||
|
||||
assert email == invitation.email
|
||||
assert isinstance(exception, smtplib.SMTPException)
|
||||
|
||||
|
||||
# get_abilities
|
||||
|
||||
|
||||
|
||||
86
src/backend/core/tests/test_utils.py
Normal file
86
src/backend/core/tests/test_utils.py
Normal file
@@ -0,0 +1,86 @@
|
||||
"""
|
||||
Unit tests for the Invitation model
|
||||
"""
|
||||
import smtplib
|
||||
from logging import Logger
|
||||
from unittest import mock
|
||||
|
||||
from django.core import mail
|
||||
|
||||
import pytest
|
||||
|
||||
from core.utils import email_invitation
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_utils__email_invitation_success():
|
||||
"""
|
||||
The email invitation is sent successfully.
|
||||
"""
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
email_invitation("en", "guest@example.com", "123-456-789")
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 1
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
email = mail.outbox[0]
|
||||
|
||||
assert email.to == ["guest@example.com"]
|
||||
email_content = " ".join(email.body.split())
|
||||
assert "Invitation to join Docs!" in email_content
|
||||
assert "docs/123-456-789/" in email_content
|
||||
|
||||
|
||||
def test_utils__email_invitation_success_fr():
|
||||
"""
|
||||
The email invitation is sent successfully in french.
|
||||
"""
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
email_invitation("fr-fr", "guest@example.com", "123-456-789")
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 1
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
email = mail.outbox[0]
|
||||
|
||||
assert email.to == ["guest@example.com"]
|
||||
email_content = " ".join(email.body.split())
|
||||
assert "Invitation à rejoindre Docs !" in email_content
|
||||
assert "docs/123-456-789/" in email_content
|
||||
|
||||
|
||||
@mock.patch(
|
||||
"core.utils.send_mail",
|
||||
side_effect=smtplib.SMTPException("Error SMTPException"),
|
||||
)
|
||||
@mock.patch.object(Logger, "error")
|
||||
def test_utils__email_invitation_failed(mock_logger, _mock_send_mail):
|
||||
"""Check mail behavior when an SMTP error occurs when sent an email invitation."""
|
||||
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
email_invitation("en", "guest@example.com", "123-456-789")
|
||||
|
||||
# No email has been sent
|
||||
# pylint: disable-next=no-member
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
# Logger should be called
|
||||
mock_logger.assert_called_once()
|
||||
|
||||
(
|
||||
_,
|
||||
email,
|
||||
exception,
|
||||
) = mock_logger.call_args.args
|
||||
|
||||
assert email == "guest@example.com"
|
||||
assert isinstance(exception, smtplib.SMTPException)
|
||||
Reference in New Issue
Block a user