From 1504c098a9b8908dac413080d4fe5d9bad2198fa Mon Sep 17 00:00:00 2001 From: John Eskew Date: Wed, 27 Dec 2017 17:24:12 -0500 Subject: [PATCH] Form expected test redirect urls properly. --- .../third_party_auth/tests/specs/base.py | 19 +++++++---- .../tests/specs/test_google.py | 7 ++-- .../third_party_auth/tests/specs/test_lti.py | 32 ++++++++++++------- .../tests/specs/test_testshib.py | 3 +- .../third_party_auth/tests/testutil.py | 5 +-- 5 files changed, 42 insertions(+), 24 deletions(-) diff --git a/common/djangoapps/third_party_auth/tests/specs/base.py b/common/djangoapps/third_party_auth/tests/specs/base.py index bff9a595cf..094c9a6653 100644 --- a/common/djangoapps/third_party_auth/tests/specs/base.py +++ b/common/djangoapps/third_party_auth/tests/specs/base.py @@ -6,6 +6,7 @@ import json import mock from contextlib import contextmanager +import django from django import test from django.contrib import auth from django.contrib.auth import models as auth_models @@ -20,6 +21,7 @@ from social_django import views as social_views from lms.djangoapps.commerce.tests import TEST_API_URL from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory +from openedx.tests.util import expected_redirect_url from student import models as student_models from student import views as student_views from student.tests.factories import UserFactory @@ -64,7 +66,7 @@ class IntegrationTestMixin(object): provider_response = self.do_provider_login(try_login_response['Location']) # We should be redirected to the register screen since this account is not linked to an edX account: self.assertEqual(provider_response.status_code, 302) - self.assertEqual(provider_response['Location'], self.url_prefix + self.register_page_url) + self.assertEqual(provider_response['Location'], expected_redirect_url(self.register_page_url, hostname=self.hostname)) register_response = self.client.get(self.register_page_url) tpa_context = register_response.context["data"]["third_party_auth"] self.assertEqual(tpa_context["errorMessage"], None) @@ -94,7 +96,7 @@ class IntegrationTestMixin(object): continue_response = self.client.get(tpa_context["finishAuthUrl"]) # And we should be redirected to the dashboard: self.assertEqual(continue_response.status_code, 302) - self.assertEqual(continue_response['Location'], self.url_prefix + reverse('dashboard')) + self.assertEqual(continue_response['Location'], expected_redirect_url(reverse('dashboard'), hostname=self.hostname)) # Now check that we can login again, whether or not we have yet verified the account: self.client.logout() @@ -115,7 +117,7 @@ class IntegrationTestMixin(object): complete_response = self.do_provider_login(try_login_response['Location']) # We should be redirected to the login screen since this account is not linked to an edX account: self.assertEqual(complete_response.status_code, 302) - self.assertEqual(complete_response['Location'], self.url_prefix + self.login_page_url) + self.assertEqual(complete_response['Location'], expected_redirect_url(self.login_page_url, hostname=self.hostname)) login_response = self.client.get(self.login_page_url) tpa_context = login_response.context["data"]["third_party_auth"] self.assertEqual(tpa_context["errorMessage"], None) @@ -132,7 +134,7 @@ class IntegrationTestMixin(object): continue_response = self.client.get(tpa_context["finishAuthUrl"]) # And we should be redirected to the dashboard: self.assertEqual(continue_response.status_code, 302) - self.assertEqual(continue_response['Location'], self.url_prefix + reverse('dashboard')) + self.assertEqual(continue_response['Location'], expected_redirect_url(reverse('dashboard'), hostname=self.hostname)) # Now check that we can login again: self.client.logout() @@ -161,7 +163,12 @@ class IntegrationTestMixin(object): # required to set the login cookie (it sticks around if the main session times out): if not previous_session_timed_out: self.assertEqual(login_response.status_code, 302) - self.assertEqual(login_response['Location'], self.url_prefix + self.complete_url) + expected_url = expected_redirect_url(self.complete_url, hostname=self.hostname) + # TODO: Remove Django 1.11 upgrade shim + # SHIM: Get rid of this logic post-upgrade + if django.VERSION >= (1, 9): + expected_url = "{}?".format(expected_url) + self.assertEqual(login_response['Location'], expected_url) # And then we should be redirected to the dashboard: login_response = self.client.get(login_response['Location']) self.assertEqual(login_response.status_code, 302) @@ -169,7 +176,7 @@ class IntegrationTestMixin(object): url_expected = reverse('dashboard') else: url_expected = reverse('third_party_inactive_redirect') + '?next=' + reverse('dashboard') - self.assertEqual(login_response['Location'], self.url_prefix + url_expected) + self.assertEqual(login_response['Location'], expected_redirect_url(url_expected, hostname=self.hostname)) # Now we are logged in: dashboard_response = self.client.get(reverse('dashboard')) self.assertEqual(dashboard_response.status_code, 200) diff --git a/common/djangoapps/third_party_auth/tests/specs/test_google.py b/common/djangoapps/third_party_auth/tests/specs/test_google.py index 1c7b0f3589..cd9666a05b 100644 --- a/common/djangoapps/third_party_auth/tests/specs/test_google.py +++ b/common/djangoapps/third_party_auth/tests/specs/test_google.py @@ -6,6 +6,7 @@ from django.conf import settings from django.core.urlresolvers import reverse import json from mock import patch +from openedx.tests.util import expected_redirect_url from social_core.exceptions import AuthException from student.tests.factories import UserFactory from third_party_auth import pipeline @@ -72,7 +73,7 @@ class GoogleOauth2IntegrationTest(base.Oauth2IntegrationTest): response = self.client.get(complete_url) # This should redirect to the custom login/register form: self.assertEqual(response.status_code, 302) - self.assertEqual(response['Location'], 'http://example.none/auth/custom_auth_entry') + self.assertEqual(response['Location'], expected_redirect_url('/auth/custom_auth_entry', hostname='example.none')) response = self.client.get(response['Location']) self.assertEqual(response.status_code, 200) @@ -106,7 +107,7 @@ class GoogleOauth2IntegrationTest(base.Oauth2IntegrationTest): # Now our custom login/registration page must resume the pipeline: response = self.client.get(complete_url) self.assertEqual(response.status_code, 302) - self.assertEqual(response['Location'], 'http://example.none/misc/final-destination') + self.assertEqual(response['Location'], expected_redirect_url('/misc/final-destination', hostname='example.none')) _, strategy = self.get_request_and_strategy() self.assert_social_auth_exists_for_user(created_user, strategy) @@ -133,4 +134,4 @@ class GoogleOauth2IntegrationTest(base.Oauth2IntegrationTest): response = self.client.get(complete_url) # This should redirect to the custom error URL self.assertEqual(response.status_code, 302) - self.assertEqual(response['Location'], 'http://example.none/misc/my-custom-sso-error-page') + self.assertEqual(response['Location'], expected_redirect_url('/misc/my-custom-sso-error-page', hostname='example.none')) diff --git a/common/djangoapps/third_party_auth/tests/specs/test_lti.py b/common/djangoapps/third_party_auth/tests/specs/test_lti.py index 4b2bb1061b..e09428bc30 100644 --- a/common/djangoapps/third_party_auth/tests/specs/test_lti.py +++ b/common/djangoapps/third_party_auth/tests/specs/test_lti.py @@ -2,18 +2,20 @@ Integration tests for third_party_auth LTI auth providers """ import unittest +import django from django.conf import settings from django.contrib.auth.models import User from django.core.urlresolvers import reverse from oauthlib.oauth1.rfc5849 import Client, SIGNATURE_TYPE_BODY +from openedx.tests.util import expected_redirect_url from third_party_auth.tests import testutil FORM_ENCODED = 'application/x-www-form-urlencoded' LTI_CONSUMER_KEY = 'consumer' LTI_CONSUMER_SECRET = 'secret' -LTI_TPA_LOGIN_URL = 'http://testserver/auth/login/lti/' -LTI_TPA_COMPLETE_URL = 'http://testserver/auth/complete/lti/' +LTI_TPA_LOGIN_URL = '/auth/login/lti/' +LTI_TPA_COMPLETE_URL = '/auth/complete/lti/' OTHER_LTI_CONSUMER_KEY = 'settings-consumer' OTHER_LTI_CONSUMER_SECRET = 'secret2' LTI_USER_ID = 'lti_user_id' @@ -29,8 +31,9 @@ class IntegrationTestLTI(testutil.TestCase): def setUp(self): super(IntegrationTestLTI, self).setUp() - self.client.defaults['SERVER_NAME'] = 'testserver' - self.url_prefix = 'http://testserver' + self.hostname = 'testserver' + self.client.defaults['SERVER_NAME'] = self.hostname + self.url_prefix = 'http://{}'.format(self.hostname) self.configure_lti_provider( name='Other Tool Consumer 1', enabled=True, lti_consumer_key='other1', @@ -58,7 +61,7 @@ class IntegrationTestLTI(testutil.TestCase): def test_lti_login(self): # The user initiates a login from an external site (uri, _headers, body) = self.lti.sign( - uri=LTI_TPA_LOGIN_URL, http_method='POST', + uri=self.url_prefix + LTI_TPA_LOGIN_URL, http_method='POST', headers={'Content-Type': FORM_ENCODED}, body={ 'user_id': LTI_USER_ID, @@ -85,27 +88,32 @@ class IntegrationTestLTI(testutil.TestCase): } ) self.assertEqual(ajax_register_response.status_code, 200) - continue_response = self.client.get(LTI_TPA_COMPLETE_URL) + continue_response = self.client.get(self.url_prefix + LTI_TPA_COMPLETE_URL) # The user should be redirected to the finish_auth view which will enroll them. # FinishAuthView.js reads the URL parameters directly from $.url self.assertEqual(continue_response.status_code, 302) self.assertEqual( continue_response['Location'], - 'http://testserver/account/finish_auth/?course_id=my_course_id&enrollment_action=enroll' + expected_redirect_url('/account/finish_auth/?course_id=my_course_id&enrollment_action=enroll') ) # Now check that we can login again self.client.logout() self.verify_user_email(EMAIL) (uri, _headers, body) = self.lti.sign( - uri=LTI_TPA_LOGIN_URL, http_method='POST', + uri=self.url_prefix + LTI_TPA_LOGIN_URL, http_method='POST', headers={'Content-Type': FORM_ENCODED}, body={'user_id': LTI_USER_ID} ) login_2_response = self.client.post(path=uri, content_type=FORM_ENCODED, data=body) # The user should be redirected to the dashboard self.assertEqual(login_2_response.status_code, 302) - self.assertEqual(login_2_response['Location'], LTI_TPA_COMPLETE_URL) + expected_url = expected_redirect_url(LTI_TPA_COMPLETE_URL) + # TODO: Remove Django 1.11 upgrade shim + # SHIM: Get rid of this logic post-upgrade + if django.VERSION >= (1, 9): + expected_url = "{}?".format(expected_url) + self.assertEqual(login_2_response['Location'], expected_url) continue_2_response = self.client.get(login_2_response['Location']) self.assertEqual(continue_2_response.status_code, 302) self.assertTrue(continue_2_response['Location'].endswith(reverse('dashboard'))) @@ -115,12 +123,12 @@ class IntegrationTestLTI(testutil.TestCase): self.assertEqual(user.username, EDX_USER_ID) def test_reject_initiating_login(self): - response = self.client.get(LTI_TPA_LOGIN_URL) + response = self.client.get(self.url_prefix + LTI_TPA_LOGIN_URL) self.assertEqual(response.status_code, 405) # Not Allowed def test_reject_bad_login(self): login_response = self.client.post( - path=LTI_TPA_LOGIN_URL, content_type=FORM_ENCODED, + path=self.url_prefix + LTI_TPA_LOGIN_URL, content_type=FORM_ENCODED, data="invalid=login", ) # The user should be redirected to the login page with an error message @@ -140,7 +148,7 @@ class IntegrationTestLTI(testutil.TestCase): signature_type=SIGNATURE_TYPE_BODY, ) (uri, _headers, body) = lti.sign( - uri=LTI_TPA_LOGIN_URL, http_method='POST', + uri=self.url_prefix + LTI_TPA_LOGIN_URL, http_method='POST', headers={'Content-Type': FORM_ENCODED}, body={ 'user_id': LTI_USER_ID, diff --git a/common/djangoapps/third_party_auth/tests/specs/test_testshib.py b/common/djangoapps/third_party_auth/tests/specs/test_testshib.py index a393f39756..a6f480ce33 100644 --- a/common/djangoapps/third_party_auth/tests/specs/test_testshib.py +++ b/common/djangoapps/third_party_auth/tests/specs/test_testshib.py @@ -13,6 +13,7 @@ from social_django.models import UserSocialAuth from testfixtures import LogCapture from unittest import skip +from openedx.tests.util import expected_redirect_url from third_party_auth.saml import log as saml_log, SapSuccessFactorsIdentityProvider from third_party_auth.tasks import fetch_saml_metadata from third_party_auth.tests import testutil @@ -135,7 +136,7 @@ class TestShibIntegrationTest(SamlIntegrationTestUtilities, IntegrationTestMixin try_login_response = self.client.get(testshib_login_url) # The user should be redirected to back to the login page: self.assertEqual(try_login_response.status_code, 302) - self.assertEqual(try_login_response['Location'], self.url_prefix + self.login_page_url) + self.assertEqual(try_login_response['Location'], expected_redirect_url(self.login_page_url, hostname=self.hostname)) # When loading the login page, the user will see an error message: response = self.client.get(self.login_page_url) self.assertEqual(response.status_code, 200) diff --git a/common/djangoapps/third_party_auth/tests/testutil.py b/common/djangoapps/third_party_auth/tests/testutil.py index 8479aa6346..e47d41d4a0 100644 --- a/common/djangoapps/third_party_auth/tests/testutil.py +++ b/common/djangoapps/third_party_auth/tests/testutil.py @@ -187,8 +187,9 @@ class TestCase(ThirdPartyAuthTestMixin, django.test.TestCase): super(TestCase, self).setUp() # Explicitly set a server name that is compatible with all our providers: # (The SAML lib we use doesn't like the default 'testserver' as a domain) - self.client.defaults['SERVER_NAME'] = 'example.none' - self.url_prefix = 'http://example.none' + self.hostname = 'example.none' + self.client.defaults['SERVER_NAME'] = self.hostname + self.url_prefix = 'http://{}'.format(self.hostname) class SAMLTestCase(TestCase):