""" Unit tests for bulk-email-related models. """ import datetime import ddt from django.core.management import call_command from django.test import TestCase from mock import Mock, patch from opaque_keys.edx.keys import CourseKey from pytz import UTC from bulk_email.api import is_bulk_email_feature_enabled from bulk_email.models import ( SEND_TO_COHORT, SEND_TO_STAFF, SEND_TO_TRACK, BulkEmailFlag, CourseAuthorization, CourseEmail, CourseEmailTemplate, Optout, ) from course_modes.models import CourseMode from openedx.core.djangoapps.course_groups.models import CourseCohort from student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory @ddt.ddt @patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True)) class CourseEmailTest(ModuleStoreTestCase): """Test the CourseEmail model.""" def test_creation(self): course_id = CourseKey.from_string('abc/123/doremi') sender = UserFactory.create() to_option = SEND_TO_STAFF subject = "dummy subject" html_message = "dummy message" email = CourseEmail.create(course_id, sender, [to_option], subject, html_message) self.assertEqual(email.course_id, course_id) self.assertIn(SEND_TO_STAFF, [target.target_type for target in email.targets.all()]) self.assertEqual(email.subject, subject) self.assertEqual(email.html_message, html_message) self.assertEqual(email.sender, sender) def test_creation_with_optional_attributes(self): course_id = CourseKey.from_string('abc/123/doremi') sender = UserFactory.create() to_option = SEND_TO_STAFF subject = "dummy subject" html_message = "dummy message" template_name = "branded_template" from_addr = "branded@branding.com" email = CourseEmail.create( course_id, sender, [to_option], subject, html_message, template_name=template_name, from_addr=from_addr ) self.assertEqual(email.course_id, course_id) self.assertEqual(email.targets.all()[0].target_type, SEND_TO_STAFF) self.assertEqual(email.subject, subject) self.assertEqual(email.html_message, html_message) self.assertEqual(email.sender, sender) self.assertEqual(email.template_name, template_name) self.assertEqual(email.from_addr, from_addr) def test_bad_to_option(self): course_id = CourseKey.from_string('abc/123/doremi') sender = UserFactory.create() to_option = "fake" subject = "dummy subject" html_message = "dummy message" with self.assertRaises(ValueError): CourseEmail.create(course_id, sender, to_option, subject, html_message) @ddt.data( datetime.datetime(1999, 1, 1, tzinfo=UTC), datetime.datetime(datetime.MAXYEAR, 1, 1, tzinfo=UTC), ) def test_track_target(self, expiration_datetime): """ Tests that emails can be sent to a specific track. Also checks that emails can be sent to an expired track (EDUCATOR-364) """ course = CourseFactory.create() course_id = course.id sender = UserFactory.create() to_option = 'track:test' subject = "dummy subject" html_message = "dummy message" CourseMode.objects.create( mode_slug='test', mode_display_name='Test', course_id=course_id, expiration_datetime=expiration_datetime, ) email = CourseEmail.create(course_id, sender, [to_option], subject, html_message) self.assertEqual(len(email.targets.all()), 1) target = email.targets.all()[0] self.assertEqual(target.target_type, SEND_TO_TRACK) self.assertEqual(target.short_display(), 'track-test') self.assertEqual(target.long_display(), 'Course mode: Test, Currency: usd') @ddt.data( CourseMode.AUDIT, CourseMode.HONOR, ) def test_track_target_with_free_mode(self, free_mode): """ Tests that when emails are sent to a free track the track display should not contain currency. """ course = CourseFactory.create() mode_display_name = free_mode.capitalize course_id = course.id sender = UserFactory.create() to_option = 'track:{}'.format(free_mode) subject = "dummy subject" html_message = "dummy message" CourseMode.objects.create( mode_slug=free_mode, mode_display_name=mode_display_name, course_id=course_id, ) email = CourseEmail.create(course_id, sender, [to_option], subject, html_message) self.assertEqual(len(email.targets.all()), 1) target = email.targets.all()[0] self.assertEqual(target.target_type, SEND_TO_TRACK) self.assertEqual(target.short_display(), 'track-{}'.format(free_mode)) self.assertEqual(target.long_display(), u'Course mode: {}'.format(mode_display_name)) def test_cohort_target(self): course_id = CourseKey.from_string('abc/123/doremi') sender = UserFactory.create() to_option = 'cohort:test cohort' subject = "dummy subject" html_message = "dummy message" CourseCohort.create(cohort_name='test cohort', course_id=course_id) email = CourseEmail.create(course_id, sender, [to_option], subject, html_message) self.assertEqual(len(email.targets.all()), 1) target = email.targets.all()[0] self.assertEqual(target.target_type, SEND_TO_COHORT) self.assertEqual(target.short_display(), 'cohort-test cohort') self.assertEqual(target.long_display(), 'Cohort: test cohort') class OptoutTest(TestCase): def test_is_user_opted_out_for_course(self): user = UserFactory.create() course_id = CourseKey.from_string('abc/123/doremi') self.assertFalse(Optout.is_user_opted_out_for_course(user, course_id)) Optout.objects.create( user=user, course_id=course_id, ) self.assertTrue(Optout.is_user_opted_out_for_course(user, course_id)) class NoCourseEmailTemplateTest(TestCase): """Test the CourseEmailTemplate model without loading the template data.""" def test_get_missing_template(self): with self.assertRaises(CourseEmailTemplate.DoesNotExist): CourseEmailTemplate.get_template() class CourseEmailTemplateTest(TestCase): """Test the CourseEmailTemplate model.""" def setUp(self): super(CourseEmailTemplateTest, self).setUp() # load initial content (since we don't run migrations as part of tests): call_command("loaddata", "course_email_template.json") def _get_sample_plain_context(self): """Provide sample context sufficient for rendering plaintext template""" context = { 'course_title': "Bogus Course Title", 'course_url': "/location/of/course/url", 'email_settings_url': "/location/of/email/settings/url", 'platform_name': 'edX', 'email': 'your-email@test.com', 'unsubscribe_link': '/bulk_email/email/optout/dummy' } return context def _get_sample_html_context(self): """Provide sample context sufficient for rendering HTML template""" context = self._get_sample_plain_context() context['course_image_url'] = "/location/of/course/image/url" return context def _add_xss_fields(self, context): """ Add fields to the context for XSS testing. """ context['course_title'] = "