Commit 3278fcf1 by sanfordstudent Committed by GitHub

Merge pull request #15045 from edx/neem/handle_unrescorable

400 for non-rescorable blocks
parents 5314784a 8cfff9a8
......@@ -101,6 +101,11 @@ class InstructorDashboardPage(CoursePage):
ecommerce_section.wait_for_page()
return ecommerce_section
def is_rescore_unsupported_message_visible(self):
return u'This component cannot be rescored.' in unicode(
self.q(css='.request-response-error').html
)
@staticmethod
def get_asset_path(file_name):
"""
......
......@@ -15,14 +15,18 @@ from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.lms.create_mode import ModeCreationPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage, EntranceExamAdmin
from common.test.acceptance.pages.lms.instructor_dashboard import (
InstructorDashboardPage,
EntranceExamAdmin,
StudentSpecificAdmin,
)
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.lms.dashboard import DashboardPage
from common.test.acceptance.pages.lms.problem import ProblemPage
from common.test.acceptance.pages.lms.pay_and_verify import PaymentAndVerificationFlow
from common.test.acceptance.pages.lms.login_and_register import CombinedLoginAndRegisterPage
from common.test.acceptance.pages.common.utils import enroll_user_track
from common.test.acceptance.tests.helpers import disable_animations
from common.test.acceptance.tests.helpers import disable_animations, create_multiple_choice_problem
from common.test.acceptance.fixtures.certificates import CertificateConfigFixture
......@@ -1337,3 +1341,50 @@ class EcommerceTest(BaseInstructorDashboardTest):
# Log in and visit E-commerce section under Instructor dashboard
self.assertNotIn(u'Coupon Code List', self.visit_ecommerce_section().get_sections_header_values())
class StudentAdminTest(BaseInstructorDashboardTest):
SECTION_NAME = 'Test Section 1'
SUBSECTION_NAME = 'Test Subsection 1'
UNIT_NAME = 'Test Unit 1'
PROBLEM_NAME = 'Test Problem 1'
def setUp(self):
super(StudentAdminTest, self).setUp()
self.course_fix = CourseFixture(
self.course_info['org'],
self.course_info['number'],
self.course_info['run'],
self.course_info['display_name']
)
self.problem = create_multiple_choice_problem(self.PROBLEM_NAME)
self.vertical = XBlockFixtureDesc('vertical', "Lab Unit")
self.course_fix.add_children(
XBlockFixtureDesc('chapter', self.SECTION_NAME).add_children(
XBlockFixtureDesc('sequential', self.SUBSECTION_NAME).add_children(
self.vertical.add_children(self.problem)
)
),
).install()
self.username, _ = self.log_in_as_instructor()
self.instructor_dashboard_page = self.visit_instructor_dashboard()
def test_rescore_nonrescorable(self):
student_admin_section = self.instructor_dashboard_page.select_student_admin(StudentSpecificAdmin)
student_admin_section.set_student_email_or_username(self.username)
# not a rescorable block
student_admin_section.set_problem_location(self.vertical.locator)
getattr(student_admin_section, 'rescore_button').click()
self.assertTrue(self.instructor_dashboard_page.is_rescore_unsupported_message_visible())
def test_rescore_rescorable(self):
student_admin_section = self.instructor_dashboard_page.select_student_admin(StudentSpecificAdmin)
student_admin_section.set_student_email_or_username(self.username)
student_admin_section.set_problem_location(self.problem.locator)
getattr(student_admin_section, 'rescore_button').click()
alert = get_modal_alert(student_admin_section.browser)
alert.dismiss()
self.assertFalse(self.instructor_dashboard_page.is_rescore_unsupported_message_visible())
......@@ -2118,18 +2118,24 @@ def rescore_problem(request, course_id):
if student:
response_payload['student'] = student_identifier
lms.djangoapps.instructor_task.api.submit_rescore_problem_for_student(
request,
module_state_key,
student,
only_if_higher,
)
try:
lms.djangoapps.instructor_task.api.submit_rescore_problem_for_student(
request,
module_state_key,
student,
only_if_higher,
)
except NotImplementedError as exc:
return HttpResponseBadRequest(exc.message)
elif all_students:
lms.djangoapps.instructor_task.api.submit_rescore_problem_for_all_students(
request,
module_state_key,
only_if_higher,
)
try:
lms.djangoapps.instructor_task.api.submit_rescore_problem_for_all_students(
request,
module_state_key,
only_if_higher,
)
except NotImplementedError as exc:
return HttpResponseBadRequest(exc.message)
else:
return HttpResponseBadRequest()
......
......@@ -255,10 +255,14 @@ def check_arguments_for_rescoring(usage_key):
in). An ItemNotFoundException is raised if the corresponding module
descriptor doesn't exist. NotImplementedError is raised if the
corresponding module doesn't support rescoring calls.
Note: the string returned here is surfaced as the error
message on the instructor dashboard when a rescore is
submitted for a non-rescorable block.
"""
descriptor = modulestore().get_item(usage_key)
if not _supports_rescore(descriptor):
msg = "Specified module does not support rescoring."
msg = _("This component cannot be rescored.")
raise NotImplementedError(msg)
......
......@@ -436,7 +436,7 @@
}
StudentAdmin.prototype.rescore_problem_single = function(onlyIfHigher) {
var errorMessage, fullErrorMessage, fullSuccessMessage,
var defaultErrorMessage, fullDefaultErrorMessage, fullSuccessMessage,
problemToReset, sendData, successMessage, uniqStudentIdentifier,
that = this;
uniqStudentIdentifier = this.$field_student_select_grade.val();
......@@ -461,8 +461,8 @@
student_id: uniqStudentIdentifier,
problem_id: problemToReset
});
errorMessage = gettext("Error starting a task to rescore problem '<%- problem_id %>' for student '<%- student_id %>'. Make sure that the the problem and student identifiers are complete and correct."); // eslint-disable-line max-len
fullErrorMessage = _.template(errorMessage)({
defaultErrorMessage = gettext("Error starting a task to rescore problem '<%- problem_id %>' for student '<%- student_id %>'. Make sure that the the problem and student identifiers are complete and correct."); // eslint-disable-line max-len
fullDefaultErrorMessage = _.template(defaultErrorMessage)({
student_id: uniqStudentIdentifier,
problem_id: problemToReset
});
......@@ -474,8 +474,11 @@
success: this.clear_errors_then(function() {
return alert(fullSuccessMessage); // eslint-disable-line no-alert
}),
error: statusAjaxError(function() {
return that.$request_err_grade.text(fullErrorMessage);
error: statusAjaxError(function(response) {
if (response.responseText) {
return that.$request_err_grade.text(response.responseText);
}
return that.$request_err_grade.text(fullDefaultErrorMessage);
})
});
};
......@@ -518,8 +521,9 @@
};
StudentAdmin.prototype.rescore_problem_all = function(onlyIfHigher) {
var confirmMessage, errorMessage, fullConfirmMessage,
fullErrorMessage, fullSuccessMessage, problemToReset, sendData, successMessage,
var confirmMessage, defaultErrorMessage, fullConfirmMessage,
fullDefaultErrorMessage, fullSuccessMessage, problemToReset,
sendData, successMessage,
that = this;
problemToReset = this.$field_problem_select_all.val();
if (!problemToReset) {
......@@ -541,8 +545,8 @@
fullSuccessMessage = _.template(successMessage)({
problem_id: problemToReset
});
errorMessage = gettext("Error starting a task to rescore problem '<%- problem_id %>'. Make sure that the problem identifier is complete and correct."); // eslint-disable-line max-len
fullErrorMessage = _.template(errorMessage)({
defaultErrorMessage = gettext("Error starting a task to rescore problem '<%- problem_id %>'. Make sure that the problem identifier is complete and correct."); // eslint-disable-line max-len
fullDefaultErrorMessage = _.template(defaultErrorMessage)({
problem_id: problemToReset
});
return $.ajax({
......@@ -553,8 +557,11 @@
success: this.clear_errors_then(function() {
return alert(fullSuccessMessage); // eslint-disable-line no-alert
}),
error: statusAjaxError(function() {
return that.$request_response_error_all.text(fullErrorMessage);
error: statusAjaxError(function(response) {
if (response.responseText) {
return that.$request_response_error_all.text(response.responseText);
}
return that.$request_response_error_all.text(fullDefaultErrorMessage);
})
});
} else {
......
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