Commit c7d4270a by Julia Hansbrough Committed by Brian Wilson

API tests, email tests, working notifications

parent b8aff26c
...@@ -704,6 +704,80 @@ class TestInstructorSendEmail(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -704,6 +704,80 @@ class TestInstructorSendEmail(ModuleStoreTestCase, LoginEnrollmentTestCase):
def test_send_email_as_logged_in_instructor(self): def test_send_email_as_logged_in_instructor(self):
url = reverse('send_email', kwargs={'course_id': self.course.id}) url = reverse('send_email', kwargs={'course_id': self.course.id})
response = self.client.post(url,{
'send_to': 'staff',
'subject': 'test subject',
'message': 'test message',
})
self.assertEqual(response.status_code, 200)
def test_send_email_but_not_logged_in(self):
self.client.logout()
url = reverse('send_email', kwargs={'course_id': self.course.id})
response = self.client.post(url, {
'send_to': 'staff',
'subject': 'test subject',
'message': 'test message',
})
self.assertEqual(response.status_code, 403)
def test_send_email_but_not_staff(self):
self.client.logout()
self.student = UserFactory()
self.client.login(username=self.student.username, password='test')
url = reverse('send_email', kwargs={'course_id': self.course.id})
response = self.client.post(url, {
'send_to': 'staff',
'subject': 'test subject',
'message': 'test message',
})
self.assertEqual(response.status_code, 403)
def test_send_email_but_course_not_exist(self):
url = reverse('send_email', kwargs={'course_id': 'GarbageCourse/DNE/NoTerm'})
response = self.client.post(url, {
'send_to': 'staff',
'subject': 'test subject',
'message': 'test message',
})
self.assertNotEqual(response.status_code, 200)
def test_send_email_no_sendto(self):
url = reverse('send_email', kwargs={'course_id': self.course.id})
response = self.client.post(url, {
'subject': 'test subject',
'message': 'test message',
})
self.assertEqual(response.status_code, 400)
def test_send_email_no_subject(self):
url = reverse('send_email', kwargs={'course_id': self.course.id})
response = self.client.post(url, {
'send_to': 'staff',
'message': 'test message',
})
self.assertEqual(response.status_code, 400)
def test_send_email_no_message(self):
url = reverse('send_email', kwargs={'course_id': self.course.id})
response = self.client.post(url, {
'send_to': 'staff',
'subject': 'test subject',
})
self.assertEqual(response.status_code, 400)
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
class TestInstructorSendEmail(ModuleStoreTestCase, LoginEnrollmentTestCase):
"""
fill this out
"""
def setUp(self):
self.instructor = AdminFactory.create()
self.course = CourseFactory.create()
self.client.login(username=self.instructor.username, password='test')
def test_send_email_as_logged_in_instructor(self):
url = reverse('send_email', kwargs={'course_id': self.course.id})
response = self.client.get(url,{ response = self.client.get(url,{
'send_to': 'staff', 'send_to': 'staff',
'subject': 'test subject', 'subject': 'test subject',
......
...@@ -41,9 +41,9 @@ class TestInstructorDashboardEmailView(ModuleStoreTestCase): ...@@ -41,9 +41,9 @@ class TestInstructorDashboardEmailView(ModuleStoreTestCase):
self.client.login(username=instructor.username, password="test") self.client.login(username=instructor.username, password="test")
# URL for instructor dash # URL for instructor dash
self.url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id}) self.url = reverse('instructor_dashboard_2', kwargs={'course_id': self.course.id})
# URL for email view # URL for email view
self.email_link = '<a href="#" onclick="goto(\'Email\')" class="None">Email</a>' self.email_link = '<a href="" data-section="send_email">Email</a>'
def tearDown(self): def tearDown(self):
""" """
...@@ -51,30 +51,34 @@ class TestInstructorDashboardEmailView(ModuleStoreTestCase): ...@@ -51,30 +51,34 @@ class TestInstructorDashboardEmailView(ModuleStoreTestCase):
""" """
patch.stopall() patch.stopall()
# Enabled and IS mongo
@patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True}) @patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True})
def test_email_flag_true(self): def test_email_flag_true(self):
from nose.tools import set_trace; set_trace()
# Assert that the URL for the email view is in the response # Assert that the URL for the email view is in the response
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertTrue(self.email_link in response.content) self.assertTrue(self.email_link in response.content)
# Select the Email view of the instructor dash
session = self.client.session
session['idash_mode'] = 'Email'
session.save()
response = self.client.get(self.url)
# Ensure we've selected the view properly and that the send_to field is present.
selected_email_link = '<a href="#" onclick="goto(\'Email\')" class="selectedmode">Email</a>'
self.assertTrue(selected_email_link in response.content)
send_to_label = '<label for="id_to">Send to:</label>' send_to_label = '<label for="id_to">Send to:</label>'
self.assertTrue(send_to_label in response.content) self.assertTrue(send_to_label in response.content)
self.assertEqual(response.status_code,200)
# Disabled but IS mongo
@patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': False}) @patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': False})
def test_email_flag_false(self): def test_email_flag_false(self):
# Assert that the URL for the email view is not in the response # Assert that the URL for the email view is not in the response
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertFalse(self.email_link in response.content) self.assertFalse(self.email_link in response.content)
# Enabled but NOT mongo
@patch.dict(settings.MITX_FEATURES,{'ENABLE_INSTRUCTOR_EMAIL': True})
def test_email_flag_false(self):
with patch('xmodule.modulestore.mongo.base.MongoModuleStore.get_modulestore_type') as mock_modulestore:
mock_modulestore.return_value = XML_MODULESTORE_TYPE
response = self.client.get(self.url)
self.assertFalse(self.email_link in response.content)
@patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True}) @patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True})
def test_email_flag_true_xml_store(self): def test_email_flag_true_xml_store(self):
# If the enable email setting is enabled, but this is an XML backed course, # If the enable email setting is enabled, but this is an XML backed course,
...@@ -92,49 +96,8 @@ class TestInstructorDashboardEmailView(ModuleStoreTestCase): ...@@ -92,49 +96,8 @@ class TestInstructorDashboardEmailView(ModuleStoreTestCase):
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertFalse(self.email_link in response.content) self.assertFalse(self.email_link in response.content)
# Disabled and IS Mongo
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
class TestStudentDashboardEmailView(ModuleStoreTestCase):
"""
Check for email view displayed with flag
"""
def setUp(self):
self.course = CourseFactory.create()
# Create student account
student = UserFactory.create()
CourseEnrollmentFactory.create(user=student, course_id=self.course.id)
self.client.login(username=student.username, password="test")
# URL for dashboard
self.url = reverse('dashboard')
# URL for email settings modal
self.email_modal_link = (('<a href="#email-settings-modal" class="email-settings" rel="leanModal" '
'data-course-id="{0}/{1}/{2}" data-course-number="{1}" '
'data-optout="False">Email Settings</a>')
.format(self.course.org,
self.course.number,
self.course.display_name.replace(' ', '_')))
def tearDown(self):
"""
Undo all patches.
"""
patch.stopall()
@patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True})
def test_email_flag_true(self):
# Assert that the URL for the email view is in the response
response = self.client.get(self.url)
self.assertTrue(self.email_modal_link in response.content)
@patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': False}) @patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': False})
def test_email_flag_false(self):
# Assert that the URL for the email view is not in the response
response = self.client.get(self.url)
self.assertFalse(self.email_modal_link in response.content)
@patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True})
def test_email_flag_true_xml_store(self): def test_email_flag_true_xml_store(self):
# If the enable email setting is enabled, but this is an XML backed course, # If the enable email setting is enabled, but this is an XML backed course,
# the email view shouldn't be available on the instructor dashboard. # the email view shouldn't be available on the instructor dashboard.
...@@ -149,4 +112,4 @@ class TestStudentDashboardEmailView(ModuleStoreTestCase): ...@@ -149,4 +112,4 @@ class TestStudentDashboardEmailView(ModuleStoreTestCase):
# Assert that the URL for the email view is not in the response # Assert that the URL for the email view is not in the response
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertFalse(self.email_modal_link in response.content) self.assertFalse(self.email_link in response.content)
...@@ -43,6 +43,8 @@ from bulk_email.models import CourseEmail ...@@ -43,6 +43,8 @@ from bulk_email.models import CourseEmail
from html_to_text import html_to_text from html_to_text import html_to_text
from bulk_email import tasks from bulk_email import tasks
log = logging.getLogger(__name__)
def common_exceptions_400(func): def common_exceptions_400(func):
""" """
...@@ -743,9 +745,9 @@ def list_forum_members(request, course_id): ...@@ -743,9 +745,9 @@ def list_forum_members(request, course_id):
} }
return JsonResponse(response_payload) return JsonResponse(response_payload)
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True) @cache_control(no_cache=True, no_store=True, must_revalidate=True)
# todo check if staff is the desired access level
# todo do html and plaintext messages
@require_level('staff') @require_level('staff')
@require_query_params(send_to="sending to whom", subject="subject line", message="message text") @require_query_params(send_to="sending to whom", subject="subject line", message="message text")
def send_email(request, course_id): def send_email(request, course_id):
...@@ -756,17 +758,13 @@ def send_email(request, course_id): ...@@ -756,17 +758,13 @@ def send_email(request, course_id):
- 'subject' specifies email's subject - 'subject' specifies email's subject
- 'message' specifies email's content - 'message' specifies email's content
""" """
set_trace()
course = get_course_by_id(course_id) course = get_course_by_id(course_id)
has_instructor_access = has_access(request.user, course, 'instructor')
send_to = request.GET.get("send_to") send_to = request.GET.get("send_to")
subject = request.GET.get("subject") subject = request.GET.get("subject")
message = request.GET.get("message") message = request.GET.get("message")
text_message = html_to_text(message) text_message = html_to_text(message)
if subject == "":
return HttpResponseBadRequest("Operation requires instructor access.")
email = CourseEmail( email = CourseEmail(
course_id = course_id, course_id=course_id,
sender=request.user, sender=request.user,
to_option=send_to, to_option=send_to,
subject=subject, subject=subject,
...@@ -783,6 +781,7 @@ def send_email(request, course_id): ...@@ -783,6 +781,7 @@ def send_email(request, course_id):
} }
return JsonResponse(response_payload) return JsonResponse(response_payload)
@ensure_csrf_cookie @ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True) @cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff') @require_level('staff')
......
...@@ -22,7 +22,6 @@ class SendEmail ...@@ -22,7 +22,6 @@ class SendEmail
# attach click handlers # attach click handlers
@$btn_send.click => @$btn_send.click =>
if @$subject.val() == "" if @$subject.val() == ""
alert gettext("Your message must have a subject.") alert gettext("Your message must have a subject.")
else if @$emailEditor.save()['data'] == "" else if @$emailEditor.save()['data'] == ""
...@@ -46,8 +45,11 @@ class SendEmail ...@@ -46,8 +45,11 @@ class SendEmail
dataType: 'json' dataType: 'json'
url: @$btn_send.data 'endpoint' url: @$btn_send.data 'endpoint'
data: send_data data: send_data
success: (data) => @display_response gettext('Your email was successfully queued for sending.') success: (data) =>
@display_response gettext('Your email was successfully queued for sending.')
$(".msg-confirm").css({"display":"block"})
error: std_ajax_err => @fail_with_error gettext('Error sending email.') error: std_ajax_err => @fail_with_error gettext('Error sending email.')
$(".msg-confirm").css({"display":"none"})
fail_with_error: (msg) -> fail_with_error: (msg) ->
console.warn msg console.warn msg
......
...@@ -260,19 +260,17 @@ section.instructor-dashboard-content-2 { ...@@ -260,19 +260,17 @@ section.instructor-dashboard-content-2 {
// system feedback - messages // system feedback - messages
.msg { .msg {
border-radius: 1px;
padding: 10px 15px;
.copy { margin-bottom: 20px;
font-weight: 600; font-weight: 600;
} color: green;
} }
.msg-confirm { .msg-confirm {
border-top: 2px solid green;
background: tint(green,90%); background: tint(green,90%);
display: none;
.copy {
color: green;
}
} }
.list-advice { .list-advice {
...@@ -289,7 +287,7 @@ section.instructor-dashboard-content-2 { ...@@ -289,7 +287,7 @@ section.instructor-dashboard-content-2 {
} }
} }
} }
.msg .copy { .copy {
font-weight: 600; } font-weight: 600; }
.msg-confirm { .msg-confirm {
background: #e5f2e5; } background: #e5f2e5; }
......
<%! from django.utils.translation import ugettext as _ %>
<%page args="section_data"/>
<h2>Email</h2>
<form>
<ul class="list-fields">
<li class="field">
<label for="id_to">${_("Send to:")}</label>
<select id="id_to" name="to_option">
<option value="myself">${_("Myself")}</option>
%if to_option == "staff":
<option value="staff" selected="selected">${_("Staff and instructors")}</option>
%else:
<option value="staff">${_("Staff and instructors")}</option>
%endif
%if to_option == "all":
<option value="all" selected="selected">${_("All (students, staff and instructors)")}</option>
%else:
<option value="all">${_("All (students, staff and instructors)")}</option>
%endif
</select>
</li>
<li class="field">
<label for="id_subject">${_("Subject: ")}</label>
%if subject:
<input type="text" id="id_subject" name="subject" maxlength="100" size="75" value="${subject}">
%else:
<input type="text" id="id_subject" name="subject" maxlength="100" size="75">
%endif
</li>
<li class="field">
<label>Message:</label>
<div class="email-editor">
<section class="xmodule_edit xmodule_HtmlDescriptor" data-type="HTMLEditingDescriptor">
<section class="html-editor editor">
<div class="row">
<textarea class="tiny-mce">&lt;p&gt;hihihi&lt;/p&gt;</textarea>
</div>
</section>
</section>
</div>
<input type="hidden" name="message" value="">
</li>
</ul>
<div class="submit-email-action">
${_("Please try not to email students more than once a day. Important things to consider before sending:")}
<ul class="list-advice">
<li class="item">${_("Have you read over the email to make sure it says everything you want to say?")}</li>
<li class="item">${_("Have you sent the email to yourself first to make sure you're happy with how it's displayed?")}</li>
</ul>
<input type="submit" name="send-email" value="Send email" data-endpoint="${ section_data[get_send_email_url']}">
</div>
</form>
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<script type="text/javascript" src="jsi18n/"></script> <script type="text/javascript" src="jsi18n/"></script>
<div class="vert-left send-email"> <div class="vert-left send-email">
<h2> ${_("Send Email")} </h2> <h2> ${_("Send Email")} </h2>
<div class="request-response msg msg-confirm" id="request-response"></div> <div class="request-response msg msg-confirm copy" id="request-response"></div>
<ul class="list-fields"> <ul class="list-fields">
<li class="field"> <li class="field">
<label for="id_to">${_("Send to:")}</label><br/> <label for="id_to">${_("Send to:")}</label><br/>
...@@ -45,5 +45,6 @@ ...@@ -45,5 +45,6 @@
</ul> </ul>
</div> </div>
<input type="button" name="send" value="${_("Send Email")}" data-endpoint="${ section_data['send_email'] }" > <input type="button" name="send" value="${_("Send Email")}" data-endpoint="${ section_data['send_email'] }" >
<input type="button" name="send" value="${_("Send")}" data-endpoint="${ section_data['send_email'] }" >
<div class="request-response-error"></div> <div class="request-response-error"></div>
</div> </div>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment