ENT-3503 | Add unit tests to cover 100% of openedx.features.enterprise_support.utils, all in a single test file.

This commit is contained in:
Alex Dusenbery
2020-11-09 11:50:51 -05:00
committed by Alex Dusenbery
parent 2f8fa9e4f2
commit 341c1c98e5
2 changed files with 356 additions and 2 deletions

View File

@@ -3,20 +3,41 @@ Test the enterprise support utils.
"""
import json
import uuid
import ddt
import mock
from django.conf import settings
from django.test import TestCase
from django.test.utils import override_settings
from django.urls import NoReverseMatch
from edx_toggles.toggles.testutils import override_waffle_flag
from openedx.core.djangolib.testing.utils import skip_unless_lms
from openedx.features.enterprise_support.tests import FEATURES_WITH_ENTERPRISE_ENABLED
from openedx.features.enterprise_support.tests.factories import (
EnterpriseCustomerBrandingConfigurationFactory,
EnterpriseCustomerFactory,
EnterpriseCustomerUserFactory
)
from openedx.features.enterprise_support.utils import ENTERPRISE_HEADER_LINKS, get_enterprise_learner_portal
from openedx.features.enterprise_support.utils import (
ENTERPRISE_HEADER_LINKS,
clear_data_consent_share_cache,
enterprise_fields_only,
fetch_enterprise_customer_by_id,
get_data_consent_share_cache_key,
get_enterprise_learner_generic_name,
get_enterprise_learner_portal,
get_enterprise_readonly_account_fields,
get_enterprise_sidebar_context,
get_enterprise_slug_login_url,
get_provider_login_url,
handle_enterprise_cookies_for_logistration,
is_enterprise_learner,
update_account_settings_context_for_enterprise,
update_logistration_context_for_enterprise,
update_third_party_auth_context_for_enterprise,
)
from common.djangoapps.student.tests.factories import UserFactory
@@ -33,6 +54,103 @@ class TestEnterpriseUtils(TestCase):
cls.user = UserFactory.create(password='password')
super(TestEnterpriseUtils, cls).setUpTestData()
@mock.patch('openedx.features.enterprise_support.utils.get_cache_key')
def test_get_data_consent_share_cache_key(self, mock_get_cache_key):
expected_cache_key = mock_get_cache_key.return_value
assert expected_cache_key == get_data_consent_share_cache_key('some-user-id', 'some-course-id')
mock_get_cache_key.assert_called_once_with(
type='data_sharing_consent_needed',
user_id='some-user-id',
course_id='some-course-id',
)
@mock.patch('openedx.features.enterprise_support.utils.get_cache_key')
@mock.patch('openedx.features.enterprise_support.utils.TieredCache')
def test_clear_data_consent_share_cache(self, mock_tiered_cache, mock_get_cache_key):
user_id = 'some-user-id'
course_id = 'some-course-id'
clear_data_consent_share_cache(user_id, course_id)
mock_get_cache_key.assert_called_once_with(
type='data_sharing_consent_needed',
user_id='some-user-id',
course_id='some-course-id',
)
mock_tiered_cache.delete_all_tiers.assert_called_once_with(mock_get_cache_key.return_value)
@mock.patch('openedx.features.enterprise_support.utils.update_third_party_auth_context_for_enterprise')
def test_update_logistration_context_no_customer_data(self, mock_update_tpa_context):
request = mock.Mock()
context = {}
enterprise_customer = {}
update_logistration_context_for_enterprise(request, context, enterprise_customer)
assert context['enable_enterprise_sidebar'] is False
mock_update_tpa_context.assert_called_once_with(request, context, enterprise_customer)
@mock.patch('openedx.features.enterprise_support.utils.update_third_party_auth_context_for_enterprise')
@mock.patch('openedx.features.enterprise_support.utils.get_enterprise_sidebar_context', return_value={})
def test_update_logistration_context_no_sidebar_context(self, mock_sidebar_context, mock_update_tpa_context):
request = mock.Mock(GET={'proxy_login': False})
context = {}
enterprise_customer = {'key': 'value'}
update_logistration_context_for_enterprise(request, context, enterprise_customer)
assert context['enable_enterprise_sidebar'] is False
mock_update_tpa_context.assert_called_once_with(request, context, enterprise_customer)
mock_sidebar_context.assert_called_once_with(enterprise_customer, False)
@mock.patch('openedx.features.enterprise_support.utils.update_third_party_auth_context_for_enterprise')
@mock.patch('openedx.features.enterprise_support.utils.get_enterprise_sidebar_context')
@mock.patch('openedx.features.enterprise_support.utils.enterprise_fields_only')
def test_update_logistration_context_with_sidebar_context(
self, mock_enterprise_fields_only, mock_sidebar_context, mock_update_tpa_context
):
request = mock.Mock(GET={'proxy_login': False})
context = {
'data': {
'registration_form_desc': {
'thing-1': 'one',
'thing-2': 'two',
},
},
}
enterprise_customer = {'name': 'pied-piper'}
mock_sidebar_context.return_value = {
'sidebar-1': 'one',
'sidebar-2': 'two',
}
update_logistration_context_for_enterprise(request, context, enterprise_customer)
assert context['enable_enterprise_sidebar'] is True
mock_update_tpa_context.assert_called_once_with(request, context, enterprise_customer)
mock_enterprise_fields_only.assert_called_once_with(context['data']['registration_form_desc'])
mock_sidebar_context.assert_called_once_with(enterprise_customer, False)
@ddt.data(
{'is_proxy_login': True, 'branding_configuration': {'logo': 'path-to-logo'}},
{'is_proxy_login': True, 'branding_configuration': {}},
{'is_proxy_login': False, 'branding_configuration': {'nonsense': 'foo'}},
)
@ddt.unpack
def test_get_enterprise_sidebar_context(self, is_proxy_login, branding_configuration):
enterprise_customer = {
'name': 'pied-piper',
'branding_configuration': branding_configuration,
}
actual_result = get_enterprise_sidebar_context(enterprise_customer, is_proxy_login)
assert 'pied-piper' == actual_result['enterprise_name']
expected_logo_url = branding_configuration.get('logo', '')
assert expected_logo_url == actual_result['enterprise_logo_url']
self.assertIn('pied-piper', str(actual_result['enterprise_branded_welcome_string']))
@ddt.data(
('notfoundpage', 0),
)
@@ -49,6 +167,155 @@ class TestEnterpriseUtils(TestCase):
self.client.get(resource)
self.assertEqual(mock_customer_request.call_count, expected_calls)
@mock.patch('openedx.features.enterprise_support.utils.configuration_helpers.get_value')
def test_enterprise_fields_only(self, mock_get_value):
mock_get_value.return_value = ['cat', 'dog', 'sheep']
fields = {
'fields': [
{'name': 'cat', 'value': 1},
{'name': 'fish', 'value': 2},
{'name': 'dog', 'value': 3},
{'name': 'emu', 'value': 4},
{'name': 'sheep', 'value': 5},
],
}
expected_fields = [
{'name': 'fish', 'value': 2},
{'name': 'emu', 'value': 4},
]
assert expected_fields == enterprise_fields_only(fields)
@mock.patch('openedx.features.enterprise_support.utils.third_party_auth')
def test_update_third_party_auth_context_for_enterprise(self, mock_tpa):
context = {
'data': {
'third_party_auth': {
'errorMessage': 'Widget error.',
},
},
}
enterprise_customer = mock.Mock()
request = mock.Mock()
# This will directly modify context
update_third_party_auth_context_for_enterprise(request, context, enterprise_customer)
self.assertIn(
'We are sorry, you are not authorized',
str(context['data']['third_party_auth']['errorMessage'])
)
self.assertIn(
'Widget error.',
str(context['data']['third_party_auth']['errorMessage'])
)
assert [] == context['data']['third_party_auth']['providers']
assert [] == context['data']['third_party_auth']['secondaryProviders']
self.assertFalse(context['data']['third_party_auth']['autoSubmitRegForm'])
self.assertIn(
'Just a couple steps',
str(context['data']['third_party_auth']['autoRegisterWelcomeMessage'])
)
assert 'Continue' == str(context['data']['third_party_auth']['registerFormSubmitButtonText'])
mock_tpa.pipeline.get.assert_called_once_with(request)
@mock.patch('openedx.features.enterprise_support.utils.standard_cookie_settings', return_value={})
def test_handle_enterprise_cookies_for_logistration(self, mock_cookie_settings):
context = {'enable_enterprise_sidebar': True}
request = mock.Mock()
response = mock.Mock()
handle_enterprise_cookies_for_logistration(request, response, context)
response.set_cookie.assert_called_once_with(
'experiments_is_enterprise',
'true',
)
response.delete_cookie.assert_called_once_with(
settings.ENTERPRISE_CUSTOMER_COOKIE_NAME,
domain=settings.BASE_COOKIE_DOMAIN,
)
mock_cookie_settings.assert_called_once_with(request)
@mock.patch('openedx.features.enterprise_support.utils.get_enterprise_readonly_account_fields', return_value=[])
def test_update_account_settings_context_for_enterprise(self, mock_get_fields):
enterprise_customer = {
'name': 'pied-piper',
'identity_provider': None,
}
context = {}
user = mock.Mock()
update_account_settings_context_for_enterprise(context, enterprise_customer, user)
expected_context = {
'enterprise_name': 'pied-piper',
'sync_learner_profile_data': False,
'edx_support_url': settings.SUPPORT_SITE_LINK,
'enterprise_readonly_account_fields': {
'fields': mock_get_fields.return_value,
},
}
mock_get_fields.assert_called_once_with(user)
assert expected_context == context
@mock.patch('openedx.features.enterprise_support.utils.get_current_request')
@mock.patch('openedx.features.enterprise_support.api.enterprise_customer_for_request')
def test_get_enterprise_readonly_account_fields_no_sync_learner_profile_data(
self, mock_customer_for_request, mock_get_current_request
):
mock_get_current_request.return_value = mock.Mock(
GET={'enterprise_customer': 'some-uuid'},
)
mock_customer_for_request.return_value = {
'uuid': 'some-uuid',
'identity_provider': None,
}
user = mock.Mock()
actual_fields = get_enterprise_readonly_account_fields(user)
assert set() == actual_fields
mock_customer_for_request.assert_called_once_with(mock_get_current_request.return_value)
mock_get_current_request.assert_called_once_with()
@mock.patch('openedx.features.enterprise_support.utils.UserSocialAuth')
@mock.patch('openedx.features.enterprise_support.utils.get_current_request')
@mock.patch('openedx.features.enterprise_support.api.enterprise_customer_for_request')
@mock.patch('openedx.features.enterprise_support.utils.third_party_auth')
def test_get_enterprise_readonly_account_fields_with_idp_sync(
self, mock_tpa, mock_customer_for_request, mock_get_current_request, mock_user_social_auth
):
mock_get_current_request.return_value = mock.Mock(
GET={'enterprise_customer': 'some-uuid'},
)
mock_customer_for_request.return_value = {
'uuid': 'some-uuid',
'identity_provider': 'mock-idp',
}
mock_idp = mock.MagicMock(
backend_name='mock-backend',
sync_learner_profile_data=True,
)
mock_tpa.provider.Registry.get.return_value = mock_idp
user = mock.Mock()
actual_fields = get_enterprise_readonly_account_fields(user)
assert set(settings.ENTERPRISE_READONLY_ACCOUNT_FIELDS) == actual_fields
mock_customer_for_request.assert_called_once_with(mock_get_current_request.return_value)
mock_get_current_request.assert_called_once_with()
mock_tpa.provider.Registry.get.assert_called_with(provider_id='mock-idp')
mock_select_related = mock_user_social_auth.objects.select_related
mock_select_related.assert_called_once_with('user')
mock_select_related.return_value.filter.assert_called_once_with(
provider=mock_idp.backend_name,
user=user
)
@override_waffle_flag(ENTERPRISE_HEADER_LINKS, True)
def test_get_enterprise_learner_portal_uncached(self):
"""
@@ -148,3 +415,90 @@ class TestEnterpriseUtils(TestCase):
}, user=self.user)
portal = get_enterprise_learner_portal(request)
self.assertDictEqual(portal, enterprise_customer_data)
@override_waffle_flag(ENTERPRISE_HEADER_LINKS, True)
def test_get_enterprise_learner_portal_no_enterprise_user(self):
request = mock.MagicMock(session={}, user=self.user)
# Indicate the "preferred" customer in the request
request.GET = {'enterprise_customer': uuid.uuid4()}
portal = get_enterprise_learner_portal(request)
self.assertIsNone(portal)
def test_get_enterprise_learner_generic_name_404_pages(self):
request = mock.Mock(view_name='404')
self.assertIsNone(get_enterprise_learner_generic_name(request))
@mock.patch('openedx.features.enterprise_support.api.enterprise_customer_for_request')
def test_get_enterprise_learner_generic_name_with_replacement(self, mock_customer_for_request):
request = mock.Mock()
mock_customer_for_request.return_value = {
'name': 'Test Corp',
'replace_sensitive_sso_username': True,
}
generic_name = get_enterprise_learner_generic_name(request)
assert 'Test CorpLearner' == generic_name
@mock.patch('openedx.features.enterprise_support.api.enterprise_customer_for_request')
def test_get_enterprise_learner_generic_name_no_replacement(self, mock_customer_for_request):
request = mock.Mock()
mock_customer_for_request.return_value = {
'name': 'Test Corp',
'replace_sensitive_sso_username': False,
}
generic_name = get_enterprise_learner_generic_name(request)
assert '' == generic_name
def test_is_enterprise_learner(self):
EnterpriseCustomerUserFactory.create(active=True, user_id=self.user.id)
self.assertTrue(is_enterprise_learner(self.user))
def test_is_enterprise_learner_no_enterprise_user(self):
self.assertFalse(is_enterprise_learner(self.user))
@mock.patch('openedx.features.enterprise_support.utils.reverse')
def test_get_enterprise_slug_login_url_no_reverse_match(self, mock_reverse):
mock_reverse.side_effect = NoReverseMatch
self.assertIsNone(get_enterprise_slug_login_url())
mock_reverse.assert_called_once_with('enterprise_slug_login')
@mock.patch('openedx.features.enterprise_support.utils.reverse')
def test_get_enterprise_slug_login_url_with_match(self, mock_reverse):
self.assertIsNotNone(get_enterprise_slug_login_url())
mock_reverse.assert_called_once_with('enterprise_slug_login')
def test_fetch_enterprise_customer_by_id(self):
the_uuid = uuid.uuid4()
customer = EnterpriseCustomerFactory.create(uuid=the_uuid)
assert customer == fetch_enterprise_customer_by_id(the_uuid)
@mock.patch('openedx.features.enterprise_support.utils.get_next_url_for_login_page')
@mock.patch('openedx.features.enterprise_support.utils.third_party_auth')
def test_get_provider_login_url_no_redirect_url(self, mock_tpa, mock_next_login_url):
request = mock.Mock()
provider_id = 'anything'
login_url = get_provider_login_url(request, provider_id)
assert mock_tpa.pipeline.get_login_url.return_value == login_url
mock_tpa.pipeline.get_login_url.assert_called_once_with(
provider_id,
mock_tpa.pipeline.AUTH_ENTRY_LOGIN,
redirect_url=mock_next_login_url.return_value,
)
mock_next_login_url.assert_called_once_with(request)
@mock.patch('openedx.features.enterprise_support.utils.get_next_url_for_login_page')
@mock.patch('openedx.features.enterprise_support.utils.third_party_auth')
def test_get_provider_login_url_with_redirect_url(self, mock_tpa, mock_next_login_url):
request = mock.Mock()
provider_id = 'anything'
redirect_url = 'the-next-url'
login_url = get_provider_login_url(request, provider_id, redirect_url=redirect_url)
assert mock_tpa.pipeline.get_login_url.return_value == login_url
mock_tpa.pipeline.get_login_url.assert_called_once_with(
provider_id,
mock_tpa.pipeline.AUTH_ENTRY_LOGIN,
redirect_url=redirect_url,
)
self.assertFalse(mock_next_login_url.called)

View File

@@ -144,7 +144,7 @@ def enterprise_fields_only(fields):
def update_third_party_auth_context_for_enterprise(request, context, enterprise_customer=None):
"""
Return updated context of third party auth with modified for enterprise.
Return updated context of third party auth with modified data for the given enterprise customer.
Arguments:
request (HttpRequest): The request for the logistration page.