def test_get_limited_number_of_courses_using_config(self): course_location = self.store.make_course_key('Org0', 'Course0', 'Run0') self._create_course_with_access_groups(course_location) course_location = self.store.make_course_key('Org1', 'Course1', 'Run1') self._create_course_with_access_groups(course_location) # get dashboard courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(len(courses_list), 2) with self.settings(DASHBOARD_COURSE_LIMIT=1): course_limit = settings.DASHBOARD_COURSE_LIMIT courses_list = list(get_course_enrollments(self.student, None, [], course_limit)) self.assertEqual(len(courses_list), 1)
def test_course_listing_has_pre_requisite_courses(self): """ Creates four courses. Enroll test user in all courses Sets two of them as pre-requisites of another course. Checks course where pre-requisite course is set has appropriate info. """ course_location2 = self.store.make_course_key('Org1', 'Course2', 'Run2') self._create_course_with_access_groups(course_location2) pre_requisite_course_location = self.store.make_course_key('Org1', 'Course3', 'Run3') self._create_course_with_access_groups(pre_requisite_course_location) pre_requisite_course_location2 = self.store.make_course_key('Org1', 'Course4', 'Run4') self._create_course_with_access_groups(pre_requisite_course_location2) # create a course with pre_requisite_courses pre_requisite_courses = [ unicode(pre_requisite_course_location), unicode(pre_requisite_course_location2), ] course_location = self.store.make_course_key('Org1', 'Course1', 'Run1') self._create_course_with_access_groups(course_location, { 'pre_requisite_courses': pre_requisite_courses }) set_prerequisite_courses(course_location, pre_requisite_courses) # get dashboard course_enrollments = list(get_course_enrollments(self.student, None, [])) courses_having_prerequisites = frozenset( enrollment.course_id for enrollment in course_enrollments if enrollment.course_overview.pre_requisite_courses ) courses_requirements_not_met = get_pre_requisite_courses_not_completed( self.student, courses_having_prerequisites ) self.assertEqual(len(courses_requirements_not_met[course_location]['courses']), len(pre_requisite_courses))
def test_get_course_list(self): """ Test getting courses """ course_location = self.store.make_course_key('Org1', 'Course1', 'Run1') self._create_course_with_access_groups(course_location) # get dashboard courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(len(courses_list), 1) self.assertEqual(courses_list[0].course_id, course_location) CourseEnrollment.unenroll(self.student, course_location) # get dashboard courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(len(courses_list), 0)
def test_course_listing_has_pre_requisite_courses(self): """ Creates four courses. Enroll test user in all courses Sets two of them as pre-requisites of another course. Checks course where pre-requisite course is set has appropriate info. """ course_location2 = self.store.make_course_key('Org1', 'Course2', 'Run2') self._create_course_with_access_groups(course_location2) pre_requisite_course_location = self.store.make_course_key('Org1', 'Course3', 'Run3') self._create_course_with_access_groups(pre_requisite_course_location) pre_requisite_course_location2 = self.store.make_course_key('Org1', 'Course4', 'Run4') self._create_course_with_access_groups(pre_requisite_course_location2) # create a course with pre_requisite_courses pre_requisite_courses = [ six.text_type(pre_requisite_course_location), six.text_type(pre_requisite_course_location2), ] course_location = self.store.make_course_key('Org1', 'Course1', 'Run1') self._create_course_with_access_groups(course_location, { 'pre_requisite_courses': pre_requisite_courses }) set_prerequisite_courses(course_location, pre_requisite_courses) # get dashboard course_enrollments = list(get_course_enrollments(self.student, None, [])) courses_having_prerequisites = frozenset( enrollment.course_id for enrollment in course_enrollments if enrollment.course_overview.pre_requisite_courses ) courses_requirements_not_met = get_pre_requisite_courses_not_completed( self.student, courses_having_prerequisites ) self.assertEqual(len(courses_requirements_not_met[course_location]['courses']), len(pre_requisite_courses))
def test_dashboard_rendering_with_two_courses(self): """ Tests that the dashboard renders the recent enrollment message appropriately for two courses. """ self._configure_message_timeout(600) course_location = locator.CourseLocator('Org2', 'Course2', 'Run2') course, _ = self._create_course_and_enrollment(course_location) self.client.login(username=self.student.username, password=self.PASSWORD) response = self.client.get(reverse("dashboard")) courses_enrollments = list( get_course_enrollments(self.student, None, [])) courses_enrollments.sort(key=lambda x: x.created, reverse=True) self.assertEqual(len(courses_enrollments), 3) recent_course_enrollments = _get_recently_enrolled_courses( courses_enrollments) self.assertEqual(len(recent_course_enrollments), 2) self.assertContains( response, "Thank you for enrolling in:".format( course_name=self.course.display_name)) self.assertContains( response, ' and '.join(enrollment.course.display_name for enrollment in recent_course_enrollments))
def view_programs(request): """View programs in which the user is engaged.""" show_program_listing = ProgramsApiConfig.current().show_program_listing if not show_program_listing: raise Http404 enrollments = list(get_course_enrollments(request.user, None, [])) meter = ProgramProgressMeter(request.user, enrollments) programs = meter.engaged_programs # TODO: Pull 'xseries' string from configuration model. marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries').strip('/') for program in programs: program['display_category'] = get_display_category(program) program['marketing_url'] = '{root}/{slug}'.format( root=marketing_root, slug=program['marketing_slug'] ) context = { 'programs': programs, 'progress': meter.progress, 'xseries_url': marketing_root if ProgramsApiConfig.current().show_xseries_ad else None, 'nav_hidden': True, 'show_program_listing': show_program_listing, 'credentials': get_programs_credentials(request.user, category='xseries'), 'disable_courseware_js': True, 'uses_pattern_library': True } return render_to_response('learner_dashboard/programs.html', context)
def test_enrollments_sorted_most_recent(self): """ Test that the list of newly created courses are properly sorted to show the most recent enrollments first. """ self._configure_message_timeout(600) # Create a number of new enrollments and courses, and force their creation behind # the first enrollment courses = [] for idx, seconds_past in zip(range(2, 6), [5, 10, 15, 20]): course_location = locator.CourseLocator( 'Org{num}'.format(num=idx), 'Course{num}'.format(num=idx), 'Run{num}'.format(num=idx) ) course, enrollment = self._create_course_and_enrollment(course_location) enrollment.created = datetime.datetime.now(UTC) - datetime.timedelta(seconds=seconds_past) enrollment.save() courses.append(course) courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(len(courses_list), 6) recent_course_list = _get_recently_enrolled_courses(courses_list) self.assertEqual(len(recent_course_list), 5) self.assertEqual(recent_course_list[1].course.id, courses[0].id) self.assertEqual(recent_course_list[2].course.id, courses[1].id) self.assertEqual(recent_course_list[3].course.id, courses[2].id) self.assertEqual(recent_course_list[4].course.id, courses[3].id)
def view_programs(request): """View programs in which the user is engaged.""" show_program_listing = ProgramsApiConfig.current().show_program_listing if not show_program_listing: raise Http404 enrollments = list(get_course_enrollments(request.user, None, [])) programs = get_engaged_programs(request.user, enrollments) # TODO: Pull 'xseries' string from configuration model. marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries').strip('/') for program in programs: program['marketing_url'] = '{root}/{slug}'.format( root=marketing_root, slug=program['marketing_slug']) return render_to_response( 'learner_dashboard/programs.html', { 'programs': programs, 'xseries_url': marketing_root if ProgramsApiConfig.current().show_xseries_ad else None, 'nav_hidden': True, 'show_program_listing': show_program_listing })
def test_dashboard_rendering_with_two_courses(self): """ Tests that the dashboard renders the recent enrollment message appropriately for two courses. """ self._configure_message_timeout(600) course_location = locator.CourseLocator( 'Org2', 'Course2', 'Run2' ) course, _ = self._create_course_and_enrollment(course_location) self.client.login(username=self.student.username, password=self.PASSWORD) response = self.client.get(reverse("dashboard")) courses_enrollments = list(get_course_enrollments(self.student, None, [])) courses_enrollments.sort(key=lambda x: x.created, reverse=True) self.assertEqual(len(courses_enrollments), 3) recent_course_enrollments = _get_recently_enrolled_courses(courses_enrollments) self.assertEqual(len(recent_course_enrollments), 2) self.assertContains( response, "Thank you for enrolling in:".format(course_name=self.course.display_name) ) self.assertContains( response, ' and '.join(enrollment.course.display_name for enrollment in recent_course_enrollments) )
def test_zero_second_delta(self): """ Tests that the recent enrollment list is empty if configured to zero seconds. """ self._configure_message_timeout(0) courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(len(courses_list), 2) recent_course_list = _get_recently_enrolled_courses(courses_list) self.assertEqual(len(recent_course_list), 0)
def get_subscription_catalog_ids(user, course_enrollments=None): if not course_enrollments: site_org_whitelist, site_org_blacklist = get_org_black_and_whitelist_for_site( user) course_enrollments = list( get_course_enrollments(user, site_org_whitelist, site_org_blacklist)) course_enrollments.sort(key=lambda x: x.created, reverse=True) subscription_courses = frozenset( get_subscription_catalog_id(enrollment.course_id) for enrollment in course_enrollments) return filter(None, subscription_courses)
def test_recently_enrolled_courses(self): """ Test if the function for filtering recent enrollments works appropriately. """ self._configure_message_timeout(60) # get courses through iterating all courses courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(len(courses_list), 2) recent_course_list = _get_recently_enrolled_courses(courses_list) self.assertEqual(len(recent_course_list), 1)
def test_errored_course_regular_access(self): """ Test the course list for regular staff when get_course returns an ErrorDescriptor """ # pylint: disable=protected-access mongo_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) course_key = mongo_store.make_course_key('Org1', 'Course1', 'Run1') self._create_course_with_access_groups(course_key, default_store=ModuleStoreEnum.Type.mongo) with patch('xmodule.modulestore.mongo.base.MongoKeyValueStore', Mock(side_effect=Exception)): self.assertIsInstance(modulestore().get_course(course_key), ErrorDescriptor) # get courses through iterating all courses courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(courses_list, [])
def test_course_listing_errored_deleted_courses(self): """ Create good courses, courses that won't load, and deleted courses which still have roles. Test course listing. """ mongo_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) good_location = mongo_store.make_course_key('testOrg', 'testCourse', 'RunBabyRun') self._create_course_with_access_groups(good_location, default_store=ModuleStoreEnum.Type.mongo) course_location = mongo_store.make_course_key('testOrg', 'doomedCourse', 'RunBabyRun') self._create_course_with_access_groups(course_location, default_store=ModuleStoreEnum.Type.mongo) mongo_store.delete_course(course_location, ModuleStoreEnum.UserID.test) courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(len(courses_list), 1, courses_list) self.assertEqual(courses_list[0].course_id, good_location)
def test_errored_course_regular_access(self): """ Test the course list for regular staff when get_course returns an ErrorDescriptor """ # pylint: disable=protected-access mongo_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) course_key = mongo_store.make_course_key('Org1', 'Course1', 'Run1') self._create_course_with_access_groups(course_key, default_store=ModuleStoreEnum.Type.mongo) with mock.patch('xmodule.modulestore.mongo.base.MongoKeyValueStore', mock.Mock(side_effect=Exception)): self.assertIsInstance(modulestore().get_course(course_key), ErrorDescriptor) # Invalidate (e.g., delete) the corresponding CourseOverview, forcing get_course to be called. CourseOverview.objects.filter(id=course_key).delete() courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(courses_list, [])
def test_enrollments_sorted_most_recent(self): """ Test that the list of newly created courses are properly sorted to show the most recent enrollments first. Also test recent enrollment message rendered appropriately for more than two courses. """ self._configure_message_timeout(600) # Create a number of new enrollments and courses, and force their creation behind # the first enrollment courses = [] for idx, seconds_past in zip(range(2, 6), [5, 10, 15, 20]): course_location = locator.CourseLocator( 'Org{num}'.format(num=idx), 'Course{num}'.format(num=idx), 'Run{num}'.format(num=idx) ) course, enrollment = self._create_course_and_enrollment(course_location) enrollment.created = now() - datetime.timedelta(seconds=seconds_past) enrollment.save() courses.append(course) courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(len(courses_list), 6) recent_course_list = _get_recently_enrolled_courses(courses_list) self.assertEqual(len(recent_course_list), 5) self.assertEqual(recent_course_list[1].course.id, courses[0].id) self.assertEqual(recent_course_list[2].course.id, courses[1].id) self.assertEqual(recent_course_list[3].course.id, courses[2].id) self.assertEqual(recent_course_list[4].course.id, courses[3].id) self.client.login(username=self.student.username, password=self.PASSWORD) response = self.client.get(reverse("dashboard")) # verify recent enrollment message self.assertContains( response, 'Thank you for enrolling in:'.format(course_name=self.course.display_name) ) self.assertContains( response, ', '.join(enrollment.course.display_name for enrollment in recent_course_list) )
def test_enrollments_sorted_most_recent(self): """ Test that the list of newly created courses are properly sorted to show the most recent enrollments first. Also test recent enrollment message rendered appropriately for more than two courses. """ self._configure_message_timeout(600) # Create a number of new enrollments and courses, and force their creation behind # the first enrollment courses = [] for idx, seconds_past in zip(list(range(2, 6)), [5, 10, 15, 20]): course_location = locator.CourseLocator( 'Org{num}'.format(num=idx), 'Course{num}'.format(num=idx), 'Run{num}'.format(num=idx) ) course, enrollment = self._create_course_and_enrollment(course_location) enrollment.created = now() - datetime.timedelta(seconds=seconds_past) enrollment.save() courses.append(course) courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(len(courses_list), 6) recent_course_list = _get_recently_enrolled_courses(courses_list) self.assertEqual(len(recent_course_list), 5) self.assertEqual(recent_course_list[1].course.id, courses[0].id) self.assertEqual(recent_course_list[2].course.id, courses[1].id) self.assertEqual(recent_course_list[3].course.id, courses[2].id) self.assertEqual(recent_course_list[4].course.id, courses[3].id) self.client.login(username=self.student.username, password=self.PASSWORD) response = self.client.get(reverse("dashboard")) # verify recent enrollment message self.assertContains( response, 'Thank you for enrolling in:'.format(course_name=self.course.display_name) ) self.assertContains( response, ', '.join(enrollment.course.display_name for enrollment in recent_course_list) )
def test_errored_course_regular_access(self): """ Test the course list for regular staff when get_course returns an ErrorDescriptor """ # pylint: disable=protected-access mongo_store = modulestore()._get_modulestore_by_type( ModuleStoreEnum.Type.mongo) course_key = mongo_store.make_course_key('Org1', 'Course1', 'Run1') self._create_course_with_access_groups( course_key, default_store=ModuleStoreEnum.Type.mongo) with patch('xmodule.modulestore.mongo.base.MongoKeyValueStore', Mock(side_effect=Exception)): self.assertIsInstance(modulestore().get_course(course_key), ErrorDescriptor) # get courses through iterating all courses courses_list = list(get_course_enrollments(self.student, None, [])) self.assertEqual(courses_list, [])
def view_programs(request): """View programs in which the user is engaged.""" if not ProgramsApiConfig.current().is_student_dashboard_enabled: raise Http404 enrollments = list(get_course_enrollments(request.user, None, [])) programs = get_engaged_programs(request.user, enrollments) # TODO: Pull 'xseries' string from configuration model. marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries').strip('/') for program in programs: program['marketing_url'] = '{root}/{slug}'.format( root=marketing_root, slug=program['marketing_slug'] ) return render_to_response('learner_dashboard/programs.html', { 'programs': programs, 'xseries_url': marketing_root if ProgramsApiConfig.current().show_xseries_ad else None })
def get_student_info(self, student): # List of courses user is enrolled to org_filter_out_set = '' course_org_filter = '' course_enrollments = list( get_course_enrollments(student, course_org_filter, org_filter_out_set)) #last login data_email last_login_brut = str(student.last_login) last_login = last_login_brut.split('.') #Check if user is staff / microsite admin / student check_admin_microsite = False try: microsite_key = MicrositeAdminManager.objects.get( user=student).microsite_id user_org = microsite = Microsite.objects.get(pk=microsite_key).key check_admin_microsite = True except: user_org = "Not microsite admin" pass compteur_progress = 0 compteur_finish = 0 compteur_start = 0 compteur_certified = 0 progress_courses = [] finish_courses = [] start_courses = [] certified_courses = [] _now = int(datetime.datetime.now().strftime("%s")) if len(course_enrollments) > 0: #For each course user is enrolled to for dashboard_index, enrollment in enumerate(course_enrollments): course_id = enrollment.course_overview.id user_id = student.id course_tma = get_course_by_id(enrollment.course_id) try: course_grade_factory = CourseGradeFactory().create( student, course_tma) passed = course_grade_factory.passed percent = course_grade_factory.percent except: passed = False percent = 0 course_progression = get_overall_progress(user_id, course_id) try: _end = int(enrollment.course_overview.end.strftime("%s")) except: _end = 0 _progress = True if _end > 0 and _end < _now: _progress = False #storing student results for this class q = {} q['passed'] = passed q['percent'] = float(int(percent * 1000) / 10) q['course_id'] = str(enrollment.course_id) q['duration'] = CourseDetails.fetch( enrollment.course_id).effort q['required'] = course_tma.is_required_atp q['content_data'] = course_tma.content_data q['category'] = course_tma.categ q['display_name_with_default'] = enrollment.course_overview.display_name_with_default q['course_progression'] = course_progression if passed == True: compteur_certified += 1 certified_courses.append(q) if course_progression > 0 and course_progression < 100 and passed == False and _progress == True: compteur_progress += 1 progress_courses.append(q) elif course_progression == 100 or passed or _progress == False: compteur_finish += 1 finish_courses.append(q) elif course_progression == 0 and _progress == True: compteur_start += 1 start_courses.append(q) if student.is_staff: status = "Staff" elif check_admin_microsite: status = "Admin Microsite" else: status = "Student" context = { 'student_id': student.id, 'status': status, 'student_mail': student.email, 'student_name': student.first_name + " " + student.last_name, 'progress_courses': compteur_progress, #'progress_courses': progress_courses, 'finished_courses': compteur_finish, #'finish_courses': finish_courses, 'started_courses': compteur_start, #'start_courses':start_courses, 'certified_courses': compteur_certified, #'certified_course' : certified_courses, 'user org': user_org, 'last login': last_login[0] } return context
def get_student_info(self, email): if User.objects.filter(email=email).exists(): student = User.objects.get(email=email) # List of courses user is enrolled to org_filter_out_set = '' course_org_filter = '' course_enrollments = list( get_course_enrollments(student, course_org_filter, org_filter_out_set)) #last login data_email last_login_brut = str(student.last_login) last_login = last_login_brut.split('.') #Check if microsite admin if MicrositeAdminManager.objects.filter(user=student).exists(): check_admin_microsite = True microsite_key = MicrositeAdminManager.objects.get( user=student).microsite_id microsite_admin_org = Microsite.objects.get( pk=microsite_key).key else: check_admin_microsite = False #Check wich course invited first if CourseEnrollment.objects.filter(user=student).exists(): course_id = CourseEnrollment.objects.filter( user=student).order_by('-created')[0].course_id user_org = str(course_id).split('+')[0].replace( "course-v1:", "") else: user_org = "No organization found for user" #Course counters compteur_progress = 0 compteur_finish = 0 compteur_start = 0 compteur_certified = 0 progress_courses = [] finish_courses = [] start_courses = [] certified_courses = [] _now = int(datetime.datetime.now().strftime("%s")) if len(course_enrollments) > 0: #For each course user is enrolled to for dashboard_index, enrollment in enumerate( course_enrollments): course_id = enrollment.course_overview.id user_id = student.id course_tma = get_course_by_id(enrollment.course_id) try: course_grade_factory = CourseGradeFactory().create( student, course_tma) passed = course_grade_factory.passed percent = course_grade_factory.percent except: passed = False percent = 0 course_progression = get_overall_progress( user_id, course_id) try: _end = int( enrollment.course_overview.end.strftime("%s")) except: _end = 0 _progress = True if _end > 0 and _end < _now: _progress = False #storing student results for this class q = {} q['passed'] = passed q['percent'] = float(int(percent * 1000) / 10) q['course_id'] = str(enrollment.course_id) q['duration'] = CourseDetails.fetch( enrollment.course_id).effort q['required'] = course_tma.is_required_atp q['content_data'] = course_tma.content_data q['category'] = course_tma.categ q['display_name_with_default'] = enrollment.course_overview.display_name_with_default q['course_progression'] = course_progression if passed == True: compteur_certified += 1 certified_courses.append(q) if course_progression > 0 and course_progression < 100 and passed == False and _progress == True: compteur_progress += 1 progress_courses.append(q) elif course_progression == 100 or passed or _progress == False: compteur_finish += 1 finish_courses.append(q) elif course_progression == 0 and _progress == True: compteur_start += 1 start_courses.append(q) #Candidate status if student.is_staff: status = "Staff" elif check_admin_microsite: status = "Admin Microsite" else: status = "Student" context = { 'student_id': student.id, 'status': status, 'student_mail': student.email, 'student_name': student.first_name + " " + student.last_name, 'progress_courses': compteur_progress, #'progress_courses': progress_courses, 'finished_courses': compteur_finish, #'finish_courses': finish_courses, 'started_courses': compteur_start, #'start_courses':start_courses, 'certified_courses': compteur_certified, #'certified_course' : certified_courses, 'user_org': user_org, 'last login': last_login[0] } if check_admin_microsite: context['microsite_admin_org'] = microsite_admin_org else: if UserPreprofile.objects.filter(email=email).exists(): user = UserPreprofile.objects.get(email=email) if CourseEnrollmentAllowed.objects.filter( email=email).exists(): profile = CourseEnrollmentAllowed.objects.filter( email=email).order_by('-created') course_id = profile[0].course_id user_org = str(course_id).split('+')[0].replace( "course-v1:", "") else: user_org = "No organization found for user" context = { 'student_mail': email, 'student_name': user.first_name + " " + user.last_name, 'status': "User preregistered on platform", 'user_org': user_org } else: context = { 'student_mail': email, 'status': "Unknown user", } return context