def test_add_course_milestone(self): """ Unit Test: test_add_course_milestone """ with self.assertNumQueries(3): api.add_course_milestone( self.test_course_key, self.relationship_types['REQUIRES'], self.test_milestone ) requirer_milestones = api.get_course_milestones( self.test_course_key, self.relationship_types['REQUIRES'] ) self.assertEqual(len(requirer_milestones), 1) with self.assertNumQueries(3): api.add_course_milestone( self.test_prerequisite_course_key, self.relationship_types['FULFILLS'], self.test_milestone ) fulfiller_milestones = api.get_course_milestones( self.test_prerequisite_course_key, self.relationship_types['FULFILLS'], ) self.assertEqual(len(fulfiller_milestones), 1)
def test_remove_course_milestone(self): """ Unit Test: test_remove_course_milestone """ api.add_course_milestone(self.test_course_key, self.relationship_types['REQUIRES'], self.test_milestone) requirer_milestones = api.get_course_milestones( self.test_course_key, self.relationship_types['REQUIRES']) self.assertEqual(len(requirer_milestones), 1) with self.assertNumQueries(2): api.remove_course_milestone(self.test_course_key, self.test_milestone) requirer_milestones = api.get_course_milestones(self.test_course_key) self.assertEqual(len(requirer_milestones), 0)
def fulfill_course_milestone(course_key, user): """ Marks the course specified by the given course_key as complete for the given user. If any other courses require this course as a prerequisite, their milestones will be appropriately updated. """ if not ENABLE_MILESTONES_APP.is_enabled(): return None try: course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship="fulfills") except InvalidMilestoneRelationshipTypeException: # we have not seeded milestone relationship types seed_milestone_relationship_types() course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship="fulfills") for milestone in course_milestones: milestones_api.add_user_milestone({'id': user.id}, milestone)
def fulfill_course_milestone(course_key, user): """ Marks the course specified by the given course_key as complete for the given user. If any other courses require this course as a prerequisite, their milestones will be appropriately updated. """ if not settings.FEATURES.get('MILESTONES_APP'): return None try: course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship="fulfills") except InvalidMilestoneRelationshipTypeException: # we have not seeded milestone relationship types seed_milestone_relationship_types() course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship="fulfills") for milestone in course_milestones: milestones_api.add_user_milestone({'id': user.id}, milestone)
def get_course_milestones(course_id): """ Client API operation adapter/wrapper """ if not ENABLE_MILESTONES_APP.is_enabled(): return [] return milestones_api.get_course_milestones(course_id)
def test_remove_course_milestone_missing_milestone(self): """ Unit Test: test_remove_course_milestone_missing_milestone """ with self.assertNumQueries(1): api.remove_course_milestone(self.test_course_key, self.test_milestone) requirer_milestones = api.get_course_milestones(self.test_course_key) self.assertEqual(len(requirer_milestones), 0)
def get_course_milestones(course_id): """ Client API operation adapter/wrapper """ if not settings.FEATURES.get('MILESTONES_APP'): return [] return milestones_api.get_course_milestones(course_id)
def test_remove_content_references(self): """ Unit Test: test_remove_content_references """ # Add a course dependency on the test milestone api.add_course_milestone( self.test_course_key, self.relationship_types['REQUIRES'], self.test_milestone ) self.assertEqual(len(api.get_course_milestones(self.test_course_key)), 1) # Add a content fulfillment for the test milestone api.add_course_content_milestone( self.test_course_key, self.test_content_key, self.relationship_types['FULFILLS'], self.test_milestone ) milestones = api.get_course_content_milestones(self.test_course_key, self.test_content_key) self.assertEqual(len(milestones), 1) # Remove the content dependency with self.assertNumQueries(2): api.remove_content_references(self.test_content_key) milestones = api.get_course_content_milestones(self.test_course_key, self.test_content_key) self.assertEqual(len(milestones), 0)
def test_remove_course_milestone(self): """ Unit Test: test_remove_course_milestone """ api.add_course_milestone( self.test_course_key, self.relationship_types['REQUIRES'], self.test_milestone ) requirer_milestones = api.get_course_milestones( self.test_course_key, self.relationship_types['REQUIRES'] ) self.assertEqual(len(requirer_milestones), 1) with self.assertNumQueries(2): api.remove_course_milestone(self.test_course_key, self.test_milestone) requirer_milestones = api.get_course_milestones(self.test_course_key) self.assertEqual(len(requirer_milestones), 0)
def get_course_milestones(course_id): """ Client API operation adapter/wrapper """ if not settings.FEATURES.get('MILESTONES_APP', False): return [] from milestones import api as milestones_api return milestones_api.get_course_milestones(course_id)
def fulfill_course_milestone(course_key, user): """ Marks the course specified by the given course_key as complete for the given user. If any other courses require this course as a prerequisite, their milestones will be appropriately updated. """ if not settings.FEATURES.get('MILESTONES_APP', False): return None from milestones import api as milestones_api from milestones.exceptions import InvalidMilestoneRelationshipTypeException try: course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship="fulfills") except InvalidMilestoneRelationshipTypeException: # we have not seeded milestone relationship types seed_milestone_relationship_types() course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship="fulfills") for milestone in course_milestones: milestones_api.add_user_milestone({'id': user.id}, milestone)
def fulfill_course_milestone(course_key, user): """ Marks the course specified by the given course_key as complete for the given user. If any other courses require this course as a prerequisite, their milestones will be appropriately updated. """ if settings.FEATURES.get('MILESTONES_APP', False): course_milestones = get_course_milestones(course_key=course_key, relationship="fulfills") for milestone in course_milestones: add_user_milestone({'id': user.id}, milestone)
def remove_course_milestones(course_key, user, relationship): """ Remove all user milestones for the course specified by course_key. """ if not settings.FEATURES.get('MILESTONES_APP'): return None course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship=relationship) for milestone in course_milestones: milestones_api.remove_user_milestone({'id': user.id}, milestone)
def remove_course_milestones(course_key, user, relationship): """ Remove all user milestones for the course specified by course_key. """ if not ENABLE_MILESTONES_APP.is_enabled(): return None course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship=relationship) for milestone in course_milestones: milestones_api.remove_user_milestone({'id': user.id}, milestone)
def test_add_course_milestone(self): """ Unit Test: test_add_course_milestone """ with self.assertNumQueries(3): api.add_course_milestone(self.test_course_key, self.relationship_types['REQUIRES'], self.test_milestone) requirer_milestones = api.get_course_milestones( self.test_course_key, self.relationship_types['REQUIRES']) self.assertEqual(len(requirer_milestones), 1) with self.assertNumQueries(3): api.add_course_milestone(self.test_prerequisite_course_key, self.relationship_types['FULFILLS'], self.test_milestone) fulfiller_milestones = api.get_course_milestones( self.test_prerequisite_course_key, self.relationship_types['FULFILLS'], ) self.assertEqual(len(fulfiller_milestones), 1)
def test_get_course_milestones_with_invalid_relationship_type(self): """ Unit Test: test_get_course_milestones_with_invalid_relationship_type """ api.add_course_milestone( self.test_course_key, self.relationship_types['REQUIRES'], self.test_milestone ) with self.assertNumQueries(1): requirer_milestones = api.get_course_milestones( self.test_course_key, 'INVALID RELATIONSHIP TYPE' ) self.assertEqual(len(requirer_milestones), 0)
def test_remove_course_references(self): """ Unit Test: test_remove_course_references """ # Add a course dependency on the test milestone api.add_course_milestone(self.test_course_key, self.relationship_types['REQUIRES'], self.test_milestone) self.assertEqual(len(api.get_course_milestones(self.test_course_key)), 1) # Add a content fulfillment for the test milestone api.add_course_content_milestone(self.test_course_key, self.test_content_key, self.relationship_types['FULFILLS'], self.test_milestone) self.assertEqual( len( api.get_course_content_milestones(self.test_course_key, self.test_content_key)), 1) # Remove the course dependency with self.assertNumQueries(4): api.remove_course_references(self.test_course_key) self.assertEqual(len(api.get_course_milestones(self.test_course_key)), 0)
def set_prerequisite_courses(course_key, prerequisite_course_keys): """ It would remove any existing requirement milestones for the given `course_key` and create new milestones for each pre-requisite course in `prerequisite_course_keys`. To only remove course milestones pass `course_key` and empty list or None as `prerequisite_course_keys` . """ if settings.FEATURES.get('MILESTONES_APP', False): #remove any existing requirement milestones with this pre-requisite course as requirement course_milestones = get_course_milestones(course_key=course_key, relationship="requires") if course_milestones: for milestone in course_milestones: remove_prerequisite_course(course_key, milestone) # add milestones if pre-requisite course is selected if prerequisite_course_keys: for prerequisite_course_key_string in prerequisite_course_keys: prerequisite_course_key = CourseKey.from_string(prerequisite_course_key_string) add_prerequisite_course(course_key, prerequisite_course_key)
def test_contentstore_views_entrance_exam_delete(self): """ Unit Test: test_contentstore_views_entrance_exam_delete """ resp = self.client.post(self.exam_url, {}, http_accept='application/json') self.assertEqual(resp.status_code, 201) resp = self.client.get(self.exam_url) self.assertEqual(resp.status_code, 200) resp = self.client.delete(self.exam_url) self.assertEqual(resp.status_code, 204) resp = self.client.get(self.exam_url) self.assertEqual(resp.status_code, 404) user = User.objects.create( username='******', email='*****@*****.**', is_active=True, ) user.set_password('test') user.save() milestones = milestones_api.get_course_milestones( unicode(self.course_key)) self.assertEqual(len(milestones), 1) milestone_key = '{}.{}'.format(milestones[0]['namespace'], milestones[0]['name']) paths = milestones_api.get_course_milestones_fulfillment_paths( unicode(self.course_key), serialize_user(user)) # What we have now is a course milestone requirement and no valid fulfillment # paths for the specified user. The LMS is going to have to ignore this situation, # because we can't confidently prevent it from occuring at some point in the future. # milestone_key_1 = self.assertEqual(len(paths[milestone_key]), 0) # Re-adding an entrance exam to the course should fix the missing link # It wipes out any old entrance exam artifacts and inserts a new exam course chapter/module resp = self.client.post(self.exam_url, {}, http_accept='application/json') self.assertEqual(resp.status_code, 201) resp = self.client.get(self.exam_url) self.assertEqual(resp.status_code, 200)
def set_prerequisite_courses(course_key, prerequisite_course_keys): """ It would remove any existing requirement milestones for the given `course_key` and create new milestones for each pre-requisite course in `prerequisite_course_keys`. To only remove course milestones pass `course_key` and empty list or None as `prerequisite_course_keys` . """ if not is_prerequisite_courses_enabled(): return None #remove any existing requirement milestones with this pre-requisite course as requirement course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship="requires") if course_milestones: for milestone in course_milestones: remove_prerequisite_course(course_key, milestone) # add milestones if pre-requisite course is selected if prerequisite_course_keys: for prerequisite_course_key_string in prerequisite_course_keys: prerequisite_course_key = CourseKey.from_string(prerequisite_course_key_string) add_prerequisite_course(course_key, prerequisite_course_key)
def set_prerequisite_courses(course_key, prerequisite_course_keys): """ It would remove any existing requirement milestones for the given `course_key` and create new milestones for each pre-requisite course in `prerequisite_course_keys`. To only remove course milestones pass `course_key` and empty list or None as `prerequisite_course_keys` . """ if not settings.FEATURES.get('ENABLE_PREREQUISITE_COURSES', False): return None from milestones import api as milestones_api #remove any existing requirement milestones with this pre-requisite course as requirement course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship="requires") if course_milestones: for milestone in course_milestones: remove_prerequisite_course(course_key, milestone) # add milestones if pre-requisite course is selected if prerequisite_course_keys: for prerequisite_course_key_string in prerequisite_course_keys: prerequisite_course_key = CourseKey.from_string(prerequisite_course_key_string) add_prerequisite_course(course_key, prerequisite_course_key)
def test_contentstore_views_entrance_exam_delete(self): """ Unit Test: test_contentstore_views_entrance_exam_delete """ resp = self.client.post(self.exam_url, {}, http_accept='application/json') self.assertEqual(resp.status_code, 201) resp = self.client.get(self.exam_url) self.assertEqual(resp.status_code, 200) resp = self.client.delete(self.exam_url) self.assertEqual(resp.status_code, 204) resp = self.client.get(self.exam_url) self.assertEqual(resp.status_code, 404) user = User.objects.create( username='******', email='*****@*****.**', is_active=True, ) user.set_password('test') user.save() milestones = milestones_api.get_course_milestones(unicode(self.course_key)) self.assertEqual(len(milestones), 1) milestone_key = '{}.{}'.format(milestones[0]['namespace'], milestones[0]['name']) paths = milestones_api.get_course_milestones_fulfillment_paths( unicode(self.course_key), serialize_user(user) ) # What we have now is a course milestone requirement and no valid fulfillment # paths for the specified user. The LMS is going to have to ignore this situation, # because we can't confidently prevent it from occuring at some point in the future. # milestone_key_1 = self.assertEqual(len(paths[milestone_key]), 0) # Re-adding an entrance exam to the course should fix the missing link # It wipes out any old entrance exam artifacts and inserts a new exam course chapter/module resp = self.client.post(self.exam_url, {}, http_accept='application/json') self.assertEqual(resp.status_code, 201) resp = self.client.get(self.exam_url) self.assertEqual(resp.status_code, 200)
def test_contentstore_views_entrance_exam_post(self): """ Unit Test: test_contentstore_views_entrance_exam_post """ resp = self.client.post(self.exam_url, {}, http_accept='application/json') self.assertEqual(resp.status_code, 201) resp = self.client.get(self.exam_url) self.assertEqual(resp.status_code, 200) # Reload the test course now that the exam module has been added self.course = modulestore().get_course(self.course.id) metadata = CourseMetadata.fetch_all(self.course) self.assertTrue(metadata['entrance_exam_enabled']) self.assertIsNotNone(metadata['entrance_exam_minimum_score_pct']) self.assertIsNotNone(metadata['entrance_exam_id']['value']) self.assertTrue(len(milestones_api.get_course_milestones(unicode(self.course.id)))) content_milestones = milestones_api.get_course_content_milestones( unicode(self.course.id), metadata['entrance_exam_id']['value'], self.milestone_relationship_types['FULFILLS'] ) self.assertTrue(len(content_milestones))
def test_contentstore_views_entrance_exam_post(self): """ Unit Test: test_contentstore_views_entrance_exam_post """ resp = self.client.post(self.exam_url, {}, http_accept='application/json') self.assertEqual(resp.status_code, 201) resp = self.client.get(self.exam_url) self.assertEqual(resp.status_code, 200) # Reload the test course now that the exam module has been added self.course = modulestore().get_course(self.course.id) metadata = CourseMetadata.fetch_all(self.course) self.assertTrue(metadata['entrance_exam_enabled']) self.assertIsNotNone(metadata['entrance_exam_minimum_score_pct']) self.assertIsNotNone(metadata['entrance_exam_id']['value']) self.assertTrue( len( milestones_api.get_course_milestones( unicode(self.course.id)))) content_milestones = milestones_api.get_course_content_milestones( unicode(self.course.id), metadata['entrance_exam_id']['value'], self.milestone_relationship_types['FULFILLS']) self.assertTrue(len(content_milestones))
def test_get_course_unfulfilled_milestones(self): """ Unit Test: test_get_course_unfulfilled_milestones """ namespace = 'test_get_milestones' milestone1 = api.add_milestone({ 'name': 'localmilestone1', 'display_name': 'Local Milestone 1', 'namespace': namespace, 'description': 'Local Milestone 1 Description' }) api.add_course_milestone( self.test_course_key, self.relationship_types['REQUIRES'], milestone1 ) milestone2 = api.add_milestone({ 'name': 'localmilestone2', 'display_name': 'Local Milestone 2', 'namespace': namespace, 'description': 'Local Milestone 2 Description' }) api.add_course_milestone( self.test_course_key, self.relationship_types['REQUIRES'], milestone2 ) # Confirm that the course has only two milestones, and that the User still needs to collect both course_milestones = api.get_course_milestones(self.test_course_key) self.assertEqual(len(course_milestones), 2) with self.assertNumQueries(2): required_milestones = api.get_course_required_milestones( self.test_course_key, self.serialized_test_user ) # Link the User to Milestone 2 (this one is now 'collected') api.add_user_milestone(self.serialized_test_user, milestone2) user_milestones = api.get_user_milestones(self.serialized_test_user, namespace=namespace) self.assertEqual(len(user_milestones), 1) self.assertEqual(user_milestones[0]['id'], milestone2['id']) # Only Milestone 1 should be listed as 'required' for the course at this point with self.assertNumQueries(2): required_milestones = api.get_course_required_milestones( self.test_course_key, self.serialized_test_user ) self.assertEqual(len(required_milestones), 1) self.assertEqual(required_milestones[0]['id'], milestone1['id']) # Link the User to Milestone 1 (this one is now 'collected', as well) api.add_user_milestone(self.serialized_test_user, milestone1) user_milestones = api.get_user_milestones(self.serialized_test_user, namespace=namespace) self.assertEqual(len(user_milestones), 2) # And there should be no more Milestones required for this User+Course with self.assertNumQueries(2): required_milestones = api.get_course_required_milestones( self.test_course_key, self.serialized_test_user ) self.assertEqual(len(required_milestones), 0)
def test_get_course_unfulfilled_milestones(self): """ Unit Test: test_get_course_unfulfilled_milestones """ namespace = 'test_get_milestones' milestone1 = api.add_milestone({ 'name': 'localmilestone1', 'display_name': 'Local Milestone 1', 'namespace': namespace, 'description': 'Local Milestone 1 Description' }) api.add_course_milestone(self.test_course_key, self.relationship_types['REQUIRES'], milestone1) milestone2 = api.add_milestone({ 'name': 'localmilestone2', 'display_name': 'Local Milestone 2', 'namespace': namespace, 'description': 'Local Milestone 2 Description' }) api.add_course_milestone(self.test_course_key, self.relationship_types['REQUIRES'], milestone2) # Confirm that the course has only two milestones, and that the User still needs to collect both course_milestones = api.get_course_milestones(self.test_course_key) self.assertEqual(len(course_milestones), 2) with self.assertNumQueries(2): required_milestones = api.get_course_required_milestones( self.test_course_key, self.serialized_test_user) # Link the User to Milestone 2 (this one is now 'collected') api.add_user_milestone(self.serialized_test_user, milestone2) user_milestones = api.get_user_milestones(self.serialized_test_user, namespace=namespace) self.assertEqual(len(user_milestones), 1) self.assertEqual(user_milestones[0]['id'], milestone2['id']) # Only Milestone 1 should be listed as 'required' for the course at this point with self.assertNumQueries(2): required_milestones = api.get_course_required_milestones( self.test_course_key, self.serialized_test_user) self.assertEqual(len(required_milestones), 1) self.assertEqual(required_milestones[0]['id'], milestone1['id']) # Link the User to Milestone 1 (this one is now 'collected', as well) api.add_user_milestone(self.serialized_test_user, milestone1) user_milestones = api.get_user_milestones(self.serialized_test_user, namespace=namespace) self.assertEqual(len(user_milestones), 2) # And there should be no more Milestones required for this User+Course with self.assertNumQueries(2): required_milestones = api.get_course_required_milestones( self.test_course_key, self.serialized_test_user) self.assertEqual(len(required_milestones), 0)