Merge pull request #28266 from eduNEXT/MJG/1st_batch_openedx_events
[BD-32] feat: 1st batch of Open edX Events
This commit is contained in:
@@ -55,6 +55,13 @@ from simple_history.models import HistoricalRecords
|
||||
from slumber.exceptions import HttpClientError, HttpServerError
|
||||
from user_util import user_util
|
||||
|
||||
from openedx_events.learning.data import (
|
||||
CourseData,
|
||||
CourseEnrollmentData,
|
||||
UserData,
|
||||
UserPersonalData,
|
||||
)
|
||||
from openedx_events.learning.signals import COURSE_ENROLLMENT_CREATED
|
||||
import openedx.core.djangoapps.django_comment_common.comment_client as cc
|
||||
from common.djangoapps.course_modes.models import CourseMode, get_cosmetic_verified_display_price
|
||||
from common.djangoapps.student.emails import send_proctoring_requirements_email
|
||||
@@ -1569,9 +1576,16 @@ class CourseEnrollment(models.Model):
|
||||
# All the server-side checks for whether a user is allowed to enroll.
|
||||
try:
|
||||
course = CourseOverview.get_from_id(course_key)
|
||||
course_data = CourseData(
|
||||
course_key=course.id,
|
||||
display_name=course.display_name,
|
||||
)
|
||||
except CourseOverview.DoesNotExist:
|
||||
# This is here to preserve legacy behavior which allowed enrollment in courses
|
||||
# announced before the start of content creation.
|
||||
course_data = CourseData(
|
||||
course_key=course_key,
|
||||
)
|
||||
if check_access:
|
||||
log.warning("User %s failed to enroll in non-existent course %s", user.username, str(course_key))
|
||||
raise NonExistentCourseError # lint-amnesty, pylint: disable=raise-missing-from
|
||||
@@ -1607,6 +1621,25 @@ class CourseEnrollment(models.Model):
|
||||
enrollment.update_enrollment(is_active=True, mode=mode, enterprise_uuid=enterprise_uuid)
|
||||
enrollment.send_signal(EnrollStatusChange.enroll)
|
||||
|
||||
# Announce user's enrollment
|
||||
COURSE_ENROLLMENT_CREATED.send_event(
|
||||
enrollment=CourseEnrollmentData(
|
||||
user=UserData(
|
||||
pii=UserPersonalData(
|
||||
username=user.username,
|
||||
email=user.email,
|
||||
name=user.profile.name,
|
||||
),
|
||||
id=user.id,
|
||||
is_active=user.is_active,
|
||||
),
|
||||
course=course_data,
|
||||
mode=enrollment.mode,
|
||||
is_active=enrollment.is_active,
|
||||
creation_date=enrollment.created,
|
||||
)
|
||||
)
|
||||
|
||||
return enrollment
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -10,6 +10,7 @@ import ddt
|
||||
import pytest
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from openedx_events.tests.utils import OpenEdxEventsTestMixin
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
@@ -30,11 +31,13 @@ from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
@ddt.ddt
|
||||
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_SPECIAL_EXAMS': True})
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
class EnrollmentTest(UrlResetMixin, SharedModuleStoreTestCase):
|
||||
class EnrollmentTest(UrlResetMixin, SharedModuleStoreTestCase, OpenEdxEventsTestMixin):
|
||||
"""
|
||||
Test student enrollment, especially with different course modes.
|
||||
"""
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = []
|
||||
|
||||
USERNAME = "Bob"
|
||||
EMAIL = "bob@example.com"
|
||||
PASSWORD = "edx"
|
||||
@@ -42,7 +45,14 @@ class EnrollmentTest(UrlResetMixin, SharedModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
cls.course = CourseFactory.create()
|
||||
cls.course_limited = CourseFactory.create()
|
||||
cls.proctored_course = CourseFactory(
|
||||
|
||||
@@ -10,10 +10,23 @@ from django.db.utils import IntegrityError
|
||||
from django.test import TestCase
|
||||
from django_countries.fields import Country
|
||||
|
||||
from common.djangoapps.student.models import CourseEnrollmentAllowed
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentAllowedFactory, UserFactory
|
||||
from common.djangoapps.student.models import CourseEnrollmentAllowed, CourseEnrollment
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentAllowedFactory, UserFactory, UserProfileFactory
|
||||
from common.djangoapps.student.tests.tests import UserSettingsEventTestMixin
|
||||
|
||||
from openedx_events.learning.data import (
|
||||
CourseData,
|
||||
CourseEnrollmentData,
|
||||
UserData,
|
||||
UserPersonalData,
|
||||
)
|
||||
from openedx_events.learning.signals import COURSE_ENROLLMENT_CREATED
|
||||
from openedx_events.tests.utils import OpenEdxEventsTestMixin
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
class TestUserProfileEvents(UserSettingsEventTestMixin, TestCase):
|
||||
"""
|
||||
@@ -179,3 +192,87 @@ class TestUserEvents(UserSettingsEventTestMixin, TestCase):
|
||||
# CEAs shouldn't have been affected
|
||||
assert CourseEnrollmentAllowed.objects.count() == 1
|
||||
assert CourseEnrollmentAllowed.objects.filter(email='test@edx.org').count() == 1
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
class EnrollmentEventsTest(SharedModuleStoreTestCase, OpenEdxEventsTestMixin):
|
||||
"""
|
||||
Tests for the Open edX Events associated with the enrollment process through the enroll method.
|
||||
|
||||
This class guarantees that the following events are sent during the user's enrollment, with
|
||||
the exact Data Attributes as the event definition stated:
|
||||
|
||||
- COURSE_ENROLLMENT_CREATED: sent after the user's enrollment.
|
||||
"""
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = ["org.openedx.learning.course.enrollment.created.v1"]
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create()
|
||||
self.user = UserFactory.create(
|
||||
username="test",
|
||||
email="test@example.com",
|
||||
password="password",
|
||||
)
|
||||
self.user_profile = UserProfileFactory.create(user=self.user, name="Test Example")
|
||||
self.receiver_called = False
|
||||
|
||||
def _event_receiver_side_effect(self, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
Used show that the Open edX Event was called by the Django signal handler.
|
||||
"""
|
||||
self.receiver_called = True
|
||||
|
||||
def test_enrollment_created_event_emitted(self):
|
||||
"""
|
||||
Test whether the student enrollment event is sent after the user's
|
||||
enrollment process.
|
||||
|
||||
Expected result:
|
||||
- COURSE_ENROLLMENT_CREATED is sent and received by the mocked receiver.
|
||||
- The arguments that the receiver gets are the arguments sent by the event
|
||||
except the metadata generated on the fly.
|
||||
"""
|
||||
event_receiver = mock.Mock(side_effect=self._event_receiver_side_effect)
|
||||
COURSE_ENROLLMENT_CREATED.connect(event_receiver)
|
||||
|
||||
enrollment = CourseEnrollment.enroll(self.user, self.course.id)
|
||||
|
||||
self.assertTrue(self.receiver_called)
|
||||
self.assertDictContainsSubset(
|
||||
{
|
||||
"signal": COURSE_ENROLLMENT_CREATED,
|
||||
"sender": None,
|
||||
"enrollment": CourseEnrollmentData(
|
||||
user=UserData(
|
||||
pii=UserPersonalData(
|
||||
username=self.user.username,
|
||||
email=self.user.email,
|
||||
name=self.user.profile.name,
|
||||
),
|
||||
id=self.user.id,
|
||||
is_active=self.user.is_active,
|
||||
),
|
||||
course=CourseData(
|
||||
course_key=self.course.id,
|
||||
display_name=self.course.display_name,
|
||||
),
|
||||
mode=enrollment.mode,
|
||||
is_active=enrollment.is_active,
|
||||
creation_date=enrollment.created,
|
||||
),
|
||||
},
|
||||
event_receiver.call_args.kwargs
|
||||
)
|
||||
|
||||
@@ -29,6 +29,8 @@ from edx_django_utils.monitoring import set_custom_attribute
|
||||
from ratelimit.decorators import ratelimit
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from openedx_events.learning.data import UserData, UserPersonalData
|
||||
from openedx_events.learning.signals import SESSION_LOGIN_COMPLETED
|
||||
from common.djangoapps.edxmako.shortcuts import render_to_response
|
||||
from openedx.core.djangoapps.password_policy import compliance as password_policy_compliance
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
@@ -298,6 +300,19 @@ def _handle_successful_authentication_and_login(user, request):
|
||||
django_login(request, user)
|
||||
request.session.set_expiry(604800 * 4)
|
||||
log.debug("Setting user session expiry to 4 weeks")
|
||||
|
||||
# Announce user's login
|
||||
SESSION_LOGIN_COMPLETED.send_event(
|
||||
user=UserData(
|
||||
pii=UserPersonalData(
|
||||
username=user.username,
|
||||
email=user.email,
|
||||
name=user.profile.name,
|
||||
),
|
||||
id=user.id,
|
||||
is_active=user.is_active,
|
||||
),
|
||||
)
|
||||
except Exception as exc:
|
||||
AUDIT_LOG.critical("Login failed - Could not create session. Is memcached running?")
|
||||
log.critical("Login failed - Could not create session. Is memcached running?")
|
||||
|
||||
@@ -23,6 +23,8 @@ from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
|
||||
from django.views.decorators.debug import sensitive_post_parameters
|
||||
from edx_django_utils.monitoring import set_custom_attribute
|
||||
from edx_toggles.toggles import LegacyWaffleFlag, LegacyWaffleFlagNamespace
|
||||
from openedx_events.learning.data import UserData, UserPersonalData
|
||||
from openedx_events.learning.signals import STUDENT_REGISTRATION_COMPLETED
|
||||
from pytz import UTC
|
||||
from ratelimit.decorators import ratelimit
|
||||
from requests import HTTPError
|
||||
@@ -252,6 +254,18 @@ def create_account_with_params(request, params):
|
||||
# Announce registration
|
||||
REGISTER_USER.send(sender=None, user=user, registration=registration)
|
||||
|
||||
STUDENT_REGISTRATION_COMPLETED.send_event(
|
||||
user=UserData(
|
||||
pii=UserPersonalData(
|
||||
username=user.username,
|
||||
email=user.email,
|
||||
name=user.profile.name,
|
||||
),
|
||||
id=user.id,
|
||||
is_active=user.is_active,
|
||||
),
|
||||
)
|
||||
|
||||
create_comments_service_user(user)
|
||||
|
||||
try:
|
||||
|
||||
183
openedx/core/djangoapps/user_authn/views/tests/test_events.py
Normal file
183
openedx/core/djangoapps/user_authn/views/tests/test_events.py
Normal file
@@ -0,0 +1,183 @@
|
||||
"""
|
||||
Test classes for the events sent in the registration process.
|
||||
|
||||
Classes:
|
||||
RegistrationEventTest: Test event sent after registering a user through the
|
||||
user API.
|
||||
LoginSessionEventTest: Test event sent after creating the user's login session
|
||||
user through the user API.
|
||||
"""
|
||||
from unittest.mock import Mock
|
||||
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.urls import reverse
|
||||
from openedx_events.learning.data import UserData, UserPersonalData
|
||||
from openedx_events.learning.signals import SESSION_LOGIN_COMPLETED, STUDENT_REGISTRATION_COMPLETED
|
||||
from openedx_events.tests.utils import OpenEdxEventsTestMixin
|
||||
|
||||
from common.djangoapps.student.tests.factories import UserFactory, UserProfileFactory
|
||||
from openedx.core.djangoapps.user_api.tests.test_views import UserAPITestCase
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
class RegistrationEventTest(UserAPITestCase, OpenEdxEventsTestMixin):
|
||||
"""
|
||||
Tests for the Open edX Events associated with the registration process through
|
||||
the registration view.
|
||||
|
||||
This class guarantees that the following events are sent after registering
|
||||
a user, with the exact Data Attributes as the event definition stated:
|
||||
|
||||
- STUDENT_REGISTRATION_COMPLETED: after the user's registration has been
|
||||
completed.
|
||||
"""
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = ["org.openedx.learning.student.registration.completed.v1"]
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
So the Open edX Events Isolation starts, the setUpClass must be explicitly
|
||||
called with the method that executes the isolation. We do this to avoid
|
||||
MRO resolution conflicts with other sibling classes while ensuring the
|
||||
isolation process begins.
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super().setUp()
|
||||
self.url = reverse("user_api_registration")
|
||||
self.user_info = {
|
||||
"email": "user@example.com",
|
||||
"name": "Test User",
|
||||
"username": "test",
|
||||
"password": "password",
|
||||
"honor_code": "true",
|
||||
}
|
||||
self.receiver_called = False
|
||||
|
||||
def _event_receiver_side_effect(self, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
Used show that the Open edX Event was called by the Django signal handler.
|
||||
"""
|
||||
self.receiver_called = True
|
||||
|
||||
def test_send_registration_event(self):
|
||||
"""
|
||||
Test whether the student registration event is sent during the user's
|
||||
registration process.
|
||||
|
||||
Expected result:
|
||||
- STUDENT_REGISTRATION_COMPLETED is sent and received by the mocked receiver.
|
||||
- The arguments that the receiver gets are the arguments sent by the event
|
||||
except the metadata generated on the fly.
|
||||
"""
|
||||
event_receiver = Mock(side_effect=self._event_receiver_side_effect)
|
||||
STUDENT_REGISTRATION_COMPLETED.connect(event_receiver)
|
||||
|
||||
self.client.post(self.url, self.user_info)
|
||||
|
||||
user = User.objects.get(username=self.user_info.get("username"))
|
||||
self.assertTrue(self.receiver_called)
|
||||
self.assertDictContainsSubset(
|
||||
{
|
||||
"signal": STUDENT_REGISTRATION_COMPLETED,
|
||||
"sender": None,
|
||||
"user": UserData(
|
||||
pii=UserPersonalData(
|
||||
username=user.username,
|
||||
email=user.email,
|
||||
name=user.profile.name,
|
||||
),
|
||||
id=user.id,
|
||||
is_active=user.is_active,
|
||||
),
|
||||
},
|
||||
event_receiver.call_args.kwargs
|
||||
)
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
class LoginSessionEventTest(UserAPITestCase, OpenEdxEventsTestMixin):
|
||||
"""
|
||||
Tests for the Open edX Events associated with the login process through the
|
||||
login_user view.
|
||||
|
||||
This class guarantees that the following events are sent after the user's
|
||||
session creation, with the exact Data Attributes as the event definition
|
||||
stated:
|
||||
|
||||
- SESSION_LOGIN_COMPLETED: after login has been completed.
|
||||
"""
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = ["org.openedx.learning.auth.session.login.completed.v1"]
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super().setUp()
|
||||
self.url = reverse("user_api_login_session", kwargs={"api_version": "v1"})
|
||||
self.user = UserFactory.create(
|
||||
username="test",
|
||||
email="test@example.com",
|
||||
password="password",
|
||||
)
|
||||
self.user_profile = UserProfileFactory.create(user=self.user, name="Test Example")
|
||||
self.receiver_called = True
|
||||
|
||||
def _event_receiver_side_effect(self, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
Used show that the Open edX Event was called by the Django signal handler.
|
||||
"""
|
||||
self.receiver_called = True
|
||||
|
||||
def test_send_login_event(self):
|
||||
"""
|
||||
Test whether the student login event is sent after the user's
|
||||
login process.
|
||||
|
||||
Expected result:
|
||||
- SESSION_LOGIN_COMPLETED is sent and received by the mocked receiver.
|
||||
- The arguments that the receiver gets are the arguments sent by the event
|
||||
except the metadata generated on the fly.
|
||||
"""
|
||||
event_receiver = Mock(side_effect=self._event_receiver_side_effect)
|
||||
SESSION_LOGIN_COMPLETED.connect(event_receiver)
|
||||
data = {
|
||||
"email": "test@example.com",
|
||||
"password": "password",
|
||||
}
|
||||
|
||||
self.client.post(self.url, data)
|
||||
|
||||
user = User.objects.get(username=self.user.username)
|
||||
self.assertTrue(self.receiver_called)
|
||||
self.assertDictContainsSubset(
|
||||
{
|
||||
"signal": SESSION_LOGIN_COMPLETED,
|
||||
"sender": None,
|
||||
"user": UserData(
|
||||
pii=UserPersonalData(
|
||||
username=user.username,
|
||||
email=user.email,
|
||||
name=user.profile.name,
|
||||
),
|
||||
id=user.id,
|
||||
is_active=user.is_active,
|
||||
),
|
||||
},
|
||||
event_receiver.call_args.kwargs
|
||||
)
|
||||
@@ -21,6 +21,7 @@ from django.urls import NoReverseMatch, reverse
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag, override_waffle_switch
|
||||
from freezegun import freeze_time
|
||||
from common.djangoapps.student.tests.factories import RegistrationFactory, UserFactory, UserProfileFactory
|
||||
from openedx_events.tests.utils import OpenEdxEventsTestMixin
|
||||
|
||||
from openedx.core.djangoapps.password_policy.compliance import (
|
||||
NonCompliantPasswordException,
|
||||
@@ -44,11 +45,13 @@ from common.djangoapps.util.password_policy_validators import DEFAULT_MAX_PASSWO
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
class LoginTest(SiteMixin, CacheIsolationTestCase, OpenEdxEventsTestMixin):
|
||||
"""
|
||||
Test login_user() view
|
||||
"""
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = []
|
||||
|
||||
ENABLED_CACHES = ['default']
|
||||
LOGIN_FAILED_WARNING = 'Email or password is incorrect'
|
||||
ACTIVATE_ACCOUNT_WARNING = 'In order to sign in, you need to activate your account'
|
||||
@@ -56,6 +59,17 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
user_email = 'test@edx.org'
|
||||
password = 'test_password'
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def setUp(self):
|
||||
"""Setup a test user along with its registration and profile"""
|
||||
super().setUp()
|
||||
@@ -954,13 +968,26 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
|
||||
@ddt.ddt
|
||||
@skip_unless_lms
|
||||
class LoginSessionViewTest(ApiTestCase):
|
||||
class LoginSessionViewTest(ApiTestCase, OpenEdxEventsTestMixin):
|
||||
"""Tests for the login end-points of the user API. """
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = []
|
||||
|
||||
USERNAME = "bob"
|
||||
EMAIL = "bob@example.com"
|
||||
PASSWORD = "password"
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.url = reverse("user_api_login_session", kwargs={'api_version': 'v1'})
|
||||
|
||||
@@ -17,6 +17,7 @@ from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from pytz import UTC
|
||||
from social_django.models import Partial, UserSocialAuth
|
||||
from openedx_events.tests.utils import OpenEdxEventsTestMixin
|
||||
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
from openedx.core.djangoapps.site_configuration.helpers import get_value
|
||||
@@ -69,12 +70,16 @@ from common.djangoapps.util.password_policy_validators import (
|
||||
|
||||
@ddt.ddt
|
||||
@skip_unless_lms
|
||||
class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCase, RetirementTestCase):
|
||||
class RegistrationViewValidationErrorTest(
|
||||
ThirdPartyAuthTestMixin, UserAPITestCase, RetirementTestCase, OpenEdxEventsTestMixin
|
||||
):
|
||||
"""
|
||||
Tests for catching duplicate email and username validation errors within
|
||||
the registration end-points of the User API.
|
||||
"""
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = []
|
||||
|
||||
maxDiff = None
|
||||
|
||||
USERNAME = "bob"
|
||||
@@ -88,6 +93,17 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa
|
||||
COUNTRY = "us"
|
||||
GOALS = "Learn all the things!"
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super().setUp()
|
||||
self.url = reverse("user_api_registration")
|
||||
@@ -423,9 +439,13 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa
|
||||
|
||||
@ddt.ddt
|
||||
@skip_unless_lms
|
||||
class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
class RegistrationViewTestV1(
|
||||
ThirdPartyAuthTestMixin, UserAPITestCase, OpenEdxEventsTestMixin
|
||||
):
|
||||
"""Tests for the registration end-points of the User API. """
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = []
|
||||
|
||||
maxDiff = None
|
||||
|
||||
USERNAME = "bob"
|
||||
@@ -486,6 +506,17 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
]
|
||||
link_template = "<a href='/honor' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super().setUp()
|
||||
self.url = reverse("user_api_registration")
|
||||
@@ -1815,6 +1846,17 @@ class RegistrationViewTestV2(RegistrationViewTestV1):
|
||||
|
||||
# pylint: disable=test-inherits-tests
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super(RegistrationViewTestV1, self).setUp() # lint-amnesty, pylint: disable=bad-super-call
|
||||
self.url = reverse("user_api_registration_v2")
|
||||
@@ -2043,16 +2085,31 @@ class RegistrationViewTestV2(RegistrationViewTestV1):
|
||||
|
||||
@httpretty.activate
|
||||
@ddt.ddt
|
||||
class ThirdPartyRegistrationTestMixin(ThirdPartyOAuthTestMixin, CacheIsolationTestCase):
|
||||
class ThirdPartyRegistrationTestMixin(
|
||||
ThirdPartyOAuthTestMixin, CacheIsolationTestCase, OpenEdxEventsTestMixin
|
||||
):
|
||||
"""
|
||||
Tests for the User API registration endpoint with 3rd party authentication.
|
||||
"""
|
||||
CREATE_USER = False
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = []
|
||||
|
||||
ENABLED_CACHES = ['default']
|
||||
|
||||
__test__ = False
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.url = reverse('user_api_registration')
|
||||
@@ -2209,11 +2266,25 @@ class ThirdPartyRegistrationTestMixin(ThirdPartyOAuthTestMixin, CacheIsolationTe
|
||||
|
||||
@skipUnless(settings.FEATURES.get("ENABLE_THIRD_PARTY_AUTH"), "third party auth not enabled")
|
||||
class TestFacebookRegistrationView(
|
||||
ThirdPartyRegistrationTestMixin, ThirdPartyOAuthTestMixinFacebook, TransactionTestCase
|
||||
ThirdPartyRegistrationTestMixin, ThirdPartyOAuthTestMixinFacebook, TransactionTestCase, OpenEdxEventsTestMixin
|
||||
):
|
||||
"""Tests the User API registration endpoint with Facebook authentication."""
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = []
|
||||
|
||||
__test__ = True
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def test_social_auth_exception(self):
|
||||
"""
|
||||
According to the do_auth method in social_core.backends.facebook.py,
|
||||
@@ -2227,21 +2298,48 @@ class TestFacebookRegistrationView(
|
||||
|
||||
@skipUnless(settings.FEATURES.get("ENABLE_THIRD_PARTY_AUTH"), "third party auth not enabled")
|
||||
class TestGoogleRegistrationView(
|
||||
ThirdPartyRegistrationTestMixin, ThirdPartyOAuthTestMixinGoogle, TransactionTestCase
|
||||
ThirdPartyRegistrationTestMixin, ThirdPartyOAuthTestMixinGoogle, TransactionTestCase, OpenEdxEventsTestMixin
|
||||
):
|
||||
"""Tests the User API registration endpoint with Google authentication."""
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = []
|
||||
|
||||
__test__ = True
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class RegistrationValidationViewTests(test_utils.ApiTestCase):
|
||||
class RegistrationValidationViewTests(test_utils.ApiTestCase, OpenEdxEventsTestMixin):
|
||||
"""
|
||||
Tests for validity of user data in registration forms.
|
||||
"""
|
||||
|
||||
ENABLED_OPENEDX_EVENTS = []
|
||||
|
||||
endpoint_name = 'registration_validation'
|
||||
path = reverse(endpoint_name)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up class method for the Test class.
|
||||
|
||||
This method starts manually events isolation. Explanation here:
|
||||
openedx/core/djangoapps/user_authn/views/tests/test_events.py#L44
|
||||
"""
|
||||
super().setUpClass()
|
||||
cls.start_events_isolation()
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
cache.clear()
|
||||
|
||||
@@ -122,6 +122,7 @@ nltk # Natural language processing; used by the c
|
||||
nodeenv # Utility for managing Node.js environments; we use this for deployments and testing
|
||||
oauthlib # OAuth specification support for authenticating via LTI or other Open edX services
|
||||
openedx-calc # Library supporting mathematical calculations for Open edX
|
||||
openedx-events # Open edX Events from Hooks Extension Framework (OEP-50)
|
||||
ora2
|
||||
piexif # Exif image metadata manipulation, used in the profile_images app
|
||||
Pillow # Image manipulation library; used for course assets, profile images, invoice PDFs, etc.
|
||||
|
||||
@@ -53,6 +53,7 @@ attrs==21.2.0
|
||||
# -r requirements/edx/base.in
|
||||
# aiohttp
|
||||
# edx-ace
|
||||
# openedx-events
|
||||
babel==2.9.1
|
||||
# via
|
||||
# -r requirements/edx/base.in
|
||||
@@ -220,6 +221,7 @@ django==2.2.24
|
||||
# help-tokens
|
||||
# jsonfield2
|
||||
# lti-consumer-xblock
|
||||
# openedx-events
|
||||
# ora2
|
||||
# rest-condition
|
||||
# super-csv
|
||||
@@ -469,6 +471,7 @@ edx-opaque-keys[django]==2.2.2
|
||||
# edx-user-state-client
|
||||
# edx-when
|
||||
# lti-consumer-xblock
|
||||
# openedx-events
|
||||
# ora2
|
||||
# xmodule
|
||||
edx-organizations==6.10.0
|
||||
@@ -702,6 +705,8 @@ oauthlib==3.0.1
|
||||
# social-auth-core
|
||||
openedx-calc==2.0.1
|
||||
# via -r requirements/edx/base.in
|
||||
openedx-events==0.5.1
|
||||
# via -r requirements/edx/base.in
|
||||
ora2==3.6.20
|
||||
# via -r requirements/edx/base.in
|
||||
packaging==21.0
|
||||
|
||||
@@ -74,6 +74,7 @@ attrs==21.2.0
|
||||
# aiohttp
|
||||
# edx-ace
|
||||
# jsonschema
|
||||
# openedx-events
|
||||
# pytest
|
||||
babel==2.9.1
|
||||
# via
|
||||
@@ -298,6 +299,7 @@ django==2.2.24
|
||||
# help-tokens
|
||||
# jsonfield2
|
||||
# lti-consumer-xblock
|
||||
# openedx-events
|
||||
# ora2
|
||||
# rest-condition
|
||||
# super-csv
|
||||
@@ -574,6 +576,7 @@ edx-opaque-keys[django]==2.2.2
|
||||
# edx-user-state-client
|
||||
# edx-when
|
||||
# lti-consumer-xblock
|
||||
# openedx-events
|
||||
# ora2
|
||||
# xmodule
|
||||
edx-organizations==6.10.0
|
||||
@@ -929,6 +932,8 @@ oauthlib==3.0.1
|
||||
# social-auth-core
|
||||
openedx-calc==2.0.1
|
||||
# via -r requirements/edx/testing.txt
|
||||
openedx-events==0.5.1
|
||||
# via -r requirements/edx/testing.txt
|
||||
ora2==3.6.20
|
||||
# via -r requirements/edx/testing.txt
|
||||
packaging==21.0
|
||||
|
||||
@@ -68,6 +68,7 @@ attrs==21.2.0
|
||||
# -r requirements/edx/base.txt
|
||||
# aiohttp
|
||||
# edx-ace
|
||||
# openedx-events
|
||||
# pytest
|
||||
babel==2.9.1
|
||||
# via
|
||||
@@ -283,6 +284,7 @@ distlib==0.3.2
|
||||
# help-tokens
|
||||
# jsonfield2
|
||||
# lti-consumer-xblock
|
||||
# openedx-events
|
||||
# ora2
|
||||
# rest-condition
|
||||
# super-csv
|
||||
@@ -556,6 +558,7 @@ edx-opaque-keys[django]==2.2.2
|
||||
# edx-user-state-client
|
||||
# edx-when
|
||||
# lti-consumer-xblock
|
||||
# openedx-events
|
||||
# ora2
|
||||
# xmodule
|
||||
edx-organizations==6.10.0
|
||||
@@ -877,6 +880,8 @@ oauthlib==3.0.1
|
||||
# social-auth-core
|
||||
openedx-calc==2.0.1
|
||||
# via -r requirements/edx/base.txt
|
||||
openedx-events==0.5.1
|
||||
# via -r requirements/edx/base.txt
|
||||
ora2==3.6.20
|
||||
# via -r requirements/edx/base.txt
|
||||
packaging==21.0
|
||||
|
||||
Reference in New Issue
Block a user