def setUp(self): """ Test case scaffolding """ self.course = CourseFactory.create() self.instructor_tab = ItemFactory.create( category="instructor", parent_location=self.course.location, data="Instructor Tab", display_name="Instructor") self.extra_tab_2 = ItemFactory.create( category="static_tab", parent_location=self.course.location, data="Extra Tab", display_name="Extra Tab 2") self.extra_tab_3 = ItemFactory.create( category="static_tab", parent_location=self.course.location, data="Extra Tab", display_name="Extra Tab 3") self.setup_user() self.enroll(self.course) self.user.is_staff = True self.relationship_types = milestones_api.get_milestone_relationship_types( ) MilestoneRelationshipType.objects.create(name='requires') MilestoneRelationshipType.objects.create(name='fulfills')
def get_milestone_relationship_types(): """ Client API operation adapter/wrapper """ if not settings.FEATURES.get('MILESTONES_APP'): return {} return milestones_api.get_milestone_relationship_types()
def _fulfill_content_milestones(user, course_key, content_key): """ Internal helper to handle milestone fulfillments for the specified content module """ # Fulfillment Use Case: Entrance Exam # If this module is part of an entrance exam, we'll need to see if the student # has reached the point at which they can collect the associated milestone if settings.FEATURES.get('ENTRANCE_EXAMS', False): course = modulestore().get_course(course_key) content = modulestore().get_item(content_key) entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', False) in_entrance_exam = getattr(content, 'in_entrance_exam', False) if entrance_exam_enabled and in_entrance_exam: exam_pct = _calculate_entrance_exam_score(user, course) if exam_pct >= course.entrance_exam_minimum_score_pct: exam_key = UsageKey.from_string(course.entrance_exam_id) relationship_types = milestones_api.get_milestone_relationship_types( ) content_milestones = milestones_api.get_course_content_milestones( course_key, exam_key, relationship=relationship_types['FULFILLS']) # Add each milestone to the user's set... user = {'id': user.id} for milestone in content_milestones: milestones_api.add_user_milestone(user, milestone)
def _fulfill_content_milestones(user, course_key, content_key): """ Internal helper to handle milestone fulfillments for the specified content module """ # Fulfillment Use Case: Entrance Exam # If this module is part of an entrance exam, we'll need to see if the student # has reached the point at which they can collect the associated milestone if settings.FEATURES.get('ENTRANCE_EXAMS', False): course = modulestore().get_course(course_key) content = modulestore().get_item(content_key) entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', False) in_entrance_exam = getattr(content, 'in_entrance_exam', False) if entrance_exam_enabled and in_entrance_exam: exam_pct = _calculate_entrance_exam_score(user, course) if exam_pct >= course.entrance_exam_minimum_score_pct: exam_key = UsageKey.from_string(course.entrance_exam_id) relationship_types = milestones_api.get_milestone_relationship_types() content_milestones = milestones_api.get_course_content_milestones( course_key, exam_key, relationship=relationship_types['FULFILLS'] ) # Add each milestone to the user's set... user = {'id': user.id} for milestone in content_milestones: milestones_api.add_user_milestone(user, milestone)
def setUp(self): """ Test case scaffolding """ super(EntranceExamsTabsTestCase, self).setUp() self.course = CourseFactory.create() self.instructor_tab = ItemFactory.create( category="instructor", parent_location=self.course.location, data="Instructor Tab", display_name="Instructor" ) self.extra_tab_2 = ItemFactory.create( category="static_tab", parent_location=self.course.location, data="Extra Tab", display_name="Extra Tab 2" ) self.extra_tab_3 = ItemFactory.create( category="static_tab", parent_location=self.course.location, data="Extra Tab", display_name="Extra Tab 3" ) self.setup_user() self.enroll(self.course) self.user.is_staff = True self.relationship_types = milestones_api.get_milestone_relationship_types() MilestoneRelationshipType.objects.create(name='requires') MilestoneRelationshipType.objects.create(name='fulfills')
def get_milestone_relationship_types(): """ Client API operation adapter/wrapper """ if not ENABLE_MILESTONES_APP.is_enabled(): return {} return milestones_api.get_milestone_relationship_types()
def setUp(self): """ Shared scaffolding for individual test runs """ super(EntranceExamHandlerTests, self).setUp() self.course_key = self.course.id self.usage_key = self.course.location self.course_url = '/course/{}'.format(unicode(self.course.id)) self.exam_url = '/course/{}/entrance_exam/'.format(unicode(self.course.id)) MilestoneRelationshipType.objects.create(name='requires', active=True) MilestoneRelationshipType.objects.create(name='fulfills', active=True) self.milestone_relationship_types = milestones_api.get_milestone_relationship_types()
def _create_entrance_exam(request, course_key, entrance_exam_minimum_score_pct=None): """ Internal workflow operation to create an entrance exam """ # Provide a default value for the minimum score percent if nothing specified if entrance_exam_minimum_score_pct is None: entrance_exam_minimum_score_pct = float(settings.ENTRANCE_EXAM_MIN_SCORE_PCT) # Confirm the course exists course = modulestore().get_course(course_key) if course is None: return HttpResponse(status=400) # Create the entrance exam item (currently it's just a chapter) payload = { "category": "chapter", "display_name": "Entrance Exam", "parent_locator": unicode(course.location), "is_entrance_exam": True, "in_entrance_exam": True, } factory = RequestFactory() internal_request = factory.post("/", json.dumps(payload), content_type="application/json") internal_request.user = request.user created_item = json.loads(create_item(internal_request).content) # Set the entrance exam metadata flags for this course # Reload the course so we don't overwrite the new child reference course = modulestore().get_course(course_key) metadata = { "entrance_exam_enabled": True, "entrance_exam_minimum_score_pct": entrance_exam_minimum_score_pct / 100, "entrance_exam_id": created_item["locator"], } CourseMetadata.update_from_dict(metadata, course, request.user) # Add an entrance exam milestone if one does not already exist milestone_namespace = generate_milestone_namespace(NAMESPACE_CHOICES["ENTRANCE_EXAM"], course_key) milestones = milestones_api.get_milestones(milestone_namespace) if len(milestones): milestone = milestones[0] else: description = "Autogenerated during {} entrance exam creation.".format(unicode(course.id)) milestone = milestones_api.add_milestone( {"name": "Completed Course Entrance Exam", "namespace": milestone_namespace, "description": description} ) relationship_types = milestones_api.get_milestone_relationship_types() milestones_api.add_course_milestone(unicode(course.id), relationship_types["REQUIRES"], milestone) milestones_api.add_course_content_milestone( unicode(course.id), created_item["locator"], relationship_types["FULFILLS"], milestone ) return HttpResponse(status=201)
def setUp(self): """ Milestones API Test Case scaffolding """ super(MilestonesApiTestCase, self).setUp() self.test_milestone = api.add_milestone({ 'name': 'test_milestone', 'display_name': 'Test Milestone', 'namespace': six.text_type(self.test_course_key), 'description': 'Test Milestone Description', }) self.relationship_types = api.get_milestone_relationship_types()
def setUp(self): """ Milestones API Test Case scaffolding """ super(MilestonesApiTestCase, self).setUp() self.test_milestone = api.add_milestone({ 'name': 'test_milestone', 'display_name': 'Test Milestone', 'namespace': unicode(self.test_course_key), 'description': 'Test Milestone Description', }) self.relationship_types = api.get_milestone_relationship_types()
def setUp(self): """ Shared scaffolding for individual test runs """ super(EntranceExamHandlerTests, self).setUp() self.course_key = self.course.id self.usage_key = self.course.location self.course_url = '/course/{}'.format(unicode(self.course.id)) self.exam_url = '/course/{}/entrance_exam/'.format( unicode(self.course.id)) MilestoneRelationshipType.objects.create(name='requires', active=True) MilestoneRelationshipType.objects.create(name='fulfills', active=True) self.milestone_relationship_types = milestones_api.get_milestone_relationship_types( )
def _fulfill_content_milestones(course_key, content_key, user_id): # pylint: disable=unused-argument """ Internal helper to handle milestone fulfillments for the specified content module """ # Fulfillment Use Case: Entrance Exam # If this module is part of an entrance exam, we'll need to see if the student # has reached the point at which they can collect the associated milestone if settings.FEATURES.get('ENTRANCE_EXAMS', False): course = modulestore().get_course(course_key) content = modulestore().get_item(content_key) entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', False) in_entrance_exam = getattr(content, 'in_entrance_exam', False) if entrance_exam_enabled and in_entrance_exam: exam_key = UsageKey.from_string(course.entrance_exam_id) exam_descriptor = modulestore().get_item(exam_key) exam_modules = yield_dynamic_descriptor_descendents( exam_descriptor, inner_get_module) ignore_categories = [ 'course', 'chapter', 'sequential', 'vertical' ] module_pcts = [] exam_pct = 0 for module in exam_modules: if module.graded and module.category not in ignore_categories: module_pct = 0 try: student_module = StudentModule.objects.get( module_state_key=module.scope_ids.usage_id, student_id=user_id) if student_module.max_grade: module_pct = student_module.grade / student_module.max_grade except StudentModule.DoesNotExist: pass module_pcts.append(module_pct) exam_pct = sum(module_pcts) / float(len(module_pcts)) if exam_pct >= course.entrance_exam_minimum_score_pct: relationship_types = milestones_api.get_milestone_relationship_types( ) content_milestones = milestones_api.get_course_content_milestones( course_key, exam_key, relationship=relationship_types['FULFILLS']) # Add each milestone to the user's set... user = {'id': user_id} for milestone in content_milestones: milestones_api.add_user_milestone(user, milestone)
def _fulfill_content_milestones(course_key, content_key, user_id): # pylint: disable=unused-argument """ Internal helper to handle milestone fulfillments for the specified content module """ # Fulfillment Use Case: Entrance Exam # If this module is part of an entrance exam, we'll need to see if the student # has reached the point at which they can collect the associated milestone if settings.FEATURES.get('ENTRANCE_EXAMS', False): course = modulestore().get_course(course_key) content = modulestore().get_item(content_key) entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', False) in_entrance_exam = getattr(content, 'in_entrance_exam', False) if entrance_exam_enabled and in_entrance_exam: exam_key = UsageKey.from_string(course.entrance_exam_id) exam_descriptor = modulestore().get_item(exam_key) exam_modules = yield_dynamic_descriptor_descendents( exam_descriptor, inner_get_module ) ignore_categories = ['course', 'chapter', 'sequential', 'vertical'] module_pcts = [] exam_pct = 0 for module in exam_modules: if module.graded and module.category not in ignore_categories: module_pct = 0 try: student_module = StudentModule.objects.get( module_state_key=module.scope_ids.usage_id, student_id=user_id ) if student_module.max_grade: module_pct = student_module.grade / student_module.max_grade except StudentModule.DoesNotExist: pass module_pcts.append(module_pct) exam_pct = sum(module_pcts) / float(len(module_pcts)) if exam_pct >= course.entrance_exam_minimum_score_pct: relationship_types = milestones_api.get_milestone_relationship_types() content_milestones = milestones_api.get_course_content_milestones( course_key, exam_key, relationship=relationship_types['FULFILLS'] ) # Add each milestone to the user's set... user = {'id': user_id} for milestone in content_milestones: milestones_api.add_user_milestone(user, milestone)
def setUp(self): """ Milestones Data Test Case scaffolding """ super(MilestonesDataTestCase, self).setUp() self.relationship_types = api.get_milestone_relationship_types()
def setUp(self): """ Test case scaffolding """ super(EntranceExamTestCases, self).setUp() self.course = CourseFactory.create(metadata={ 'entrance_exam_enabled': True, }) chapter = ItemFactory.create(parent=self.course, display_name='Overview') ItemFactory.create(parent=chapter, display_name='Welcome') ItemFactory.create(parent=self.course, category='chapter', display_name="Week 1") ItemFactory.create(parent=chapter, category='sequential', display_name="Lesson 1") ItemFactory.create(category="instructor", parent=self.course, data="Instructor Tab", display_name="Instructor") self.entrance_exam = ItemFactory.create( parent=self.course, category="chapter", display_name="Entrance Exam Section - Chapter 1") self.exam_1 = ItemFactory.create( parent=self.entrance_exam, category='sequential', display_name="Exam Sequential - Subsection 1", graded=True, metadata={'in_entrance_exam': True}) subsection = ItemFactory.create(parent=self.exam_1, category='vertical', display_name='Exam Vertical - Unit 1') self.problem_1 = ItemFactory.create( parent=subsection, category="problem", display_name="Exam Problem - Problem 1") self.problem_2 = ItemFactory.create( parent=subsection, category="problem", display_name="Exam Problem - Problem 2") self.problem_3 = ItemFactory.create( parent=subsection, category="problem", display_name="Exam Problem - Problem 3") milestone_namespace = generate_milestone_namespace( NAMESPACE_CHOICES['ENTRANCE_EXAM'], self.course.id) self.milestone = { 'name': 'Test Milestone', 'namespace': milestone_namespace, 'description': 'Testing Courseware Entrance Exam Chapter', } MilestoneRelationshipType.objects.create(name='requires', active=True) MilestoneRelationshipType.objects.create(name='fulfills', active=True) self.milestone_relationship_types = milestones_api.get_milestone_relationship_types( ) self.milestone = milestones_api.add_milestone(self.milestone) milestones_api.add_course_milestone( unicode(self.course.id), self.milestone_relationship_types['REQUIRES'], self.milestone) milestones_api.add_course_content_milestone( unicode(self.course.id), unicode(self.entrance_exam.location), self.milestone_relationship_types['FULFILLS'], self.milestone) user = UserFactory() self.request = RequestFactory() self.request.user = user self.request.COOKIES = {} self.request.META = {} self.request.is_secure = lambda: True self.request.get_host = lambda: "edx.org" self.request.method = 'GET' self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents( self.course.id, user, self.entrance_exam) self.entrance_exam.is_entrance_exam = True self.entrance_exam.in_entrance_exam = True self.course.entrance_exam_enabled = True self.course.entrance_exam_minimum_score_pct = 0.50 self.course.entrance_exam_id = unicode( self.entrance_exam.scope_ids.usage_id) modulestore().update_item(self.course, user.id) # pylint: disable=no-member
def _create_entrance_exam(request, course_key, entrance_exam_minimum_score_pct=None): """ Internal workflow operation to create an entrance exam """ # Provide a default value for the minimum score percent if nothing specified if entrance_exam_minimum_score_pct is None: entrance_exam_minimum_score_pct = float( settings.ENTRANCE_EXAM_MIN_SCORE_PCT) # Confirm the course exists course = modulestore().get_course(course_key) if course is None: return HttpResponse(status=400) # Create the entrance exam item (currently it's just a chapter) payload = { 'category': "chapter", 'display_name': "Entrance Exam", 'parent_locator': unicode(course.location), 'is_entrance_exam': True, 'in_entrance_exam': True, } factory = RequestFactory() internal_request = factory.post('/', json.dumps(payload), content_type="application/json") internal_request.user = request.user created_item = json.loads(create_item(internal_request).content) # Set the entrance exam metadata flags for this course # Reload the course so we don't overwrite the new child reference course = modulestore().get_course(course_key) metadata = { 'entrance_exam_enabled': True, 'entrance_exam_minimum_score_pct': entrance_exam_minimum_score_pct / 100, 'entrance_exam_id': created_item['locator'], } CourseMetadata.update_from_dict(metadata, course, request.user) # Add an entrance exam milestone if one does not already exist milestone_namespace = generate_milestone_namespace( NAMESPACE_CHOICES['ENTRANCE_EXAM'], course_key) milestones = milestones_api.get_milestones(milestone_namespace) if len(milestones): milestone = milestones[0] else: description = 'Autogenerated during {} entrance exam creation.'.format( unicode(course.id)) milestone = milestones_api.add_milestone({ 'name': 'Completed Course Entrance Exam', 'namespace': milestone_namespace, 'description': description }) relationship_types = milestones_api.get_milestone_relationship_types() milestones_api.add_course_milestone(unicode(course.id), relationship_types['REQUIRES'], milestone) milestones_api.add_course_content_milestone(unicode(course.id), created_item['locator'], relationship_types['FULFILLS'], milestone) return HttpResponse(status=201)
def setUp(self): """ Test case scaffolding """ super(EntranceExamTestCases, self).setUp() self.course = CourseFactory.create(metadata={"entrance_exam_enabled": True}) chapter = ItemFactory.create(parent=self.course, display_name="Overview") ItemFactory.create(parent=chapter, display_name="Welcome") ItemFactory.create(parent=self.course, category="chapter", display_name="Week 1") ItemFactory.create(parent=chapter, category="sequential", display_name="Lesson 1") ItemFactory.create(category="instructor", parent=self.course, data="Instructor Tab", display_name="Instructor") self.entrance_exam = ItemFactory.create( parent=self.course, category="chapter", display_name="Entrance Exam Section - Chapter 1" ) self.exam_1 = ItemFactory.create( parent=self.entrance_exam, category="sequential", display_name="Exam Sequential - Subsection 1", graded=True, metadata={"in_entrance_exam": True}, ) subsection = ItemFactory.create(parent=self.exam_1, category="vertical", display_name="Exam Vertical - Unit 1") self.problem_1 = ItemFactory.create( parent=subsection, category="problem", display_name="Exam Problem - Problem 1" ) self.problem_2 = ItemFactory.create( parent=subsection, category="problem", display_name="Exam Problem - Problem 2" ) self.problem_3 = ItemFactory.create( parent=subsection, category="problem", display_name="Exam Problem - Problem 3" ) milestone_namespace = generate_milestone_namespace(NAMESPACE_CHOICES["ENTRANCE_EXAM"], self.course.id) self.milestone = { "name": "Test Milestone", "namespace": milestone_namespace, "description": "Testing Courseware Entrance Exam Chapter", } MilestoneRelationshipType.objects.create(name="requires", active=True) MilestoneRelationshipType.objects.create(name="fulfills", active=True) self.milestone_relationship_types = milestones_api.get_milestone_relationship_types() self.milestone = milestones_api.add_milestone(self.milestone) milestones_api.add_course_milestone( unicode(self.course.id), self.milestone_relationship_types["REQUIRES"], self.milestone ) milestones_api.add_course_content_milestone( unicode(self.course.id), unicode(self.entrance_exam.location), self.milestone_relationship_types["FULFILLS"], self.milestone, ) user = UserFactory() self.request = RequestFactory() self.request.user = user self.request.COOKIES = {} self.request.META = {} self.request.is_secure = lambda: True self.request.get_host = lambda: "edx.org" self.request.method = "GET" self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents( self.course.id, user, self.entrance_exam ) self.entrance_exam.is_entrance_exam = True self.entrance_exam.in_entrance_exam = True self.course.entrance_exam_enabled = True self.course.entrance_exam_minimum_score_pct = 0.50 self.course.entrance_exam_id = unicode(self.entrance_exam.scope_ids.usage_id) modulestore().update_item(self.course, user.id) # pylint: disable=no-member
def _create_entrance_exam(request, course_key, entrance_exam_minimum_score_pct=None): """ Internal workflow operation to create an entrance exam """ # Provide a default value for the minimum score percent if nothing specified if entrance_exam_minimum_score_pct is None: entrance_exam_minimum_score_pct = _get_default_entrance_exam_minimum_pct() # Confirm the course exists course = modulestore().get_course(course_key) if course is None: return HttpResponse(status=400) # Create the entrance exam item (currently it's just a chapter) payload = { 'category': "chapter", 'display_name': "Entrance Exam", 'parent_locator': unicode(course.location), 'is_entrance_exam': True, 'in_entrance_exam': True, } parent_locator = unicode(course.location) created_block = create_xblock( parent_locator=parent_locator, user=request.user, category='chapter', display_name='Entrance Exam', is_entrance_exam=True ) # Set the entrance exam metadata flags for this course # Reload the course so we don't overwrite the new child reference course = modulestore().get_course(course_key) metadata = { 'entrance_exam_enabled': True, 'entrance_exam_minimum_score_pct': unicode(entrance_exam_minimum_score_pct), 'entrance_exam_id': unicode(created_block.location), } CourseMetadata.update_from_dict(metadata, course, request.user) # Create the entrance exam section item. create_xblock( parent_locator=unicode(created_block.location), user=request.user, category='sequential', display_name=_('Entrance Exam - Subsection') ) # Add an entrance exam milestone if one does not already exist milestone_namespace = generate_milestone_namespace( NAMESPACE_CHOICES['ENTRANCE_EXAM'], course_key ) milestones = milestones_api.get_milestones(milestone_namespace) if len(milestones): milestone = milestones[0] else: description = 'Autogenerated during {} entrance exam creation.'.format(unicode(course.id)) milestone = milestones_api.add_milestone({ 'name': 'Completed Course Entrance Exam', 'namespace': milestone_namespace, 'description': description }) relationship_types = milestones_api.get_milestone_relationship_types() milestones_api.add_course_milestone( unicode(course.id), relationship_types['REQUIRES'], milestone ) milestones_api.add_course_content_milestone( unicode(course.id), unicode(created_block.location), relationship_types['FULFILLS'], milestone ) return HttpResponse(status=201)
def setUp(self): """ Test case scaffolding """ super(EntranceExamTestCases, self).setUp() self.course = CourseFactory.create( metadata={ 'entrance_exam_enabled': True, } ) self.chapter = ItemFactory.create( parent=self.course, display_name='Overview' ) ItemFactory.create( parent=self.chapter, display_name='Welcome' ) ItemFactory.create( parent=self.course, category='chapter', display_name="Week 1" ) self.chapter_subsection = ItemFactory.create( parent=self.chapter, category='sequential', display_name="Lesson 1" ) chapter_vertical = ItemFactory.create( parent=self.chapter_subsection, category='vertical', display_name='Lesson 1 Vertical - Unit 1' ) ItemFactory.create( parent=chapter_vertical, category="problem", display_name="Problem - Unit 1 Problem 1" ) ItemFactory.create( parent=chapter_vertical, category="problem", display_name="Problem - Unit 1 Problem 2" ) ItemFactory.create( category="instructor", parent=self.course, data="Instructor Tab", display_name="Instructor" ) self.entrance_exam = ItemFactory.create( parent=self.course, category="chapter", display_name="Entrance Exam Section - Chapter 1", is_entrance_exam=True, in_entrance_exam=True ) self.exam_1 = ItemFactory.create( parent=self.entrance_exam, category='sequential', display_name="Exam Sequential - Subsection 1", graded=True, in_entrance_exam=True ) subsection = ItemFactory.create( parent=self.exam_1, category='vertical', display_name='Exam Vertical - Unit 1' ) self.problem_1 = ItemFactory.create( parent=subsection, category="problem", display_name="Exam Problem - Problem 1" ) self.problem_2 = ItemFactory.create( parent=subsection, category="problem", display_name="Exam Problem - Problem 2" ) self.problem_3 = ItemFactory.create( parent=subsection, category="problem", display_name="Exam Problem - Problem 3" ) milestone_namespace = generate_milestone_namespace( NAMESPACE_CHOICES['ENTRANCE_EXAM'], self.course.id ) self.milestone = { 'name': 'Test Milestone', 'namespace': milestone_namespace, 'description': 'Testing Courseware Entrance Exam Chapter', } MilestoneRelationshipType.objects.create(name='requires', active=True) MilestoneRelationshipType.objects.create(name='fulfills', active=True) self.milestone_relationship_types = milestones_api.get_milestone_relationship_types() self.milestone = milestones_api.add_milestone(self.milestone) milestones_api.add_course_milestone( unicode(self.course.id), self.milestone_relationship_types['REQUIRES'], self.milestone ) milestones_api.add_course_content_milestone( unicode(self.course.id), unicode(self.entrance_exam.location), self.milestone_relationship_types['FULFILLS'], self.milestone ) user = UserFactory() self.request = RequestFactory() self.request.user = user self.request.COOKIES = {} self.request.META = {} self.request.is_secure = lambda: True self.request.get_host = lambda: "edx.org" self.request.method = 'GET' self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents( self.course.id, user, self.entrance_exam ) self.course.entrance_exam_enabled = True self.course.entrance_exam_minimum_score_pct = 0.50 self.course.entrance_exam_id = unicode(self.entrance_exam.scope_ids.usage_id) modulestore().update_item(self.course, user.id) # pylint: disable=no-member self.client.login(username=self.request.user.username, password="******") CourseEnrollment.enroll(self.request.user, self.course.id) self.expected_locked_toc = ( [ { 'active': True, 'sections': [ { 'url_name': u'Exam_Sequential_-_Subsection_1', 'display_name': u'Exam Sequential - Subsection 1', 'graded': True, 'format': '', 'due': None, 'active': True } ], 'url_name': u'Entrance_Exam_Section_-_Chapter_1', 'display_name': u'Entrance Exam Section - Chapter 1' } ] ) self.expected_unlocked_toc = ( [ { 'active': False, 'sections': [ { 'url_name': u'Welcome', 'display_name': u'Welcome', 'graded': False, 'format': '', 'due': None, 'active': False }, { 'url_name': u'Lesson_1', 'display_name': u'Lesson 1', 'graded': False, 'format': '', 'due': None, 'active': False } ], 'url_name': u'Overview', 'display_name': u'Overview' }, { 'active': False, 'sections': [], 'url_name': u'Week_1', 'display_name': u'Week 1' }, { 'active': False, 'sections': [], 'url_name': u'Instructor', 'display_name': u'Instructor' }, { 'active': True, 'sections': [ { 'url_name': u'Exam_Sequential_-_Subsection_1', 'display_name': u'Exam Sequential - Subsection 1', 'graded': True, 'format': '', 'due': None, 'active': True } ], 'url_name': u'Entrance_Exam_Section_-_Chapter_1', 'display_name': u'Entrance Exam Section - Chapter 1' } ] )