diff --git a/openedx/core/djangoapps/user_authn/api/tests/test_data.py b/openedx/core/djangoapps/user_authn/api/tests/data_mock.py similarity index 51% rename from openedx/core/djangoapps/user_authn/api/tests/test_data.py rename to openedx/core/djangoapps/user_authn/api/tests/data_mock.py index 05d0f7cf6b..c5c1c317e1 100644 --- a/openedx/core/djangoapps/user_authn/api/tests/test_data.py +++ b/openedx/core/djangoapps/user_authn/api/tests/data_mock.py @@ -1,37 +1,35 @@ -""" Mocked data for testing """ +""" +Constants for testing MFE Context API +""" -mfe_context_data_keys = { - 'contextData', - 'registrationFields', - 'optionalFields' -} +_tpa_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' + } +] -mock_mfe_context_data = { +MFE_CONTEXT_WITH_TPA_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' - } - ], + 'providers': _tpa_providers, 'secondaryProviders': [], 'finishAuthUrl': 'https://edx.com/auth/finish', 'errorMessage': None, @@ -47,58 +45,13 @@ mock_mfe_context_data = { 'last_name': 'Test' } }, - 'registration_fields': {}, - 'optional_fields': { - 'extended_profile': [] - } } -mock_default_mfe_context_data = { - 'context_data': { - 'currentProvider': None, - 'platformName': 'édX', - 'providers': [], - 'secondaryProviders': [], - 'finishAuthUrl': None, - 'errorMessage': None, - 'registerFormSubmitButtonText': 'Create Account', - 'autoSubmitRegForm': False, - 'syncLearnerProfileData': False, - 'countryCode': '', - 'pipeline_user_details': {} - }, - 'registration_fields': {}, - 'optional_fields': { - 'extended_profile': [] - } -} - -expected_mfe_context_data = { +SERIALIZED_MFE_CONTEXT_WITH_TPA_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' - } - ], + 'providers': _tpa_providers, 'secondaryProviders': [], 'finishAuthUrl': 'https://edx.com/auth/finish', 'errorMessage': None, @@ -120,7 +73,23 @@ expected_mfe_context_data = { } } -default_expected_mfe_context_data = { +MFE_CONTEXT_WITHOUT_TPA_DATA = { + 'context_data': { + 'currentProvider': None, + 'platformName': 'édX', + 'providers': [], + 'secondaryProviders': [], + 'finishAuthUrl': None, + 'errorMessage': None, + 'registerFormSubmitButtonText': 'Create Account', + 'autoSubmitRegForm': False, + 'syncLearnerProfileData': False, + 'countryCode': '', + 'pipeline_user_details': {} + } +} + +SERIALIZED_MFE_CONTEXT_WITHOUT_TPA_DATA = { 'contextData': { 'currentProvider': None, 'platformName': 'édX', diff --git a/openedx/core/djangoapps/user_authn/api/tests/test_serializers.py b/openedx/core/djangoapps/user_authn/api/tests/test_serializers.py index 348292b172..77d0dbb271 100644 --- a/openedx/core/djangoapps/user_authn/api/tests/test_serializers.py +++ b/openedx/core/djangoapps/user_authn/api/tests/test_serializers.py @@ -1,12 +1,14 @@ -"""Tests for serializers for the MFE Context""" +""" +Tests for serializers for the MFE Context +""" from django.test import TestCase -from openedx.core.djangoapps.user_authn.api.tests.test_data import ( - mock_mfe_context_data, - expected_mfe_context_data, - mock_default_mfe_context_data, - default_expected_mfe_context_data, +from openedx.core.djangoapps.user_authn.api.tests.data_mock import ( + MFE_CONTEXT_WITH_TPA_DATA, + MFE_CONTEXT_WITHOUT_TPA_DATA, + SERIALIZED_MFE_CONTEXT_WITH_TPA_DATA, + SERIALIZED_MFE_CONTEXT_WITHOUT_TPA_DATA, ) from openedx.core.djangoapps.user_authn.serializers import MFEContextSerializer @@ -22,12 +24,12 @@ class TestMFEContextSerializer(TestCase): """ output_data = MFEContextSerializer( - mock_mfe_context_data + MFE_CONTEXT_WITH_TPA_DATA ).data self.assertDictEqual( output_data, - expected_mfe_context_data + SERIALIZED_MFE_CONTEXT_WITH_TPA_DATA ) def test_mfe_context_serializer_default_response(self): @@ -35,10 +37,10 @@ class TestMFEContextSerializer(TestCase): Test MFEContextSerializer with default data """ serialized_data = MFEContextSerializer( - mock_default_mfe_context_data + MFE_CONTEXT_WITHOUT_TPA_DATA ).data self.assertDictEqual( serialized_data, - default_expected_mfe_context_data + SERIALIZED_MFE_CONTEXT_WITHOUT_TPA_DATA ) diff --git a/openedx/core/djangoapps/user_authn/api/tests/test_views.py b/openedx/core/djangoapps/user_authn/api/tests/test_views.py index d8ab2c37c1..c1947e2939 100644 --- a/openedx/core/djangoapps/user_authn/api/tests/test_views.py +++ b/openedx/core/djangoapps/user_authn/api/tests/test_views.py @@ -1,16 +1,15 @@ """ Logistration API View Tests """ -import socket -from unittest.mock import patch -from urllib.parse import urlencode - import ddt +import socket from django.conf import settings from django.test.utils import override_settings from django.urls import reverse from rest_framework import status from rest_framework.test import APITestCase +from unittest.mock import patch +from urllib.parse import urlencode from common.djangoapps.student.models import Registration from common.djangoapps.student.tests.factories import UserFactory @@ -19,7 +18,6 @@ from common.djangoapps.third_party_auth.tests.testutil import ThirdPartyAuthTest from openedx.core.djangoapps.geoinfo.api import country_code_from_ip from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration from openedx.core.djangoapps.user_api.tests.test_views import UserAPITestCase -from openedx.core.djangoapps.user_authn.api.tests.test_data import mfe_context_data_keys from openedx.core.djangolib.testing.utils import skip_unless_lms @@ -376,7 +374,33 @@ class MFEContextViewTest(ThirdPartyAuthTestMixin, APITestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) response_keys = set(response.data.keys()) - self.assertSetEqual(response_keys, mfe_context_data_keys) + self.assertSetEqual( + response_keys, + { + 'contextData', + 'registrationFields', + 'optionalFields' + } + ) + + @with_site_configuration( + configuration={ + 'extended_profile_fields': ['specialty'] + } + ) + @override_settings( + ENABLE_DYNAMIC_REGISTRATION_FIELDS=True, + REGISTRATION_EXTRA_FIELDS={'specialty': 'optional', 'goals': 'optional'}, + ) + def test_welcome_page_context(self): + """ + Test MFE Context API response for welcome page + """ + self.query_params.update({'is_welcome_page': True}) + response = self.client.get(self.url, self.query_params) + assert response.status_code == status.HTTP_200_OK + assert list(response.data['optionalFields']['fields'].keys()) == ['specialty', 'goals'] + assert list(response.data['optionalFields']['extended_profile']) == ['specialty'] @skip_unless_lms diff --git a/openedx/core/djangoapps/user_authn/api/views.py b/openedx/core/djangoapps/user_authn/api/views.py index b1f4304070..f190ab565a 100644 --- a/openedx/core/djangoapps/user_authn/api/views.py +++ b/openedx/core/djangoapps/user_authn/api/views.py @@ -33,6 +33,21 @@ class MFEContextView(APIView): """ throttle_classes = [MFEContextThrottle] + def _get_optional_fields_context(self): + """ + Fetch optional fields data for registration form + """ + optional_fields_context = {} + optional_fields = RegistrationFieldsContext('optional').get_fields() + if optional_fields: + extended_profile_fields = configuration_helpers.get_value('extended_profile_fields') + optional_fields_context = { + 'fields': optional_fields, + 'extended_profile': extended_profile_fields if extended_profile_fields else [] + } + + return optional_fields_context + def get(self, request, **kwargs): # lint-amnesty, pylint: disable=unused-argument """ Returns @@ -45,14 +60,16 @@ class MFEContextView(APIView): Arguments: request (HttpRequest): The request, used to determine if a pipeline is currently running. - tpa_hint (string): An override flag that will return a matching provider - as long as its configuration has been enabled - is_register_page (boolen): Determine the call is from register or login page + kwargs (dict): + tpa_hint (string): An override flag that will return a matching provider + as long as its configuration has been enabled + is_register_page (bool): Determine the call is from register or login page + is_welcome_page (bool): Checks if the call is from the Welcome Page """ request_params = request.GET redirect_to = get_next_url_for_login_page(request) third_party_auth_hint = request_params.get('tpa_hint') - is_register_page = request_params.get('is_register_page') + context = { 'context_data': get_mfe_context(request, redirect_to, third_party_auth_hint), 'registration_fields': {}, @@ -61,20 +78,26 @@ class MFEContextView(APIView): }, } - if settings.ENABLE_DYNAMIC_REGISTRATION_FIELDS and is_register_page: - registration_fields = RegistrationFieldsContext().get_fields() - context['registration_fields'].update({ - 'fields': registration_fields, - }) + if settings.ENABLE_DYNAMIC_REGISTRATION_FIELDS: + if request_params.get('is_welcome_page'): + optional_fields = self._get_optional_fields_context() + return Response( + status=status.HTTP_200_OK, + data=MFEContextSerializer( + {'optional_fields': optional_fields} if optional_fields else {} + ).data + ) - optional_fields = RegistrationFieldsContext('optional').get_fields() - if optional_fields: - extended_profile_fields = configuration_helpers.get_value('extended_profile_fields') - context['optional_fields'].update({ - 'fields': optional_fields, - 'extended_profile': extended_profile_fields if extended_profile_fields else [] + if request_params.get('is_register_page'): + registration_fields = RegistrationFieldsContext().get_fields() + context['registration_fields'].update({ + 'fields': registration_fields, }) + optional_fields = self._get_optional_fields_context() + if optional_fields: + context['optional_fields'].update(optional_fields) + return Response( status=status.HTTP_200_OK, data=MFEContextSerializer(