def setUpClass(cls): super().setUpClass() cls.course = CourseFactory( name='fake', org='course', run='id', ) cls.course_key = cls.course.location.course_key # lint-amnesty, pylint: disable=no-member with cls.store.bulk_operations(cls.course.id, emit_signals=False): # lint-amnesty, pylint: disable=no-member cls.parent = ItemFactory( category="library_content", parent=cls.course, publish_item=True, ) cls.child = ItemFactory( category="html", parent=cls.parent, publish_item=True, ) cls.unrelated = ItemFactory( category="html", parent=cls.course, publish_item=True, ) cls.team_enabled_ora = ItemFactory.create( parent=cls.parent, category="openassessment", teams_enabled=True, selected_teamset_id='final project teamset')
def setUpClass(cls): super(TestInstructorEnrollmentStudentModule, cls).setUpClass() cls.course = CourseFactory( name='fake', org='course', run='id', ) # pylint: disable=no-member cls.course_key = cls.course.location.course_key with cls.store.bulk_operations(cls.course.id, emit_signals=False): cls.parent = ItemFactory( category="library_content", parent=cls.course, publish_item=True, ) cls.child = ItemFactory( category="html", parent=cls.parent, publish_item=True, ) cls.unrelated = ItemFactory( category="html", parent=cls.course, publish_item=True, )
def setUpClass(cls): super().setUpClass() cls.store = modulestore() cls.course = ToyCourseFactory.create( end=datetime(2028, 1, 1, 1, 1, 1), enrollment_start=datetime(2020, 1, 1, 1, 1, 1), enrollment_end=datetime(2028, 1, 1, 1, 1, 1), emit_signals=True, modulestore=cls.store, certificate_available_date=_NEXT_WEEK, certificates_display_behavior=CertificatesDisplayBehaviors. END_WITH_DATE) cls.chapter = ItemFactory(parent=cls.course, category='chapter') cls.sequence = ItemFactory(parent=cls.chapter, category='sequential', display_name='sequence') cls.unit = ItemFactory.create(parent=cls.sequence, category='vertical', display_name="Vertical") cls.user = UserFactory(username='******', email='*****@*****.**', password='******', is_staff=False) cls.instructor = UserFactory(username='******', email='*****@*****.**', password='******', is_staff=False) CourseInstructorRole(cls.course.id).add_users(cls.instructor) cls.url = f'/api/courseware/course/{cls.course.id}'
def test_vertical_completion_with_nested_children(self): # Create a new vertical. # It is very important that we use parent_location=self.sequence.location (and not parent=self.sequence), since # sequence is a class attribute and passing it by value will update its .children=[] which will then leak into # other tests and cause errors if the children no longer exist. parent_vertical = ItemFactory(parent_location=self.sequence.location, category='vertical') extra_vertical = ItemFactory(parent=parent_vertical, category='vertical') problem = ItemFactory(parent=extra_vertical, category='problem') parent_vertical = self.store.get_item(parent_vertical.location) # Nothing is complete assert not self.completion_service.vertical_is_complete( parent_vertical) for block_key in self.block_keys: BlockCompletion.objects.submit_completion(user=self.user, block_key=block_key, completion=1.0) # The nested child isn't complete yet assert not self.completion_service.vertical_is_complete( parent_vertical) BlockCompletion.objects.submit_completion(user=self.user, block_key=problem.location, completion=1.0) assert self.completion_service.vertical_is_complete(parent_vertical)
def test_vertical_completion_with_nested_children(self): parent_vertical = ItemFactory(parent=self.sequence, category='vertical') extra_vertical = ItemFactory(parent=parent_vertical, category='vertical') problem = ItemFactory(parent=extra_vertical, category='problem') parent_vertical = self.store.get_item(parent_vertical.location) # Nothing is complete self.assertFalse( self.completion_service.vertical_is_complete(parent_vertical)) for block_key in self.block_keys: BlockCompletion.objects.submit_completion(user=self.user, block_key=block_key, completion=1.0) # The nested child isn't complete yet self.assertFalse( self.completion_service.vertical_is_complete(parent_vertical)) BlockCompletion.objects.submit_completion(user=self.user, block_key=problem.location, completion=1.0) self.assertTrue( self.completion_service.vertical_is_complete(parent_vertical))
def test_repeated_course_module_instantiation(self, loops, default_store, course_depth): with modulestore().default_store(default_store): course = CourseFactory.create() chapter = ItemFactory(parent=course, category='chapter', graded=True) section = ItemFactory(parent=chapter, category='sequential') __ = ItemFactory(parent=section, category='problem') fake_request = self.factory.get( reverse('progress', kwargs={'course_id': unicode(course.id)})) course = modulestore().get_course(course.id, depth=course_depth) for _ in xrange(loops): field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course.id, self.user, course, depth=course_depth) course_module = get_module_for_descriptor(self.user, fake_request, course, field_data_cache, course.id, course=course) for chapter in course_module.get_children(): for section in chapter.get_children(): for item in section.get_children(): self.assertTrue(item.graded)
def setUpClass(cls): super().setUpClass() cls.store = modulestore() cls.course = CourseFactory.create( start=datetime(2020, 1, 1), end=datetime(2028, 1, 1), enrollment_start=datetime(2020, 1, 1), enrollment_end=datetime(2028, 1, 1), emit_signals=True, modulestore=cls.store, ) chapter = ItemFactory(parent=cls.course, category='chapter') ItemFactory(parent=chapter, category='sequential') CourseModeFactory(course_id=cls.course.id, mode_slug=CourseMode.AUDIT) CourseModeFactory(course_id=cls.course.id, mode_slug=CourseMode.VERIFIED, expiration_datetime=datetime(2028, 1, 1)) VerificationDeadline.objects.create(course_key=cls.course.id, deadline=datetime(2028, 1, 1)) cls.user = UserFactory(username='******', email='*****@*****.**', password='******', is_staff=False) CourseOverviewFactory.create(run='1T2020')
def test_sequence_with_ora_and_non_ora_assignments(self): """ _gather_graded_items should not set a due date for ORA problems """ with self.store.bulk_operations(self.course.id): sequence = ItemFactory(parent=self.course, category="sequential") vertical = ItemFactory(parent=sequence, category="vertical") ItemFactory.create(parent=vertical, category='openassessment', graded=True) ungraded_problem_2 = ItemFactory.create( parent=vertical, category='problem', graded=True, weight=0, ) graded_problem_1 = ItemFactory.create( parent=vertical, category='problem', graded=True, weight=1, ) expected_graded_items = [ (ungraded_problem_2.location, { 'due': None }), (graded_problem_1.location, { 'due': 5 }), ] sequence = self.store.get_item(sequence.location) self.assertCountEqual(_gather_graded_items(sequence, 5), expected_graded_items)
def test_completion_ignores_non_scored_items(self): """ Test that we treat a sequential with incomplete (but not scored) items (like a video maybe) as complete. """ course = CourseFactory() chapter = ItemFactory(parent=course, category='chapter', graded=True, due=datetime.datetime.now(), start=datetime.datetime.now() - datetime.timedelta(hours=1)) sequential = ItemFactory(parent=chapter, category='sequential') problem = ItemFactory(parent=sequential, category='problem', has_score=True) ItemFactory(parent=sequential, category='video', has_score=False) self.override_waffle_switch(True) BlockCompletion.objects.submit_completion(self.user, problem.location, 1) assignments = get_course_assignments(course.location.context_key, self.user, None) assert len(assignments) == 1 assert assignments[0].complete
def test_completion_does_not_treat_unreleased_as_complete(self): """ Test that unreleased assignments are not treated as complete. """ course = CourseFactory() chapter = ItemFactory( parent=course, category='chapter', graded=True, due=datetime.datetime.now() + datetime.timedelta(hours=2), start=datetime.datetime.now() + datetime.timedelta(hours=1)) sequential = ItemFactory(parent=chapter, category='sequential') problem = ItemFactory(parent=sequential, category='problem', has_score=True) ItemFactory(parent=sequential, category='video', has_score=False) self.override_waffle_switch(True) BlockCompletion.objects.submit_completion(self.user, problem.location, 1) assignments = get_course_assignments(course.location.context_key, self.user, None) assert len(assignments) == 1 assert not assignments[0].complete
def setUp(self): super().setUp() self.course = CourseFactory.create( start=datetime(2020, 1, 1), end=datetime(2028, 1, 1), enrollment_start=datetime(2020, 1, 1), enrollment_end=datetime(2028, 1, 1), emit_signals=True, modulestore=self.store, discussion_topics={"Test Topic": { "id": "test_topic" }}, ) chapter = ItemFactory(parent=self.course, category='chapter') ItemFactory(parent=chapter, category='sequential') self.client.login(username=self.user.username, password=self.user_password) CourseEnrollment.enroll(self.user, self.course.id) self.request = RequestFactory().get('foo') self.request.user = self.user config = ForumsConfig.current() config.enabled = True config.save()
def setUpClass(cls): super().setUpClass() cls.store = modulestore() cls.course = ToyCourseFactory.create( end=datetime(2028, 1, 1, 1, 1, 1), enrollment_start=datetime(2020, 1, 1, 1, 1, 1), enrollment_end=datetime(2028, 1, 1, 1, 1, 1), emit_signals=True, modulestore=cls.store, ) cls.chapter = ItemFactory(parent=cls.course, category='chapter') cls.sequence = ItemFactory(parent=cls.chapter, category='sequential', display_name='sequence') cls.unit = ItemFactory.create(parent=cls.sequence, category='vertical', display_name="Vertical") cls.user = UserFactory(username='******', email=u'*****@*****.**', password='******', is_staff=False) cls.instructor = UserFactory(username='******', email=u'*****@*****.**', password='******', is_staff=False) CourseInstructorRole(cls.course.id).add_users(cls.instructor) cls.url = '/api/courseware/course/{}'.format(cls.course.id)
def setUp(self): super().setUp() self.course = CourseFactory.create( start=datetime(2020, 1, 1), end=datetime(2028, 1, 1), enrollment_start=datetime(2020, 1, 1), enrollment_end=datetime(2028, 1, 1), emit_signals=True, modulestore=self.store, ) chapter = ItemFactory(parent=self.course, category='chapter') ItemFactory(parent=chapter, category='sequential') CourseModeFactory(course_id=self.course.id, mode_slug=CourseMode.AUDIT) CourseModeFactory(course_id=self.course.id, mode_slug=CourseMode.VERIFIED, expiration_datetime=datetime(2028, 1, 1)) VerificationDeadline.objects.create(course_key=self.course.id, deadline=datetime(2028, 1, 1)) CourseOverviewFactory.create(run='1T2020') self.staff_user = self.user self.user, password = self.create_non_staff_user() self.client.login(username=self.user.username, password=password)
def test_sequence_with_graded_and_ungraded_assignments(self): """ _gather_graded_items should set a due date of None on ungraded problem blocks even if the block has graded siblings in the sequence """ with modulestore().bulk_operations(self.course.id): sequence = ItemFactory(parent=self.course, category="sequential") vertical = ItemFactory(parent=sequence, category="vertical") sequence = modulestore().get_item(sequence.location) ItemFactory.create( parent=vertical, category='problem', graded=False, weight=1, ) ungraded_problem_2 = ItemFactory.create( parent=vertical, category='problem', graded=True, weight=0, ) graded_problem_1 = ItemFactory.create( parent=vertical, category='problem', graded=True, weight=1, ) expected_graded_items = [ (ungraded_problem_2.location, {'due': None}), (graded_problem_1.location, {'due': 5}), ] sequence = modulestore().get_item(sequence.location) self.assertCountEqual(_gather_graded_items(sequence, 5), expected_graded_items)
def setUp(self): super(TestInstructorEnrollmentStudentModule, self).setUp() store = modulestore() self.user = UserFactory() self.course = CourseFactory( name='fake', org='course', run='id', ) # pylint: disable=no-member self.course_key = self.course.location.course_key self.parent = ItemFactory( category="library_content", # pylint: disable=no-member user_id=self.user.id, parent=self.course, publish_item=True, modulestore=store, ) self.child = ItemFactory( category="html", # pylint: disable=no-member user_id=self.user.id, parent=self.parent, publish_item=True, modulestore=store, ) self.unrelated = ItemFactory( category="html", # pylint: disable=no-member user_id=self.user.id, parent=self.course, publish_item=True, modulestore=store, ) parent_state = json.dumps({'attempts': 32, 'otherstuff': 'alsorobots'}) child_state = json.dumps({'attempts': 10, 'whatever': 'things'}) unrelated_state = json.dumps({'attempts': 12, 'brains': 'zombie'}) StudentModule.objects.create( student=self.user, course_id=self.course_key, module_state_key=self.parent.location, state=parent_state, ) StudentModule.objects.create( student=self.user, course_id=self.course_key, module_state_key=self.child.location, state=child_state, ) StudentModule.objects.create( student=self.user, course_id=self.course_key, module_state_key=self.unrelated.location, state=unrelated_state, )
def test_get_chapters(self): """ Test get_course_chapter_ids returns expected result. """ course = CourseFactory() ItemFactory(parent=course, category='chapter') ItemFactory(parent=course, category='chapter') course_chapter_ids = get_course_chapter_ids(course.location.course_key) assert len(course_chapter_ids) == 2 assert course_chapter_ids == [str(child) for child in course.children]
def setUpClass(cls): super().setUpClass() chapter = ItemFactory(parent=cls.course, category='chapter') cls.sequence = ItemFactory(parent=chapter, category='sequential', display_name='sequence') ItemFactory.create(parent=cls.sequence, category='vertical', display_name="Vertical") cls.url = '/api/courseware/sequence/{}'.format(cls.sequence.location)
def test_fetch_problems(self): ItemFactory(parent=self.course, category='problem', display_name='problem1') ItemFactory(parent=self.course, category='problem', display_name='problem2') problems = utils.fetch_problems(self.store, self.course.id) self.assertEqual(len(problems), 3) for problem in problems: self.assertTrue(isinstance(problem, CapaDescriptor))
def test_get_chapters(self): """ Test get_course_chapter_ids returns expected result. """ course = CourseFactory() ItemFactory(parent=course, category='chapter') ItemFactory(parent=course, category='chapter') course_chapter_ids = get_course_chapter_ids(course.location.course_key) self.assertEqual(len(course_chapter_ids), 2) self.assertEqual(course_chapter_ids, [six.text_type(child) for child in course.children])
def add_subsection_with_problem(self, **kwargs): """Makes a chapter -> problem chain, and sets up the subsection as requested, returning the problem""" chapter = ItemFactory(parent=self.course, category='chapter') subsection = ItemFactory(parent=chapter, category='sequential', graded=True, **kwargs) vertical = ItemFactory(parent=subsection, category='vertical', graded=True) problem = ItemFactory(parent=vertical, category='problem', graded=True) return problem
def test_completion_does_not_count_empty_sequentials(self): """ Test that we treat a sequential with no content as incomplete. This can happen with unreleased assignments, for example (start date in future). """ course = CourseFactory() chapter = ItemFactory(parent=course, category='chapter', graded=True, due=datetime.datetime.now()) ItemFactory(parent=chapter, category='sequential') assignments = get_course_assignments(course.location.context_key, self.user, None) assert len(assignments) == 1 assert not assignments[0].complete
def set_up_course(self, **course_kwargs): """ Create a stock course with a specific due date. :param course_kwargs: All kwargs are passed to through to the :class:`CourseFactory` """ course = CourseFactory(**course_kwargs) chapter = ItemFactory(category='chapter', parent_location=course.location) # pylint: disable=no-member section = ItemFactory(category='sequential', parent_location=chapter.location, due=datetime(2013, 9, 18, 11, 30, 00)) vertical = ItemFactory(category='vertical', parent_location=section.location) ItemFactory(category='problem', parent_location=vertical.location) course = modulestore().get_instance(course.id, course.location) # pylint: disable=no-member self.assertIsNotNone(course.get_children()[0].get_children()[0].due) return course
def test_has_scheduled_content_data(self): CourseEnrollment.enroll(self.user, self.course.id) future = now() + timedelta(days=30) ItemFactory(parent=self.course, category='chapter', start=future) response = self.client.get(self.url) assert response.status_code == 200 assert response.json()['has_scheduled_content']
def test_hidden_after_due(self, is_past_due, masquerade_config, expected_hidden, expected_banner): """Validate the metadata when hide-after-due is set for a sequence""" due = datetime.now() + timedelta(days=-1 if is_past_due else 1) sequence = ItemFactory( parent_location=self.chapter.location, # ^ It is very important that we use parent_location=self.chapter.location (and not parent=self.chapter), as # chapter is a class attribute and passing it by value will update its .children=[] which will then leak # into other tests and cause errors if the children no longer exist. category='sequential', hide_after_due=True, due=due, ) CourseEnrollment.enroll(self.user, self.course.id) user = self.instructor if masquerade_config else self.user self.client.login(username=user.username, password='******') if masquerade_config: self.update_masquerade(**masquerade_config) response = self.client.get( f'/api/courseware/sequence/{sequence.location}') assert response.status_code == 200 assert response.data['is_hidden_after_due'] == expected_hidden assert bool(response.data['banner_text']) == expected_banner
def test_build_answers_distribution_report_name(self): problem_name = u"Quizz trés fà cile." problem = ItemFactory(parent=self.course, category='problem', display_name=problem_name) report_name = utils.build_answers_distribution_report_name(problem) assert report_name
def setUp(self): super().setUp() self.course = CourseFactory.create() for i in range(4): ItemFactory(parent=self.course, category="sequential", display_name="Section {}".format(i))
def test_url_hidden_if_subsection_hide_after_due(self): chapter = ItemFactory(parent=self.course, category='chapter') yesterday = now() - timedelta(days=1) hide_after_due_subsection = ItemFactory( parent=chapter, category='sequential', hide_after_due=True, due=yesterday ) CourseEnrollment.enroll(self.user, self.course.id) response = self.client.get(self.url) assert response.status_code == 200 sections = response.data['section_scores'] regular_subsection = sections[0]['subsections'][0] # default sequence that parent class gives us hide_after_due_subsection = sections[1]['subsections'][0] assert regular_subsection['url'] is not None assert hide_after_due_subsection['url'] is None
def setUp(self): self.request_factory = RequestFactory() self.user = UserFactory.create() self.request = self.request_factory.get("foo") self.request.user = self.user MakoMiddleware().process_request(self.request) course = CourseFactory(start=datetime(2013, 9, 16, 7, 17, 28)) self.course = modulestore().get_instance(course.id, course.location) # pylint: disable=no-member self.chapter = ItemFactory(category='chapter', parent_location=self.course.location) # pylint: disable=no-member self.section = ItemFactory(category='sequential', parent_location=self.chapter.location) self.vertical = ItemFactory(category='vertical', parent_location=self.section.location)
def test_xqueue_is_not_available_in_studio(self): descriptor = ItemFactory(category="problem", parent=self.course) runtime = _preview_module_system( self.request, descriptor=descriptor, field_data=mock.Mock(), ) assert runtime.xqueue is None assert runtime.service(descriptor, 'xqueue') is None
def _generate_modules_tree_with_display_names(self, module, *args): if not args: self.problem_module = module return category = args[0] self._generate_modules_tree_with_display_names(ItemFactory(parent=module, category=category, display_name=category), *args[1:])