diff --git a/tests/test_enterprise/api/test_views.py b/tests/test_enterprise/api/test_views.py index 0b0c68a216..fa380974d3 100644 --- a/tests/test_enterprise/api/test_views.py +++ b/tests/test_enterprise/api/test_views.py @@ -4437,6 +4437,7 @@ def tearDown(self): }, ) @ddt.unpack + @mock.patch('enterprise.api.v1.views.enterprise_customer.get_course_details_from_course_keys') @mock.patch('enterprise.api.v1.views.enterprise_customer.get_best_mode_from_course_key') @mock.patch('enterprise.api.v1.views.enterprise_customer.track_enrollment') @mock.patch("enterprise.models.EnterpriseCustomer.notify_enrolled_learners") @@ -4445,6 +4446,7 @@ def test_bulk_enrollment_in_bulk_courses_pending_licenses( mock_notify_task, mock_track_enroll, mock_get_course_mode, + mock_get_course_details, body, expected_code, expected_response, @@ -4464,6 +4466,7 @@ def test_bulk_enrollment_in_bulk_courses_pending_licenses( permission = Permission.objects.get(name='Can add Enterprise Customer') self.user.user_permissions.add(permission) mock_get_course_mode.return_value = VERIFIED_SUBSCRIPTION_COURSE_MODE + mock_get_course_details.return_value.__getitem__.return_value.invitation_only = False self.assertEqual(len(PendingEnrollment.objects.all()), 0) response = self.client.post( @@ -4488,6 +4491,7 @@ def test_bulk_enrollment_in_bulk_courses_pending_licenses( # no notifications to be sent unless 'notify' specifically asked for in payload mock_notify_task.assert_not_called() + @mock.patch('enterprise.api.v1.views.enterprise_customer.get_course_details_from_course_keys') @mock.patch('enterprise.api.v1.views.enterprise_customer.get_best_mode_from_course_key') @mock.patch('enterprise.api.v1.views.enterprise_customer.track_enrollment') @mock.patch('enterprise.models.EnterpriseCustomer.notify_enrolled_learners') @@ -4498,6 +4502,7 @@ def test_bulk_enrollment_in_bulk_courses_existing_users( mock_notify_task, mock_track_enroll, mock_get_course_mode, + mock_get_course_details, ): """ Tests the bulk enrollment endpoint at enroll_learners_in_courses. @@ -4505,6 +4510,8 @@ def test_bulk_enrollment_in_bulk_courses_existing_users( This tests the case where existing users are supplied, so the enrollments are fulfilled rather than pending. """ mock_update_or_create_enrollment.return_value = True + mock_get_course_details.return_value.__getitem__.return_value.invitation_only = False + user_one = factories.UserFactory(is_active=True) user_two = factories.UserFactory(is_active=True) @@ -4575,6 +4582,7 @@ def test_bulk_enrollment_in_bulk_courses_existing_users( assert mock_update_or_create_enrollment.call_count == 2 + @mock.patch('enterprise.api.v1.views.enterprise_customer.get_course_details_from_course_keys') @mock.patch('enterprise.api.v1.views.enterprise_customer.get_best_mode_from_course_key') @mock.patch('enterprise.api.v1.views.enterprise_customer.track_enrollment') @mock.patch('enterprise.models.EnterpriseCustomer.notify_enrolled_learners') @@ -4583,12 +4591,15 @@ def test_bulk_enrollment_in_bulk_courses_nonexisting_user_id( mock_notify_task, mock_track_enroll, mock_get_course_mode, + mock_get_course_details, ): """ Tests the bulk enrollment endpoint at enroll_learners_in_courses. This tests the case where a non-existent user_id is supplied, so an error should occur. """ + mock_get_course_details.return_value.__getitem__.return_value.invitation_only = False + user = factories.UserFactory(is_active=True) factories.EnterpriseCustomerFactory( @@ -4647,6 +4658,7 @@ def test_bulk_enrollment_in_bulk_courses_nonexisting_user_id( }, ) @ddt.unpack + @mock.patch("enterprise.api.v1.views.enterprise_customer.get_course_details_from_course_keys") @mock.patch("enterprise.api.v1.views.enterprise_subsidy_fulfillment.enrollment_api") @mock.patch( 'enterprise.api.v1.views.enterprise_customer.get_best_mode_from_course_key' @@ -4657,6 +4669,7 @@ def test_bulk_enrollment_enroll_after_cancel( mock_platform_enrollment, mock_get_course_mode, mock_update_or_create_enrollment, + mock_get_course_details, old_transaction_id, new_transaction_id, ): @@ -4666,6 +4679,7 @@ def test_bulk_enrollment_enroll_after_cancel( """ mock_platform_enrollment.return_value = True mock_get_course_mode.return_value = VERIFIED_SUBSCRIPTION_COURSE_MODE + mock_get_course_details.return_value.__getitem__.return_value.invitation_only = False # Needed for the cancel endpoint: mock_update_or_create_enrollment.update_enrollment.return_value = mock.Mock() @@ -4768,12 +4782,14 @@ def test_bulk_enrollment_enroll_after_cancel( }, ) @ddt.unpack + @mock.patch('enterprise.api.v1.views.enterprise_customer.get_course_details_from_course_keys') @mock.patch('enterprise.api.v1.views.enterprise_customer.get_best_mode_from_course_key') @mock.patch('enterprise.utils.lms_update_or_create_enrollment') def test_bulk_enrollment_includes_fulfillment_source_uuid( self, mock_get_course_mode, mock_update_or_create_enrollment, + mock_get_course_details, body, fulfillment_source, ): @@ -4782,6 +4798,7 @@ def test_bulk_enrollment_includes_fulfillment_source_uuid( generated subsidized enrollment uuid value as part of the response payload. """ mock_update_or_create_enrollment.return_value = True + mock_get_course_details.return_value.__getitem__.return_value.invitation_only = False user, _, enterprise_customer = self._create_user_and_enterprise_customer( body.get('enrollments_info')[0].get('email'), 'test_password' @@ -4878,6 +4895,7 @@ def test_bulk_enrollment_includes_fulfillment_source_uuid( }, ) @ddt.unpack + @mock.patch('enterprise.api.v1.views.enterprise_customer.get_course_details_from_course_keys') @mock.patch('enterprise.api.v1.views.enterprise_customer.get_best_mode_from_course_key') @mock.patch('enterprise.api.v1.views.enterprise_customer.track_enrollment') @mock.patch("enterprise.models.EnterpriseCustomer.notify_enrolled_learners") @@ -4886,6 +4904,7 @@ def test_bulk_enrollment_with_notification( mock_notify_task, mock_track_enroll, mock_get_course_mode, + mock_get_course_details, body, expected_code, expected_response, @@ -4905,6 +4924,7 @@ def test_bulk_enrollment_with_notification( permission = Permission.objects.get(name='Can add Enterprise Customer') self.user.user_permissions.add(permission) mock_get_course_mode.return_value = VERIFIED_SUBSCRIPTION_COURSE_MODE + mock_get_course_details.return_value.__getitem__.return_value.invitation_only = False self.assertEqual(len(PendingEnrollment.objects.all()), 0) @@ -4951,12 +4971,71 @@ def _make_call(course_run, enrolled_learners): mock_notify_task.assert_has_calls(mock_calls, any_order=True) + @mock.patch('enterprise.utils.CourseEnrollmentAllowed') + @mock.patch('enterprise.api.v1.views.enterprise_customer.get_course_details_from_course_keys') + @mock.patch('enterprise.api.v1.views.enterprise_customer.get_best_mode_from_course_key') + @mock.patch('enterprise.utils.lms_update_or_create_enrollment') + def test_bulk_enrollment_invitation_only( + self, + mock_update_or_create_enrollment, + mock_get_course_mode, + mock_get_course_details, + mock_cea, + ): + """ + Tests that bulk enrollment endpoint creates CourseEnrollmentAllowed object when enterprise customer allows + enrollment in invitation only courses and the course is invitation only. + """ + mock_update_or_create_enrollment.return_value = True + mock_get_course_details.return_value.__getitem__.return_value.invitation_only = True + mock_get_course_mode.return_value = VERIFIED_SUBSCRIPTION_COURSE_MODE + + user, _, enterprise_customer = self._create_user_and_enterprise_customer("abc@test.com", "test_password") + course_id = 'course-v1:edX+DemoX+Demo_Course' + body = { + 'enrollments_info': [ + { + 'user_id': user.id, + 'course_run_key': course_id, + 'license_uuid': '5a88bdcade7c4ecb838f8111b68e18ac' + }, + ] + } + def enroll(): + self.client.post( + settings.TEST_SERVER + reverse( + 'enterprise-customer-enroll-learners-in-courses', (enterprise_customer.uuid,) + ), + data=json.dumps(body), + content_type='application/json', + ) + + enroll() + mock_cea.objects.update_or_create.assert_not_called() + + enterprise_customer.allow_enrollment_in_invite_only_courses = True + enterprise_customer.save() + + enroll() + mock_cea.objects.update_or_create.assert_called_with( + course_id=course_id, + email=user.email + ) + + @mock.patch('enterprise.api.v1.views.enterprise_customer.get_course_details_from_course_keys') @mock.patch('enterprise.api.v1.views.enterprise_customer.enroll_subsidy_users_in_courses') @mock.patch('enterprise.api.v1.views.enterprise_customer.get_best_mode_from_course_key') - def test_enroll_learners_in_courses_partial_failure(self, mock_get_course_mode, mock_enroll_user): + def test_enroll_learners_in_courses_partial_failure( + self, + mock_get_course_mode, + mock_enroll_user, + mock_get_course_details, + ): """ Tests that bulk users bulk enrollment endpoint properly handles partial failures. """ + mock_get_course_details.return_value.__getitem__.return_value.invitation_only = True + ent_customer = factories.EnterpriseCustomerFactory( uuid=FAKE_UUIDS[0], name="test_enterprise"