def setUp(self): super().setUp() self.course_key = ToyCourseFactory.create().id self.course_usage_key = self.store.make_course_usage_key( self.course_key) self.block_structure = BlockStructureFactory.create_from_modulestore( self.course_usage_key, self.store) self.course = course = modulestore().get_course(self.course_key) section = course.get_children()[0] subsection = section.get_children()[0] self.block = self.store.create_child(self.learner.id, subsection.location, 'html', 'new_component') CourseEnrollmentFactory.create(user=self.learner, course_id=self.course_key, is_active=True) self.block = self.store.create_child(self.learner2.id, subsection.location, 'html', 'new_component') CourseEnrollmentFactory.create(user=self.learner2, course_id=self.course_key, is_active=True)
def test_single_denied(self): ''' Single graded problem should show error ''' course = self._create_course() blocks_dict = course['blocks'] CourseEnrollmentFactory.create( user=self.user, course_id=course['course'].id, mode='audit' ) blocks_dict['graded_1'] = ItemFactory.create( parent=blocks_dict['vertical'], category='problem', graded=True, metadata=METADATA, ) _assert_block_is_gated( block=blocks_dict['graded_1'], user=self.user, course=course['course'], is_gated=True, request_factory=self.request_factory, )
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(SupportViewEnrollmentsTests, self).setUp() SupportStaffRole().add_users(self.user) self.course = CourseFactory(display_name=u'teꜱᴛ') self.student = UserFactory.create(username='******', email='*****@*****.**', password='******') for mode in ( CourseMode.AUDIT, CourseMode.PROFESSIONAL, CourseMode.CREDIT_MODE, CourseMode.NO_ID_PROFESSIONAL_MODE, CourseMode.VERIFIED, CourseMode.HONOR ): CourseModeFactory.create(mode_slug=mode, course_id=self.course.id) self.verification_deadline = VerificationDeadline( course_key=self.course.id, deadline=datetime.now(UTC) + timedelta(days=365) ) self.verification_deadline.save() CourseEnrollmentFactory.create(mode=CourseMode.AUDIT, user=self.student, course_id=self.course.id) self.url = reverse('support:enrollment_list', kwargs={'username_or_email': self.student.username})
def setUp(self): super().setUp() # create the course self.course = CourseFactory.create() # an ordered list of block locations, where the index # corresponds to the block's index in the parents_map. self.xblock_keys = [self.course.location] # create all other blocks in the course for i, parents_index in enumerate(self.parents_map): if i == 0: continue # course already created self.xblock_keys.append( ItemFactory.create( parent=self.get_block(parents_index[0]), category="vertical", ).location ) # add additional parents if len(parents_index) > 1: for index in range(1, len(parents_index)): parent_index = parents_index[index] parent_block = self.get_block(parent_index) parent_block.children.append(self.xblock_keys[i]) update_block(parent_block) self.password = '******' self.student = UserFactory.create(is_staff=False, username='******', password=self.password) self.staff = UserFactory.create(is_staff=True, username='******', password=self.password) CourseEnrollmentFactory.create( is_active=True, mode=CourseMode.DEFAULT_MODE_SLUG, user=self.student, course_id=self.course.id )
def test_exceed_max_size(self): # Given a bunch of students enrolled in a course users = [] for i in range(5): user = UserFactory.create(username=f'max_size_{i}') CourseEnrollmentFactory.create(user=user, course_id=self.course.id, mode='audit') users.append(user) # When a team is already near capaciy team = CourseTeam.objects.create( name='team_1', course_id=self.course.id, topic_id='teamset_1', description='Team 1!', ) for i in range(2): user = users[i] team.add_user(user) # ... and I try to add members in excess of capacity csv_data = self._csv_reader_from_array([ ['user', 'mode', 'teamset_1'], ['max_size_0', 'audit', ''], ['max_size_2', 'audit', 'team_1'], ['max_size_3', 'audit', 'team_1'], ['max_size_4', 'audit', 'team_1'], ]) result = self.import_manager.set_team_memberships(csv_data) # Then the import fails with no events emitted and a "team is full" error assert not result self.assert_no_events_were_emitted() assert self.import_manager.validation_errors[0] == 'New membership for team team_1 would exceed max size of 3.' # Confirm that memberships were not altered for i in range(2): assert CourseTeamMembership.is_user_on_team(user, team)
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
def test_data_err_fail(self, retry, result, get_conn): """ Test that celery handles permanent SMTPDataErrors by failing and not retrying. """ # have every fourth email fail due to blacklisting: get_conn.return_value.send_messages.side_effect = cycle([ SMTPDataError(554, "Email address is blacklisted"), None, None, None ]) # Don't forget to account for the "myself" instructor user students = [ UserFactory() for _ in range(settings.BULK_EMAIL_EMAILS_PER_TASK - 1) ] for student in students: CourseEnrollmentFactory.create(user=student, course_id=self.course.id) 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 # We shouldn't retry when hitting a 5xx error assert not retry.called # Test that after the rejected email, the rest still successfully send ((_entry_id, _current_task_id, subtask_status), _kwargs) = result.call_args assert subtask_status.skipped == 0 expected_fails = int((settings.BULK_EMAIL_EMAILS_PER_TASK + 3) / 4.0) assert subtask_status.failed == expected_fails assert subtask_status.succeeded == ( settings.BULK_EMAIL_EMAILS_PER_TASK - expected_fails)
def test_generate_enrollment_status_hash(self): """ Verify the method returns a hash of a user's current enrollments. """ # Return None for anonymous users self.assertIsNone(CourseEnrollment.generate_enrollment_status_hash(AnonymousUser())) # No enrollments expected = hashlib.md5(self.user.username.encode('utf-8')).hexdigest() self.assertEqual(CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected) # No active enrollments enrollment_mode = 'verified' course_id = self.course.id # pylint: disable=no-member enrollment = CourseEnrollmentFactory.create(user=self.user, course_id=course_id, mode=enrollment_mode, is_active=False) self.assertEqual(CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected) # One active enrollment enrollment.is_active = True enrollment.save() expected = '{username}&{course_id}={mode}'.format( username=self.user.username, course_id=str(course_id).lower(), mode=enrollment_mode.lower() ) expected = hashlib.md5(expected.encode('utf-8')).hexdigest() self.assertEqual(CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected) # Multiple enrollments CourseEnrollmentFactory.create(user=self.user) enrollments = CourseEnrollment.enrollments_for_user(self.user).order_by(Lower('course_id')) hash_elements = [self.user.username] hash_elements += [ '{course_id}={mode}'.format(course_id=str(enrollment.course_id).lower(), mode=enrollment.mode.lower()) for enrollment in enrollments] expected = hashlib.md5('&'.join(hash_elements).encode('utf-8')).hexdigest() self.assertEqual(CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected)
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) self.assertEqual(json.loads(response.content.decode('utf-8')), self.success_content) self.assertEqual( 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 setUpClass(cls): super().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 _create_completed_program_course_enrollment(self): """ helper function create program course enrollment """ course_enrollment = CourseEnrollmentFactory.create( course_id=self.course_key, user=self.user, mode=CourseMode.MASTERS ) program_course_enrollment = ProgramCourseEnrollmentFactory( program_enrollment=self.program_enrollment, course_key=self.course_key, course_enrollment=course_enrollment, status="active" ) return program_course_enrollment
def test_unicode_students_send_to_all(self): """ Make sure email (with Unicode characters) send to all goes there. """ # Create a student with Unicode in their first & last names unicode_user = UserFactory(first_name='Ⓡⓞⓑⓞⓣ', last_name='ՇﻉรՇ') CourseEnrollmentFactory.create(user=unicode_user, course_id=self.course.id) self.students.append(unicode_user) 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 len(mail.outbox) == ((1 + len(self.staff)) + len(self.students)) assert len([e.to[0] for e in mail.outbox]) ==\ len([self.instructor.email] + [s.email for s in self.staff] + [s.email for s in self.students])
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([ ['username', '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): super().setUp() self.course = CourseFactory.create(number=self.COURSE_NUMBER, user_partitions=[self.partition]) self.chapter = ItemFactory.create( parent_location=self.course.location, category="chapter", display_name="test chapter", ) self.sequential = ItemFactory.create( parent_location=self.chapter.location, category="sequential", display_name="Split Test Tests", ) self.student = UserFactory.create() CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id) self.client.login(username=self.student.username, password='******') self.included_usage_keys = None self.excluded_usage_keys = None
def setUp(self): super(TestOptoutCourseEmails, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments course_title = u"ẗëṡẗ title イ乇丂イ ᄊ乇丂丂ムg乇 キo尺 ムレレ тэѕт мэѕѕаБэ" self.course = CourseFactory.create(run='testcourse1', display_name=course_title) self.instructor = AdminFactory.create() self.student = UserFactory.create() CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id) # load initial content (since we don't run migrations as part of tests): call_command("loaddata", "course_email_template.json") self.client.login(username=self.student.username, password="******") self.send_mail_url = reverse( 'send_email', kwargs={'course_id': text_type(self.course.id)}) self.success_content = { 'course_id': text_type(self.course.id), 'success': True, } BulkEmailFlag.objects.create(enabled=True, require_course_email_auth=False)
def setUp(self): super().setUp() 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 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_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 test_user_moved_to_another_team(self): """ We should be able to move a user from one team to another """ # Create a learner, enroll in course audit_learner = UserFactory.create(username='******') CourseEnrollmentFactory.create(user=audit_learner, course_id=self.course.id, mode='audit') # Make two teams in the same teamset, enroll the user in one team_1 = CourseTeamFactory(course_id=self.course.id, name='test_team_1', topic_id='teamset_1') team_2 = CourseTeamFactory(course_id=self.course.id, name='test_team_2', topic_id='teamset_1') team_1.add_user(audit_learner) csv_row = _csv_dict_row(audit_learner, 'audit', teamset_1=team_2.name) csv_import(self.course, [csv_row]) assert not CourseTeamMembership.is_user_on_team(audit_learner, team_1) assert CourseTeamMembership.is_user_on_team(audit_learner, team_2) self.assert_learner_removed_emitted(team_1.team_id, audit_learner.id) self.assert_learner_added_emitted(team_2.team_id, audit_learner.id)
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 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 add_user_to_course_program_team( cls, user, add_to_team=True, enroll_in_program=True, connect_enrollments=True, external_user_key=None ): """ Set up a test user by enrolling them in self.course, and then optionaly: - enroll them in a program - link their program and course enrollments - give their program enrollment an external_user_key """ course_enrollment = CourseEnrollmentFactory.create(user=user, course_id=cls.course.id) if add_to_team: cls.team.add_user(user) if enroll_in_program: program_enrollment = ProgramEnrollmentFactory.create(user=user, external_user_key=external_user_key) if connect_enrollments: ProgramCourseEnrollmentFactory.create( program_enrollment=program_enrollment, course_enrollment=course_enrollment )
def create_enrollment(self, expired): """ Create an enrollment """ if expired: course = CourseFactory.create(start=self.THREE_YEARS_AGO, mobile_available=True) enrollment = CourseEnrollmentFactory.create( user=self.user, course_id=course.id ) enrollment.created = self.THREE_YEARS_AGO + datetime.timedelta(days=1) enrollment.save() else: course = CourseFactory.create(start=self.LAST_WEEK, mobile_available=True) self.enroll(course.id) add_course_mode(course, mode_slug=CourseMode.AUDIT) add_course_mode(course)
def test_revoke_unenroll_entitlement(self, mock_course_uuid): enrollment = CourseEnrollmentFactory.create( user=self.user, course_id=self.course.id, # pylint: disable=no-member is_active=True ) course_entitlement = CourseEntitlementFactory.create(user=self.user, enrollment_course_run=enrollment) mock_course_uuid.return_value = course_entitlement.course_uuid url = reverse(self.ENTITLEMENTS_DETAILS_PATH, args=[str(course_entitlement.uuid)]) assert course_entitlement.enrollment_course_run is not None response = self.client.delete( url, content_type='application/json', ) assert response.status_code == 204 course_entitlement.refresh_from_db() assert course_entitlement.expired_at is not None assert course_entitlement.enrollment_course_run is None
def create_program_course_enrollment(self, program_enrollment, course_status=CourseStatuses.ACTIVE): """ Creates and returns a ProgramCourseEnrollment for the given program_enrollment and self.course_key, creating a CourseEnrollment if the program enrollment has a user """ course_enrollment = None if program_enrollment.user: course_enrollment = CourseEnrollmentFactory.create( course_id=self.course_id, user=program_enrollment.user, mode=CourseMode.MASTERS) course_enrollment.is_active = course_status == CourseStatuses.ACTIVE course_enrollment.save() return ProgramCourseEnrollmentFactory.create( program_enrollment=program_enrollment, course_key=self.course_id, course_enrollment=course_enrollment, status=course_status, )
def setUp(self): super().setUp() # enroll all users into the all track types course self.users = {} for mode_type in self.MODE_TYPES: self.users[mode_type] = UserFactory.create(username=mode_type) CourseEnrollmentFactory.create( user=self.users[mode_type], course_id=self.courses['all_track_types']['course'].id, mode=mode_type ) # create audit_user for ease of reference self.audit_user = self.users['audit'] # enroll audit and verified users into default course for mode_type in ['audit', 'verified']: CourseEnrollmentFactory.create( user=self.users[mode_type], course_id=self.course.id, mode=mode_type ) # enroll audit user into the audit_only course CourseEnrollmentFactory.create( user=self.audit_user, course_id=self.courses['audit_only']['course'].id, mode='audit' ) # enroll audit user into the upgrade expired course CourseEnrollmentFactory.create( user=self.audit_user, course_id=self.courses['expired_upgrade_deadline']['course'].id, mode='audit' ) ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1))
def test_enabled_for_enrollment( self, already_enrolled, enrolled_before_enabled, ): # Tweak the datetime to enable the config so that it is either before # or after now (which is when the enrollment will be created) if enrolled_before_enabled: enabled_as_of = datetime.now() + timedelta(days=1) else: enabled_as_of = datetime.now() - timedelta(days=1) config = ContentTypeGatingConfig.objects.create( enabled=True, course=self.course_overview, enabled_as_of=enabled_as_of, ) if already_enrolled: existing_enrollment = CourseEnrollmentFactory.create( user=self.user, course=self.course_overview, ) else: existing_enrollment = None enrollment = None user = self.user course_key = self.course_overview.id query_count = 7 with self.assertNumQueries(query_count): enabled = ContentTypeGatingConfig.enabled_for_enrollment( user=user, course_key=course_key, ) assert (not enrolled_before_enabled) == enabled
def setUp(self): super().setUp() self.course = CourseFactory.create(run='testcourse1', display_name="Test Course Title") self.instructor = AdminFactory.create() self.student = UserFactory.create() self.enrollment = CourseEnrollmentFactory.create( user=self.student, course_id=self.course.id) # load initial content (since we don't run migrations as part of tests): call_command("loaddata", "course_email_template.json") self.client.login(username=self.student.username, password="******") self.send_mail_url = reverse('send_email', kwargs={'course_id': str(self.course.id)}) self.success_content = { 'course_id': str(self.course.id), 'success': True, } BulkEmailFlag.objects.create(enabled=True, require_course_email_auth=False)
def _construct_enrollments(self, program_uuids, course_ids, external_user_key, edx_user=None): """ A helper function to setup the program enrollments for a given learner. If the edx user is provided, it will try to SSO the user with the enrollments Return the expected info object that should be created based on the model setup """ program_enrollments = [] for program_uuid in program_uuids: course_enrollment = None program_enrollment = ProgramEnrollmentFactory.create( external_user_key=external_user_key, program_uuid=program_uuid, user=edx_user) for course_id in course_ids: if edx_user: course_enrollment = CourseEnrollmentFactory.create( course_id=course_id, user=edx_user, mode=CourseMode.MASTERS, is_active=True) program_course_enrollment = ProgramCourseEnrollmentFactory.create( # lint-amnesty, pylint: disable=unused-variable program_enrollment=program_enrollment, course_key=course_id, course_enrollment=course_enrollment, status='active', ) program_enrollments.append(program_enrollment) serialized = ProgramEnrollmentSerializer(program_enrollments, many=True) return serialized.data