"""
Unit tests for student optouts from course email
"""


import json
from unittest.mock import Mock, patch

from django.core import mail
from django.core.management import call_command
from django.urls import reverse

from common.djangoapps.student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory
from lms.djangoapps.bulk_email.models import BulkEmailFlag, Optout
from lms.djangoapps.bulk_email.signals import force_optout_all
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory


@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))  # lint-amnesty, pylint: disable=line-too-long
class TestOptoutCourseEmailsBySignal(ModuleStoreTestCase):
    """
    Tests that the force_optout_all signal receiver opts the user out of course emails
    """

    def setUp(self):
        super().setUp()
        self.course = CourseFactory.create(run='testcourse1', display_name="Test Course Title")
        self.instructor = AdminFactory.create()
        self.student = UserFactory.create()
        self.enrollment = CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)

        # load initial content (since we don't run migrations as part of tests):
        call_command("loaddata", "course_email_template.json")

        self.client.login(username=self.student.username, password="<PASSWORD>")

        self.send_mail_url = reverse('send_email', kwargs={'course_id': str(self.course.id)})
        self.success_content = {
            'course_id': str(self.course.id),
            'success': True,
        }
        BulkEmailFlag.objects.create(enabled=True, require_course_email_auth=False)

    def test_optout_row_created_on_signal(self):
        """
        Make sure the correct row is created for a user enrolled in a course
        """
        force_optout_all(sender=self.__class__, user=self.student)
        assert Optout.objects.filter(user=self.student, course_id=self.course.id).count() == 1

    def send_test_email(self):
        """
        Navigate to the instructor dash's email view to send bulk email
        """
        # Pull up email view on instructor dashboard
        url = reverse('instructor_dashboard', kwargs={'course_id': str(self.course.id)})
        response = self.client.get(url)
        email_section = '<div class="vert-left send-email" id="section-send-email">'

        # If this fails, it is likely because BulkEmailFlag.is_enabled() is set to False
        self.assertContains(response, email_section)

        test_email = {
            'action': 'Send email',
            'send_to': '["myself", "staff", "learners"]',
            'subject': 'test subject for all',
            'message': 'test message for all'
        }
        response = self.client.post(self.send_mail_url, test_email)
        assert json.loads(response.content.decode('utf-8')) == self.success_content

    def test_optout_course(self):
        """
        Make sure student does not receive course email after being opted out
        """
        # Use the signal receiver to for the opt-out
        force_optout_all(sender=self.__class__, user=self.student)

        # Try to send a bulk course email
        self.client.login(username=self.instructor.username, password="<PASSWORD>")
        self.send_test_email()

        # Assert that self.student.email not in mail.to, outbox should only contain "myself" target
        assert len(mail.outbox) == 1
        assert len(mail.outbox[0].to) == 1
        assert mail.outbox[0].to[0] == self.instructor.email

"""
Unit tests for student optouts from course email
"""


import json
from unittest.mock import Mock, patch

from django.core import mail
from django.core.management import call_command
from django.urls import reverse

from common.djangoapps.student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory
from lms.djangoapps.bulk_email.models import BulkEmailFlag, Optout
from lms.djangoapps.bulk_email.signals import force_optout_all
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory


@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))  # lint-amnesty, pylint: disable=line-too-long
class TestOptoutCourseEmailsBySignal(ModuleStoreTestCase):
    """
    Tests that the force_optout_all signal receiver opts the user out of course emails
    """

    def setUp(self):
        super().setUp()
        self.course = CourseFactory.create(run='testcourse1', display_name="Test Course Title")
        self.instructor = AdminFactory.create()
        self.student = UserFactory.create()
        self.enrollment = CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)

        # load initial content (since we don't run migrations as part of tests):
        call_command("loaddata", "course_email_template.json")

        self.client.login(username=self.student.username, password="<PASSWORD>")

        self.send_mail_url = reverse('send_email', kwargs={'course_id': str(self.course.id)})
        self.success_content = {
            'course_id': str(self.course.id),
            'success': True,
        }
        BulkEmailFlag.objects.create(enabled=True, require_course_email_auth=False)

    def test_optout_row_created_on_signal(self):
        """
        Make sure the correct row is created for a user enrolled in a course
        """
        force_optout_all(sender=self.__class__, user=self.student)
        assert Optout.objects.filter(user=self.student, course_id=self.course.id).count() == 1

    def send_test_email(self):
        """
        Navigate to the instructor dash's email view to send bulk email
        """
        # Pull up email view on instructor dashboard
        url = reverse('instructor_dashboard', kwargs={'course_id': str(self.course.id)})
        response = self.client.get(url)
        email_section = '<div class="vert-left send-email" id="section-send-email">'

        # If this fails, it is likely because BulkEmailFlag.is_enabled() is set to False
        self.assertContains(response, email_section)

        test_email = {
            'action': 'Send email',
            'send_to': '["myself", "staff", "learners"]',
            'subject': 'test subject for all',
            'message': 'test message for all'
        }
        response = self.client.post(self.send_mail_url, test_email)
        assert json.loads(response.content.decode('utf-8')) == self.success_content

    def test_optout_course(self):
        """
        Make sure student does not receive course email after being opted out
        """
        # Use the signal receiver to for the opt-out
        force_optout_all(sender=self.__class__, user=self.student)

        # Try to send a bulk course email
        self.client.login(username=self.instructor.username, password="<PASSWORD>")
        self.send_test_email()

        # Assert that self.student.email not in mail.to, outbox should only contain "myself" target
        assert len(mail.outbox) == 1
        assert len(mail.outbox[0].to) == 1
        assert mail.outbox[0].to[0] == self.instructor.email

Unit tests for student optouts from course email # lint-amnesty, pylint: disable=line-too-long Tests that the force_optout_all signal receiver opts the user out of course emails # load initial content (since we don't run migrations as part of tests): Make sure the correct row is created for a user enrolled in a course Navigate to the instructor dash's email view to send bulk email # Pull up email view on instructor dashboard # If this fails, it is likely because BulkEmailFlag.is_enabled() is set to False Make sure student does not receive course email after being opted out # Use the signal receiver to for the opt-out # Try to send a bulk course email # Assert that self.student.email not in mail.to, outbox should only contain "myself" target