def test_can_generate_not_whitelisted(self): """ Test handling when user is not whitelisted """ u = UserFactory() cr = CourseFactory() key = cr.id # pylint: disable=no-member CourseEnrollmentFactory( user=u, course_id=key, is_active=True, mode="verified", ) assert not can_generate_allowlist_certificate(u, key)
def setUp(self): super().setUp() self.global_staff = GlobalStaffFactory() self.user = UserFactory() self.course_run = CourseFactory() self.course_run_key = self.course_run.id # pylint: disable=no-member CourseEnrollmentFactory( user=self.user, course_id=self.course_run_key, is_active=True, mode="verified", )
def setUpClass(cls): super(CourseTeamTest, cls).setUpClass() cls.course_id = "edx/the-course/1" cls.course1 = create_course(CourseKey.from_string(cls.course_id), TEAMS_CONFIG_1) cls.audit_learner = UserFactory.create(username="******") CourseEnrollmentFactory.create(user=cls.audit_learner, course_id="edx/the-course/1", mode=CourseMode.AUDIT) cls.audit_team = CourseTeamFactory( course_id="edx/the-course/1", team_id="audit-team", topic_id=TEAMSET_1_ID, name="The Team" ) cls.masters_learner = UserFactory.create(username="******") CourseEnrollmentFactory.create(user=cls.masters_learner, course_id="edx/the-course/1", mode=CourseMode.MASTERS) cls.masters_team = CourseTeamFactory( course_id="edx/the-course/1", team_id="masters-team", topic_id=TEAMSET_1_ID, name="The Team", organization_protected=True )
def test_upgrade_deadline_instructor_paced(self): course = CourseFactory(self_paced=False) course_upgrade_deadline = datetime.datetime.now( pytz.UTC) + datetime.timedelta(days=1) CourseModeFactory( course_id=course.id, mode_slug=CourseMode.VERIFIED, # This must be in the future to ensure it is returned by downstream code. expiration_datetime=course_upgrade_deadline) enrollment = CourseEnrollmentFactory(course_id=course.id, mode=CourseMode.AUDIT) DynamicUpgradeDeadlineConfiguration.objects.create(enabled=True) assert enrollment.schedule is not None assert enrollment.upgrade_deadline == course_upgrade_deadline
def test_get_course_info_for_application_review(courses, user_with_profile): """ Tests that `get_course_info_for_application_review` returns expected data for application review. """ course1 = courses['test_course1'] course2 = courses['test_course2'] course3 = CourseOverviewFactory() CourseEnrollmentFactory(user=user_with_profile, course=course2) PersistentCourseGradeFactory( user_id=user_with_profile.id, course_id=course2.id, percent_grade=1.0, letter_grade='A' ) CourseEnrollmentFactory(user=user_with_profile, course=course3) actual_courses_info = get_course_info_for_application_review([course1, course2, course3], user_with_profile) expected_courses_info = { course1.display_name: NOT_STARTED, course2.display_name: '100%', course3.display_name: IN_PROGRESS, } assert actual_courses_info == expected_courses_info
def setUp(self): super(TestCourseSockView, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments self.user = UserFactory.create() # Enroll the user in the four courses CourseEnrollmentFactory.create(user=self.user, course_id=self.standard_course.id) CourseEnrollmentFactory.create(user=self.user, course_id=self.verified_course.id) CourseEnrollmentFactory.create(user=self.user, course_id=self.verified_course_update_expired.id) CourseEnrollmentFactory.create( user=self.user, course_id=self.verified_course_already_enrolled.id, mode=CourseMode.VERIFIED ) CommerceConfiguration.objects.create(enabled=True, checkout_on_ecommerce_service=True) # Log the user in self.client.login(username=self.user.username, password=TEST_PASSWORD)
def test_remove_from_team(self): # Given a user already in a course and on a team user = UserFactory.create(username='******') mode = 'audit' CourseEnrollmentFactory.create(user=user, course_id=self.course.id, mode=mode) team = CourseTeamFactory(course_id=self.course.id, name='team_1', topic_id='teamset_1') team.add_user(user) assert CourseTeamMembership.is_user_on_team(user, team) # When I try to remove them from the team csv_data = self._csv_reader_from_array([ ['user', 'mode', 'teamset_1'], [user.username, mode, ''], ]) result = self.import_manager.set_team_memberships(csv_data) # lint-amnesty, pylint: disable=unused-variable # Then they are removed from the team and the correct events are issued assert not CourseTeamMembership.is_user_on_team(user, team) self.assert_learner_removed_emitted(team.team_id, user.id)
def setUp(self): # pylint: disable=arguments-differ super().setUp('lms.djangoapps.certificates.utils.tracker') # Create user, a course run, and an enrollment self.u = UserFactory() self.cr = CourseFactory() self.key = self.cr.id # pylint: disable=no-member CourseEnrollmentFactory( user=self.u, course_id=self.key, is_active=True, mode='verified', ) self.gen_mode = 'batch'
def test_updated_when_new_start_in_past(self): course = _create_course_run( self_paced=True, start_day_offset=5) # course starts in future enrollment = CourseEnrollmentFactory(course_id=course.id, mode=CourseMode.AUDIT) previous_start = enrollment.course.start self.assert_schedule_dates(enrollment.schedule, previous_start) course.start = course.start + datetime.timedelta( days=-10) # new course start changes to a past date self.store.update_item(course, ModuleStoreEnum.UserID.test) enrollment = CourseEnrollment.objects.get(id=enrollment.id) self.assert_schedule_dates( enrollment.schedule, course.start) # start set to new course start
def test_chunked_queries_send_numerous_emails(self, email_mock): """ Test sending a large number of emails, to test the chunked querying """ mock_factory = MockCourseEmailResult() email_mock.side_effect = mock_factory.get_mock_update_subtask_status() added_users = [] for _ in range(LARGE_NUM_EMAILS): user = UserFactory() added_users.append(user) CourseEnrollmentFactory.create(user=user, course_id=self.course.id) optouts = [] for i in [1, 3, 9, 10, 18]: # 5 random optouts user = added_users[i] optouts.append(user) optout = Optout(user=user, course_id=self.course.id) optout.save() test_email = { 'action': 'Send email', 'send_to': '["myself", "staff", "learners"]', 'subject': 'test subject for all', 'message': 'test message for all' } response = self.client.post(self.send_mail_url, test_email) assert json.loads( response.content.decode('utf-8')) == self.success_content assert mock_factory.emails_sent == \ ((((1 + len(self.staff)) + len(self.students)) + LARGE_NUM_EMAILS) - len(optouts)) outbox_contents = [e.to[0] for e in mail.outbox] should_send_contents = ( [self.instructor.email] + [s.email for s in self.staff] + [s.email for s in self.students] + [s.email for s in added_users if s not in optouts]) six.assertCountEqual(self, outbox_contents, should_send_contents)
def test_with_two_verifications(self): # checking if a user has two verification and but most recent verification course deadline is expired self._setup_mode_and_enrollment(self.DATES[self.FUTURE], "verified") # The student has an approved verification attempt = SoftwareSecurePhotoVerification.objects.create( user=self.user) attempt.mark_ready() attempt.submit() attempt.approve() # Making created at to previous date to differentiate with 2nd attempt. attempt.created_at = datetime.now(UTC) - timedelta(days=1) attempt.save() # Expect that the successfully verified message is shown self._assert_course_verification_status(VERIFY_STATUS_APPROVED) # Check that the "verification good until" date is displayed response = self.client.get(self.dashboard_url) self.assertContains(response, attempt.expiration_datetime.strftime("%m/%d/%Y")) # Adding another verification with different course. # Its created_at is greater than course deadline. course2 = CourseFactory.create() CourseModeFactory.create(course_id=course2.id, mode_slug="verified", expiration_datetime=self.DATES[self.PAST]) CourseEnrollmentFactory(course_id=course2.id, user=self.user, mode="verified") # The student has an approved verification attempt2 = SoftwareSecurePhotoVerification.objects.create( user=self.user) attempt2.mark_ready() attempt2.submit() attempt2.approve() attempt2.save() # Mark the attemp2 as approved so its date will appear on dasboard. self._assert_course_verification_status(VERIFY_STATUS_APPROVED) response2 = self.client.get(self.dashboard_url) self.assertContains(response2, attempt2.expiration_datetime.strftime("%m/%d/%Y")) self.assertContains(response2, attempt2.expiration_datetime.strftime("%m/%d/%Y"), count=2)
def test_can_generate_audit(self): """ Test handling when user is enrolled in audit mode """ u = UserFactory() cr = CourseFactory() key = cr.id # pylint: disable=no-member CourseEnrollmentFactory( user=u, course_id=key, is_active=True, mode="audit", ) assert not _can_generate_v2_certificate(u, key)
def test_cert_status_none(self): """ Test cert status when the user has no cert """ u = UserFactory() cr = CourseFactory() key = cr.id # pylint: disable=no-member CourseEnrollmentFactory( user=u, course_id=key, is_active=True, mode="verified", ) assert _set_v2_cert_status(u, key) == CertificateStatuses.notpassing
def setUp(self): super().setUp() self.user = UserFactory.create() self.verified_course = CourseFactory.create(self_paced=True, ) self.verified_course_key = self.verified_course.id # pylint: disable=no-member self.verified_enrollment = CourseEnrollmentFactory( user=self.user, course_id=self.verified_course_key, is_active=True, mode='verified', ) CertificateAllowlistFactory(user=self.user, course_id=self.verified_course_key) self.audit_course = CourseFactory.create(self_paced=False) self.audit_course_key = self.audit_course.id # pylint: disable=no-member self.audit_enrollment = CourseEnrollmentFactory( user=self.user, course_id=self.audit_course_key, is_active=True, mode='audit', ) CertificateAllowlistFactory(user=self.user, course_id=self.audit_course_key)
def test_view_course_appears_on_dashboard(self): """ When a course doesn't have completion data, its course card should display a "View Course" button. """ self.override_waffle_switch(True) course = CourseFactory.create() CourseEnrollmentFactory.create( user=self.user, course_id=course.id ) response = self.client.get(reverse('dashboard')) course_key_string = str(course.id) # No completion data means there's no block from which to resume. resume_block_key_string = '' course_run_string = self._pull_course_run_from_course_key(course_key_string) view_button_html = self._get_html_for_view_course_button( course_key_string, course_run_string ) resume_button_html = self._get_html_for_resume_course_button( course_key_string, resume_block_key_string, course_run_string ) view_button_html = self._remove_whitespace_from_html_string(view_button_html) resume_button_html = self._remove_whitespace_from_html_string(resume_button_html) dashboard_html = self._remove_whitespace_from_response(response) assert view_button_html in dashboard_html assert resume_button_html not in dashboard_html
def make_valid_goal(self, **kwargs): """Creates a goal that will cause an email to be sent as the goal is valid but has been missed""" kwargs.setdefault('days_per_week', 6) kwargs.setdefault('subscribed_to_reminders', True) kwargs.setdefault('overview__start', datetime(2021, 1, 1, tzinfo=UTC)) kwargs.setdefault('overview__end', datetime(2021, 4, 1, tzinfo=UTC)) # Have it end in the future goal = CourseGoalFactory(**kwargs) with freeze_time( '2021-02-01 10:00:00'): # Create enrollment before March CourseEnrollmentFactory(user=goal.user, course_id=goal.course_key) return goal
def test_enroll_mb_create_external_id(self): course_run_key = self.program['courses'][0]['course_runs'][0]['key'] # Enroll user enrollment = CourseEnrollmentFactory.create( course_id=course_run_key, user=self.user, mode=CourseMode.VERIFIED, ) enrollment.save() external_id = ExternalId.objects.get( user=self.user ) assert external_id is not None assert external_id.external_id_type.name == ExternalIdType.MICROBACHELORS_COACHING
def setUp(self): super(PassingGradeCertsTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments self.course = CourseFactory.create( self_paced=True, ) self.user = UserFactory.create() self.enrollment = CourseEnrollmentFactory( user=self.user, course_id=self.course.id, is_active=True, mode="verified", ) self.ip_course = CourseFactory.create(self_paced=False) self.ip_enrollment = CourseEnrollmentFactory( user=self.user, course_id=self.ip_course.id, is_active=True, mode="verified", ) attempt = SoftwareSecurePhotoVerification.objects.create( user=self.user, status='submitted' ) attempt.approve()
def test_is_on_allowlist_false(self): """ Test the absence of the user on the allowlist """ u = UserFactory() CourseEnrollmentFactory( user=u, course_id=self.course_run_key, is_active=True, mode=GeneratedCertificate.MODES.verified, ) CertificateAllowlistFactory.create(course_id=self.course_run_key, user=u, allowlist=False) assert not is_on_certificate_allowlist(u, self.course_run_key)
def test_handle_audit_status(self): """ Test handling of a user who is not passing and is enrolled in audit mode """ different_user = UserFactory() CourseEnrollmentFactory( user=different_user, course_id=self.course_run_key, is_active=True, mode=GeneratedCertificate.MODES.audit, ) assert _set_v2_cert_status(different_user, self.course_run_key) is None assert not generate_regular_certificate_task(different_user, self.course_run_key)
def test_can_generate_not_allowlisted(self): """ Test handling when user is not on the certificate allowlist. """ u = UserFactory() cr = CourseFactory() key = cr.id # pylint: disable=no-member CourseEnrollmentFactory( user=u, course_id=key, is_active=True, mode=GeneratedCertificate.MODES.verified, ) assert not _can_generate_allowlist_certificate(u, key) assert _set_allowlist_cert_status(u, key) is None
def setup_partitions_and_course(self, active=True): """ Setup course structure and create user for user partition transformer test. Args: active: boolean representing if the user partitions are active or not """ # Set up user partitions and groups. self.setup_groups_partitions(active=active) self.user_partition = self.user_partitions[0] # Build course. self.course_hierarchy = self.get_course_hierarchy() self.blocks = self.build_course(self.course_hierarchy) self.course = self.blocks['course'] # Enroll user in course. CourseEnrollmentFactory.create( user=self.user, course_id=self.course.id, is_active=True ) # Set up cohorts. self.setup_cohorts(self.course)
def setUp(self): super(TestGradebook, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments instructor = AdminFactory.create() self.client.login(username=instructor.username, password='******') self.users = [UserFactory.create() for _ in range(USER_COUNT)] for user in self.users: CourseEnrollmentFactory.create(user=user, course_id=self.course.id) for i, item in enumerate(self.items): for j, user in enumerate(self.users): StudentModuleFactory.create(grade=1 if i < j else 0, max_grade=1, student=user, course_id=self.course.id, module_state_key=item.location) task_compute_all_grades_for_course.apply_async( kwargs={'course_key': text_type(self.course.id)}) self.response = self.client.get( reverse('spoc_gradebook', args=(text_type(self.course.id), ))) self.assertEqual(self.response.status_code, 200)
def setUp(self): super().setUp() # Configure course as a credit course CreditCourse.objects.create(course_key=self.course.id, enabled=True) # Configure credit requirements (passing grade and in-course reverification) credit_api.set_credit_requirements( self.course.id, [{ "namespace": "grade", "name": "grade", "display_name": self.MIN_GRADE_REQ_DISPLAY, "criteria": { "min_grade": 0.8 } }, { "namespace": "reverification", "name": "midterm", "display_name": self.VERIFICATION_REQ_DISPLAY, "criteria": {} }]) # Create a user and log in self.user = UserFactory.create(username=self.USERNAME, password=self.PASSWORD) self.user.profile.name = self.USER_FULL_NAME self.user.profile.save() result = self.client.login(username=self.USERNAME, password=self.PASSWORD) assert result, 'Could not log in' # Enroll the user in the course as "verified" self.enrollment = CourseEnrollmentFactory(user=self.user, course_id=self.course.id, mode="verified")
def test_grade_not_appears_before_cert_available_date(self): """ Verify that learners are able to see their final grade of the course in the learner dashboard after the course had ended """ self.course_key = CourseKey.from_string('course-v1:edX+DemoX+Demo_Course') self.course = CourseOverviewFactory.create(id=self.course_key, end_date=self.THREE_YEARS_AGO, certificate_available_date=self.TOMORROW, lowest_passing_grade=0.3) self.course_enrollment = CourseEnrollmentFactory(course_id=self.course.id, user=self.user) GeneratedCertificateFactory(status='notpassing', course_id=self.course.id, user=self.user, grade=0.45) response = self.client.get(reverse('dashboard')) self.assertNotContains(response, 'Your final grade:') self.assertNotContains(response, '<span class="grade-value">45%</span>')
def test_create_new_team_from_import(self): # Given a user in a course user = UserFactory.create(username='******') mode = 'audit' CourseEnrollmentFactory.create(user=user, course_id=self.course.id, mode=mode) # When I add them to a team that does not exist assert CourseTeam.objects.all().count() == 0 csv_data = self._csv_reader_from_array([ ['username', 'mode', 'teamset_1'], [user.username, mode, 'new_exciting_team'], ]) result = self.import_manager.set_team_memberships(csv_data) # lint-amnesty, pylint: disable=unused-variable # Then a new team is created assert CourseTeam.objects.all().count() == 1 # ... and the user is assigned to the team new_team = CourseTeam.objects.get(topic_id='teamset_1', name='new_exciting_team') assert CourseTeamMembership.is_user_on_team(user, new_team) self.assert_learner_added_emitted(new_team.team_id, user.id)
def _setup_mode_and_enrollment(self, deadline, enrollment_mode): """Create a course mode and enrollment. Arguments: deadline (datetime): The deadline for submitting your verification. enrollment_mode (str): The mode of the enrollment. """ CourseModeFactory.create(course_id=self.course.id, mode_slug="verified", expiration_datetime=deadline) CourseEnrollmentFactory(course_id=self.course.id, user=self.user, mode=enrollment_mode) VerificationDeadline.set_deadline(self.course.id, deadline)
def test_can_receive_discount_entitlement(self, entitlement_mode): """ Ensure that only users who have not already purchased courses receive the discount. """ CourseEnrollmentFactory(is_active=True, course_id=self.course.id, user=self.user) if entitlement_mode is not None: CourseEntitlementFactory.create(mode=entitlement_mode, user=self.user) applicability = can_receive_discount(user=self.user, course=self.course) assert applicability == (entitlement_mode is None)
def create_resolver(self): """ Creates a CourseUpdateResolver with an enrollment to schedule. """ enrollment = CourseEnrollmentFactory(course_id=self.course.id, user=self.user, mode='audit') return CourseUpdateResolver( async_send_task=Mock(name='async_send_task'), site=self.site_config.site, target_datetime=enrollment.schedule.start_date, day_offset=-7, bin_num=CourseUpdateResolver.bin_num_for_user_id(self.user.id), )
def test_send_to_track_other_enrollments(self): """ Failing test for EDUCATOR-217: verifies that emails are only sent to users in a specific track if they're in that track in the course the email is being sent from. """ # Create a mode and designate an enrolled user to be placed in that mode CourseMode.objects.create(mode_slug='test_mode', course_id=self.course.id) test_mode_student = self.students[0] update_enrollment(test_mode_student, str(self.course.id), 'test_mode') # Take another user already enrolled in the course, then enroll them in # another course but in that same test mode test_mode_student_other_course = self.students[1] other_course = CourseFactory.create() CourseMode.objects.create(mode_slug='test_mode', course_id=other_course.id) CourseEnrollmentFactory.create( user=test_mode_student_other_course, course_id=other_course.id ) update_enrollment(test_mode_student_other_course, str(other_course.id), 'test_mode') # Send the emails... test_email = { 'action': 'Send email', 'send_to': '["track:test_mode"]', 'subject': 'test subject for test_mode track', 'message': 'test message for test_mode track', } response = self.client.post(self.send_mail_url, test_email) assert json.loads(response.content.decode('utf-8')) == self.success_content # Only the the student in the test mode in the course the email was # sent from should receive an email assert len(mail.outbox) == 1 assert mail.outbox[0].to[0] == test_mode_student.email