refactor: mfe_context response to serialize object keys to camelcase (#31930)
This commit is contained in:
137
openedx/core/djangoapps/user_authn/api/tests/test_serializers.py
Normal file
137
openedx/core/djangoapps/user_authn/api/tests/test_serializers.py
Normal file
@@ -0,0 +1,137 @@
|
||||
"""Tests for serializers for the MFE Context"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from openedx.core.djangoapps.user_authn.serializers import MFEContextSerializer
|
||||
|
||||
|
||||
class TestMFEContextSerializer(TestCase):
|
||||
"""
|
||||
High-level unit tests for MFEContextSerializer
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_mock_mfe_context_data():
|
||||
"""
|
||||
Helper function to generate mock data for the MFE Context API view.
|
||||
"""
|
||||
|
||||
mock_context_data = {
|
||||
'context_data': {
|
||||
'currentProvider': 'edX',
|
||||
'platformName': 'edX',
|
||||
'providers': [
|
||||
{
|
||||
'id': 'oa2-facebook',
|
||||
'name': 'Facebook',
|
||||
'iconClass': 'fa-facebook',
|
||||
'iconImage': None,
|
||||
'skipHintedLogin': False,
|
||||
'skipRegistrationForm': False,
|
||||
'loginUrl': 'https://facebook.com/login',
|
||||
'registerUrl': 'https://facebook.com/register'
|
||||
},
|
||||
{
|
||||
'id': 'oa2-google-oauth2',
|
||||
'name': 'Google',
|
||||
'iconClass': 'fa-google-plus',
|
||||
'iconImage': None,
|
||||
'skipHintedLogin': False,
|
||||
'skipRegistrationForm': False,
|
||||
'loginUrl': 'https://google.com/login',
|
||||
'registerUrl': 'https://google.com/register'
|
||||
}
|
||||
],
|
||||
'secondaryProviders': [],
|
||||
'finishAuthUrl': 'https://edx.com/auth/finish',
|
||||
'errorMessage': None,
|
||||
'registerFormSubmitButtonText': 'Create Account',
|
||||
'autoSubmitRegForm': False,
|
||||
'syncLearnerProfileData': False,
|
||||
'countryCode': '',
|
||||
'pipeline_user_details': {
|
||||
'username': 'test123',
|
||||
'email': 'test123@edx.com',
|
||||
'fullname': 'Test Test',
|
||||
'first_name': 'Test',
|
||||
'last_name': 'Test'
|
||||
}
|
||||
},
|
||||
'registration_fields': {},
|
||||
'optional_fields': {
|
||||
'extended_profile': []
|
||||
}
|
||||
}
|
||||
|
||||
return mock_context_data
|
||||
|
||||
@staticmethod
|
||||
def get_expected_data():
|
||||
"""
|
||||
Helper function to generate expected data for the MFE Context API view serializer.
|
||||
"""
|
||||
|
||||
expected_data = {
|
||||
'contextData': {
|
||||
'currentProvider': 'edX',
|
||||
'platformName': 'edX',
|
||||
'providers': [
|
||||
{
|
||||
'id': 'oa2-facebook',
|
||||
'name': 'Facebook',
|
||||
'iconClass': 'fa-facebook',
|
||||
'iconImage': None,
|
||||
'skipHintedLogin': False,
|
||||
'skipRegistrationForm': False,
|
||||
'loginUrl': 'https://facebook.com/login',
|
||||
'registerUrl': 'https://facebook.com/register'
|
||||
},
|
||||
{
|
||||
'id': 'oa2-google-oauth2',
|
||||
'name': 'Google',
|
||||
'iconClass': 'fa-google-plus',
|
||||
'iconImage': None,
|
||||
'skipHintedLogin': False,
|
||||
'skipRegistrationForm': False,
|
||||
'loginUrl': 'https://google.com/login',
|
||||
'registerUrl': 'https://google.com/register'
|
||||
}
|
||||
],
|
||||
'secondaryProviders': [],
|
||||
'finishAuthUrl': 'https://edx.com/auth/finish',
|
||||
'errorMessage': None,
|
||||
'registerFormSubmitButtonText': 'Create Account',
|
||||
'autoSubmitRegForm': False,
|
||||
'syncLearnerProfileData': False,
|
||||
'countryCode': '',
|
||||
'pipelineUserDetails': {
|
||||
'username': 'test123',
|
||||
'email': 'test123@edx.com',
|
||||
'name': 'Test Test',
|
||||
'firstName': 'Test',
|
||||
'lastName': 'Test'
|
||||
}
|
||||
},
|
||||
'registrationFields': {},
|
||||
'optionalFields': {
|
||||
'extended_profile': []
|
||||
}
|
||||
}
|
||||
|
||||
return expected_data
|
||||
|
||||
def test_mfe_context_serializer(self):
|
||||
"""
|
||||
Test MFEContextSerializer with mock data that serializes data correctly
|
||||
"""
|
||||
|
||||
mfe_context_data = self.get_mock_mfe_context_data()
|
||||
expected_data = self.get_expected_data()
|
||||
output_data = MFEContextSerializer(
|
||||
mfe_context_data
|
||||
).data
|
||||
|
||||
self.assertDictEqual(
|
||||
output_data,
|
||||
expected_data
|
||||
)
|
||||
@@ -42,6 +42,8 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
hostname = socket.gethostname()
|
||||
ip_address = socket.gethostbyname(hostname)
|
||||
self.country_code = country_code_from_ip(ip_address)
|
||||
self.pipeline_user_details = {'username': None, 'email': None, 'name': None,
|
||||
'firstName': None, 'lastName': None}
|
||||
|
||||
# Several third party auth providers are created for these tests:
|
||||
self.configure_google_provider(enabled=True, visible=True)
|
||||
@@ -93,8 +95,12 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
"""
|
||||
Returns the MFE context
|
||||
"""
|
||||
|
||||
if add_user_details:
|
||||
self.pipeline_user_details.update({'email': 'test@test.com'})
|
||||
|
||||
return {
|
||||
'context_data': {
|
||||
'contextData': {
|
||||
'currentProvider': current_provider,
|
||||
'platformName': settings.PLATFORM_NAME,
|
||||
'providers': self.get_provider_data(params) if params else [],
|
||||
@@ -102,12 +108,13 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
'finishAuthUrl': pipeline.get_complete_url(backend_name) if backend_name else None,
|
||||
'errorMessage': None,
|
||||
'registerFormSubmitButtonText': 'Create Account',
|
||||
'autoSubmitRegForm': False,
|
||||
'syncLearnerProfileData': False,
|
||||
'pipeline_user_details': {'email': 'test@test.com'} if add_user_details else {},
|
||||
'countryCode': self.country_code
|
||||
'countryCode': self.country_code,
|
||||
'pipelineUserDetails': self.pipeline_user_details,
|
||||
},
|
||||
'registration_fields': {},
|
||||
'optional_fields': {
|
||||
'registrationFields': {},
|
||||
'optionalFields': {
|
||||
'extended_profile': [],
|
||||
},
|
||||
}
|
||||
@@ -182,7 +189,7 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
})
|
||||
|
||||
response = self.client.get(self.url, self.query_params)
|
||||
assert response.data['context_data']['providers'] == provider_data
|
||||
assert response.data['contextData']['providers'] == provider_data
|
||||
|
||||
def test_user_country_code(self):
|
||||
"""
|
||||
@@ -191,7 +198,7 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
response = self.client.get(self.url, self.query_params)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.data['context_data']['countryCode'] == self.country_code
|
||||
assert response.data['contextData']['countryCode'] == self.country_code
|
||||
|
||||
@override_settings(
|
||||
ENABLE_DYNAMIC_REGISTRATION_FIELDS=True,
|
||||
@@ -205,7 +212,7 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
self.query_params.update({'is_register_page': True})
|
||||
response = self.client.get(self.url, self.query_params)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert response.data['registration_fields']['fields'] == {}
|
||||
assert response.data['registrationFields']['fields'] == {}
|
||||
|
||||
@with_site_configuration(
|
||||
configuration={
|
||||
@@ -223,8 +230,9 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
"""
|
||||
self.query_params.update({'is_register_page': True})
|
||||
response = self.client.get(self.url, self.query_params)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert list(response.data['registration_fields']['fields'].keys()) == ['first_name', 'last_name', 'state']
|
||||
assert list(response.data['registrationFields']['fields'].keys()) == ['first_name', 'last_name', 'state']
|
||||
|
||||
@override_settings(
|
||||
ENABLE_DYNAMIC_REGISTRATION_FIELDS=True,
|
||||
@@ -248,7 +256,7 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
self.query_params.update({'is_register_page': True})
|
||||
response = self.client.get(self.url, self.query_params)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert response.data['optional_fields']['fields'] == expected_response
|
||||
assert response.data['optionalFields']['fields'] == expected_response
|
||||
|
||||
@with_site_configuration(
|
||||
configuration={
|
||||
@@ -282,8 +290,9 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
}
|
||||
self.query_params.update({'is_register_page': True})
|
||||
response = self.client.get(self.url, self.query_params)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert response.data['optional_fields']['fields'] == expected_response
|
||||
assert response.data['optionalFields']['fields'] == expected_response
|
||||
|
||||
@with_site_configuration(
|
||||
configuration={
|
||||
@@ -302,7 +311,7 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
self.query_params.update({'is_register_page': True})
|
||||
response = self.client.get(self.url, self.query_params)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert list(response.data['optional_fields']['fields'].keys()) == ['specialty', 'goals']
|
||||
assert list(response.data['optionalFields']['fields'].keys()) == ['specialty', 'goals']
|
||||
|
||||
@with_site_configuration(
|
||||
configuration={
|
||||
@@ -322,7 +331,7 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
self.query_params.update({'is_register_page': True})
|
||||
response = self.client.get(self.url, self.query_params)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert list(response.data['registration_fields']['fields'].keys()) == ['specialty']
|
||||
assert list(response.data['registrationFields']['fields'].keys()) == ['specialty']
|
||||
|
||||
@override_settings(
|
||||
ENABLE_DYNAMIC_REGISTRATION_FIELDS=True,
|
||||
@@ -333,7 +342,6 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
Test that API return valid response dictionary with both required and optional fields
|
||||
"""
|
||||
response = self.client.get(self.url, self.query_params)
|
||||
|
||||
assert response.data == self.get_context()
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ from common.djangoapps.student.helpers import get_next_url_for_login_page
|
||||
from common.djangoapps.student.views import compose_and_send_activation_email
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.user_authn.api.helper import RegistrationFieldsContext
|
||||
from openedx.core.djangoapps.user_authn.serializers import MFEContextSerializer
|
||||
from openedx.core.djangoapps.user_authn.views.utils import get_mfe_context
|
||||
|
||||
|
||||
@@ -65,6 +66,7 @@ class MFEContextView(APIView):
|
||||
context['registration_fields'].update({
|
||||
'fields': registration_fields,
|
||||
})
|
||||
|
||||
optional_fields = RegistrationFieldsContext('optional').get_fields()
|
||||
if optional_fields:
|
||||
context['optional_fields'].update({
|
||||
@@ -74,7 +76,9 @@ class MFEContextView(APIView):
|
||||
|
||||
return Response(
|
||||
status=status.HTTP_200_OK,
|
||||
data=context
|
||||
data=MFEContextSerializer(
|
||||
context
|
||||
).data
|
||||
)
|
||||
|
||||
|
||||
|
||||
77
openedx/core/djangoapps/user_authn/serializers.py
Normal file
77
openedx/core/djangoapps/user_authn/serializers.py
Normal file
@@ -0,0 +1,77 @@
|
||||
"""
|
||||
MFE Context API Serializers
|
||||
"""
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class ProvidersSerializer(serializers.Serializer):
|
||||
"""
|
||||
Providers Serializers
|
||||
"""
|
||||
|
||||
id = serializers.CharField(allow_null=True)
|
||||
name = serializers.CharField(allow_null=True)
|
||||
iconClass = serializers.CharField(allow_null=True)
|
||||
iconImage = serializers.CharField(allow_null=True)
|
||||
skipHintedLogin = serializers.BooleanField(default=False)
|
||||
skipRegistrationForm = serializers.BooleanField(default=False)
|
||||
loginUrl = serializers.CharField(allow_null=True)
|
||||
registerUrl = serializers.CharField(allow_null=True)
|
||||
|
||||
|
||||
class PipelineUserDetailsSerializer(serializers.Serializer):
|
||||
"""
|
||||
Pipeline User Details Serializers
|
||||
"""
|
||||
|
||||
username = serializers.CharField(allow_null=True)
|
||||
email = serializers.CharField(allow_null=True)
|
||||
name = serializers.CharField(source='fullname', allow_null=True)
|
||||
firstName = serializers.CharField(source='first_name', allow_null=True)
|
||||
lastName = serializers.CharField(source='last_name', allow_null=True)
|
||||
|
||||
|
||||
class ContextDataSerializer(serializers.Serializer):
|
||||
"""
|
||||
Context Data Serializers
|
||||
"""
|
||||
|
||||
currentProvider = serializers.CharField(allow_null=True)
|
||||
platformName = serializers.CharField(allow_null=True)
|
||||
providers = serializers.ListField(
|
||||
child=ProvidersSerializer(),
|
||||
allow_null=True
|
||||
)
|
||||
secondaryProviders = serializers.ListField(
|
||||
child=ProvidersSerializer(),
|
||||
allow_null=True
|
||||
)
|
||||
finishAuthUrl = serializers.CharField(allow_null=True)
|
||||
errorMessage = serializers.CharField(allow_null=True)
|
||||
registerFormSubmitButtonText = serializers.CharField(allow_null=True)
|
||||
autoSubmitRegForm = serializers.BooleanField(default=False)
|
||||
syncLearnerProfileData = serializers.BooleanField(default=False)
|
||||
countryCode = serializers.CharField(allow_null=True)
|
||||
pipelineUserDetails = PipelineUserDetailsSerializer(source='pipeline_user_details', allow_null=True)
|
||||
|
||||
|
||||
class MFEContextSerializer(serializers.Serializer):
|
||||
"""
|
||||
Serializer class to convert the keys of MFE Context Response dict object to camelCase format.
|
||||
"""
|
||||
|
||||
contextData = ContextDataSerializer(
|
||||
source='context_data',
|
||||
default={}
|
||||
)
|
||||
registrationFields = serializers.DictField(
|
||||
source='registration_fields',
|
||||
default={}
|
||||
)
|
||||
optionalFields = serializers.DictField(
|
||||
source='optional_fields',
|
||||
default={
|
||||
'extended_profile': []
|
||||
}
|
||||
)
|
||||
Reference in New Issue
Block a user