bulk_email.py 6.62 KB
Newer Older
1 2 3 4
"""
Define steps for bulk email acceptance test.
"""

5
# pylint: disable=missing-docstring
6
# pylint: disable=redefined-outer-name
7

8 9
from lettuce import world, step
from lettuce.django import mail
10
from nose.tools import assert_in, assert_equal
11
from django.core.management import call_command
12
from django.conf import settings
13

14 15
from courseware.tests.factories import StaffFactory, InstructorFactory

16

17 18 19 20 21
@step(u'Given there is a course with a staff, instructor and student')
def make_populated_course(step):  # pylint: disable=unused-argument
    ## This is different than the function defined in common.py because it enrolls
    ## a staff, instructor, and student member regardless of what `role` is, then
    ## logs `role` in. This is to ensure we have 3 class participants to email.
22 23 24 25

    # Clear existing courses to avoid conflicts
    world.clear_courses()

26 27 28
    # Create a new course
    course = world.CourseFactory.create(
        org='edx',
29 30
        number='888',
        display_name='Bulk Email Test Course'
31
    )
32
    world.bulk_email_course_key = course.id
33

34 35
    try:
        # See if we've defined the instructor & staff user yet
36
        world.bulk_email_instructor
37 38
    except AttributeError:
        # Make & register an instructor for the course
39 40
        world.bulk_email_instructor = InstructorFactory(course_key=world.bulk_email_course_key)
        world.enroll_user(world.bulk_email_instructor, world.bulk_email_course_key)
41

42
        # Make & register a staff member
43 44
        world.bulk_email_staff = StaffFactory(course_key=course.id)
        world.enroll_user(world.bulk_email_staff, world.bulk_email_course_key)
45

46
    # Make & register a student
47 48
    world.register_by_course_key(
        course.id,
49
        username='student',
50
        password='test',
51 52 53
        is_staff=False
    )

54 55
    # Store the expected recipients
    # given each "send to" option
56
    staff_emails = [world.bulk_email_staff.email, world.bulk_email_instructor.email]
57
    world.expected_addresses = {
58 59
        'course staff': staff_emails,
        'students, staff, and instructors': staff_emails + ['student@edx.org']
60 61
    }

62 63 64 65

# Dictionary mapping a description of the email recipient
# to the corresponding <option> value in the UI.
SEND_TO_OPTIONS = {
66 67 68
    'myself': 'myself',
    'course staff': 'staff',
    'students, staff, and instructors': 'all'
69 70 71
}


72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
@step(u'I am logged in to the course as "([^"]*)"')
def log_into_the_course(step, role):  # pylint: disable=unused-argument
    # Store the role
    assert_in(role, ['instructor', 'staff'])

    # Log in as the an instructor or staff for the course
    my_email = world.bulk_email_instructor.email
    if role == 'instructor':
        world.log_in(
            username=world.bulk_email_instructor.username,
            password='test',
            email=my_email,
            name=world.bulk_email_instructor.profile.name
        )
    else:
        my_email = world.bulk_email_staff.email
        world.log_in(
            username=world.bulk_email_staff.username,
            password='test',
            email=my_email,
            name=world.bulk_email_staff.profile.name
        )

    # Store the "myself" send to option
    world.expected_addresses['myself'] = [my_email]


99
@step(u'I send email to "([^"]*)"')
100
def when_i_send_an_email(step, recipient):  # pylint: disable=unused-argument
101 102 103 104 105 106 107

    # Check that the recipient is valid
    assert_in(
        recipient, SEND_TO_OPTIONS,
        msg="Invalid recipient: {}".format(recipient)
    )

108
    # Clear the queue of existing emails
109 110
    while not mail.queue.empty():  # pylint: disable=no-member
        mail.queue.get()  # pylint: disable=no-member
111

112 113 114 115 116 117
    # Because we flush the database before each run,
    # we need to ensure that the email template fixture
    # is re-loaded into the database
    call_command('loaddata', 'course_email_template.json')

    # Go to the email section of the instructor dash
118 119 120
    url = '/courses/{}'.format(world.bulk_email_course_key)
    world.visit(url)
    world.css_click('a[href="{}/instructor"]'.format(url))
121 122 123 124 125 126 127 128 129 130 131 132 133
    world.css_click('a[data-section="send_email"]')

    # Select the recipient
    world.select_option('send_to', SEND_TO_OPTIONS[recipient])

    # Enter subject and message
    world.css_fill('input#id_subject', 'Hello')

    with world.browser.get_iframe('mce_0_ifr') as iframe:
        editor = iframe.find_by_id('tinymce')[0]
        editor.fill('test message')

    # Click send
134
    world.css_click('input[name="send"]', dismiss_alert=True)
135

136 137
    # Expect to see a message that the email was sent
    expected_msg = "Your email was successfully queued for sending."
138 139 140
    world.wait_for_visible('#request-response')
    assert_in(
        expected_msg, world.css_text('#request-response'),
141 142 143 144 145 146
        msg="Could not find email success message."
    )


UNSUBSCRIBE_MSG = 'To stop receiving email like this'

147

148
@step(u'Email is sent to "([^"]*)"')
149
def then_the_email_is_sent(step, recipient):  # pylint: disable=unused-argument
150 151 152 153 154 155 156 157 158
    # Check that the recipient is valid
    assert_in(
        recipient, SEND_TO_OPTIONS,
        msg="Invalid recipient: {}".format(recipient)
    )

    # Retrieve messages.  Because we are using celery in "always eager"
    # mode, we expect all messages to be sent by this point.
    messages = []
159 160
    while not mail.queue.empty():  # pylint: disable=no-member
        messages.append(mail.queue.get())  # pylint: disable=no-member
161 162 163

    # Check that we got the right number of messages
    assert_equal(
164
        len(messages), len(world.expected_addresses[recipient]),
165
        msg="Received {0} instead of {1} messages for {2}".format(
166
            len(messages), len(world.expected_addresses[recipient]), recipient
167 168 169 170 171 172
        )
    )

    # Check that the message properties were correct
    recipients = []
    for msg in messages:
173
        assert_in('Hello', msg.subject)
174
        assert_in(settings.BULK_EMAIL_DEFAULT_FROM_EMAIL, msg.from_email)
175 176 177 178 179 180 181 182

        # Message body should have the message we sent
        # and an unsubscribe message
        assert_in('test message', msg.body)
        assert_in(UNSUBSCRIBE_MSG, msg.body)

        # Should have alternative HTML form
        assert_equal(len(msg.alternatives), 1)
183 184
        content, mime_type = msg.alternatives[0]
        assert_equal(mime_type, 'text/html')
185 186 187 188 189 190 191
        assert_in('test message', content)
        assert_in(UNSUBSCRIBE_MSG, content)

        # Store the recipient address so we can verify later
        recipients.extend(msg.recipients())

    # Check that the messages were sent to the right people
192 193 194 195
    # Because "myself" can vary based on who sent the message,
    # we use the world.expected_addresses dict we configured
    # in an earlier step.
    for addr in world.expected_addresses[recipient]:
196
        assert_in(addr, recipients)