Hide After Due setting for Timed Exams
TNL-4366
Changes in studio to allow the hide_after_due setting to be utilized.
Includes:
-python changes to contentstore, where the data is stored.
-refactoring of timed-examination-preference-editor.underscore, to add this
setting and make the editor more accessible.
-javascript changes to link the new setting to the correct data model.
-sass updates to fix a11y issues on the editor modal.
-addition of post-due visibility information to course outline in studio.
-new tests: python, js, acceptance, and a11y
This commit is contained in:
@@ -83,7 +83,8 @@ def register_special_exams(course_key):
|
||||
due_date=timed_exam.due,
|
||||
is_proctored=timed_exam.is_proctored_exam,
|
||||
is_practice_exam=timed_exam.is_practice_exam,
|
||||
is_active=True
|
||||
is_active=True,
|
||||
hide_after_due=timed_exam.hide_after_due,
|
||||
)
|
||||
msg = 'Updated timed exam {exam_id}'.format(exam_id=exam['id'])
|
||||
log.info(msg)
|
||||
@@ -97,7 +98,8 @@ def register_special_exams(course_key):
|
||||
due_date=timed_exam.due,
|
||||
is_proctored=timed_exam.is_proctored_exam,
|
||||
is_practice_exam=timed_exam.is_practice_exam,
|
||||
is_active=True
|
||||
is_active=True,
|
||||
hide_after_due=timed_exam.hide_after_due,
|
||||
)
|
||||
msg = 'Created new timed exam {exam_id}'.format(exam_id=exam_id)
|
||||
log.info(msg)
|
||||
|
||||
@@ -53,6 +53,10 @@ class TestProctoredExams(ModuleStoreTestCase):
|
||||
exam_review_policy = get_review_policy_by_exam_id(exam['id'])
|
||||
self.assertEqual(exam_review_policy['review_policy'], sequence.exam_review_rules)
|
||||
|
||||
if not exam['is_proctored'] and not exam['is_practice_exam']:
|
||||
# the hide after due value only applies to timed exams
|
||||
self.assertEqual(exam['hide_after_due'], sequence.hide_after_due)
|
||||
|
||||
self.assertEqual(exam['course_id'], unicode(self.course.id))
|
||||
self.assertEqual(exam['content_id'], unicode(sequence.location))
|
||||
self.assertEqual(exam['exam_name'], sequence.display_name)
|
||||
@@ -62,13 +66,14 @@ class TestProctoredExams(ModuleStoreTestCase):
|
||||
self.assertEqual(exam['is_active'], expected_active)
|
||||
|
||||
@ddt.data(
|
||||
(True, 10, True, False, True, False),
|
||||
(True, 10, False, False, True, False),
|
||||
(True, 10, True, True, True, True),
|
||||
(True, 10, True, False, True, False, False),
|
||||
(True, 10, False, False, True, False, False),
|
||||
(True, 10, False, False, True, False, True),
|
||||
(True, 10, True, True, True, True, False),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_publishing_exam(self, is_time_limited, default_time_limit_minutes,
|
||||
is_proctored_exam, is_practice_exam, expected_active, republish):
|
||||
def test_publishing_exam(self, is_time_limited, default_time_limit_minutes, is_proctored_exam,
|
||||
is_practice_exam, expected_active, republish, hide_after_due):
|
||||
"""
|
||||
Happy path testing to see that when a course is published which contains
|
||||
a proctored exam, it will also put an entry into the exam tables
|
||||
@@ -85,7 +90,8 @@ class TestProctoredExams(ModuleStoreTestCase):
|
||||
is_proctored_exam=is_proctored_exam,
|
||||
is_practice_exam=is_practice_exam,
|
||||
due=datetime.now(UTC) + timedelta(minutes=default_time_limit_minutes + 1),
|
||||
exam_review_rules="allow_use_of_paper"
|
||||
exam_review_rules="allow_use_of_paper",
|
||||
hide_after_due=hide_after_due,
|
||||
)
|
||||
|
||||
listen_for_course_publish(self, self.course.id)
|
||||
@@ -117,7 +123,8 @@ class TestProctoredExams(ModuleStoreTestCase):
|
||||
graded=True,
|
||||
is_time_limited=True,
|
||||
default_time_limit_minutes=10,
|
||||
is_proctored_exam=True
|
||||
is_proctored_exam=True,
|
||||
hide_after_due=False,
|
||||
)
|
||||
|
||||
listen_for_course_publish(self, self.course.id)
|
||||
@@ -147,7 +154,8 @@ class TestProctoredExams(ModuleStoreTestCase):
|
||||
graded=True,
|
||||
is_time_limited=True,
|
||||
default_time_limit_minutes=10,
|
||||
is_proctored_exam=True
|
||||
is_proctored_exam=True,
|
||||
hide_after_due=False,
|
||||
)
|
||||
|
||||
listen_for_course_publish(self, self.course.id)
|
||||
@@ -182,7 +190,8 @@ class TestProctoredExams(ModuleStoreTestCase):
|
||||
graded=True,
|
||||
is_time_limited=True,
|
||||
default_time_limit_minutes=10,
|
||||
is_proctored_exam=True
|
||||
is_proctored_exam=True,
|
||||
hide_after_due=False,
|
||||
)
|
||||
|
||||
listen_for_course_publish(self, self.course.id)
|
||||
@@ -218,7 +227,8 @@ class TestProctoredExams(ModuleStoreTestCase):
|
||||
is_time_limited=True,
|
||||
default_time_limit_minutes=10,
|
||||
is_proctored_exam=True,
|
||||
exam_review_rules="allow_use_of_paper"
|
||||
exam_review_rules="allow_use_of_paper",
|
||||
hide_after_due=False,
|
||||
)
|
||||
|
||||
listen_for_course_publish(self, self.course.id)
|
||||
|
||||
@@ -935,7 +935,8 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
|
||||
"is_practice_exam": xblock.is_practice_exam,
|
||||
"is_time_limited": xblock.is_time_limited,
|
||||
"exam_review_rules": xblock.exam_review_rules,
|
||||
"default_time_limit_minutes": xblock.default_time_limit_minutes
|
||||
"default_time_limit_minutes": xblock.default_time_limit_minutes,
|
||||
"hide_after_due": xblock.hide_after_due,
|
||||
})
|
||||
|
||||
# Update with gating info
|
||||
|
||||
Reference in New Issue
Block a user