django-allauth-cas/tests/test_views.py
Aurélien Delobelle 049cf22b42 Renew on already authenticated + Misc tests
Renew paramater:
- By default, CAS client will use renew parameter if user already
authenticates via a CAS server. If always False, he can't
reauthenticate on a CAS server due to the single sign-on CAS feature
(except if he logouts of CAS on his own).

Tests:
- patch_cas_reponse now returns a correct CAS client taking into
account the version attribute of the CAS adapter.
- Some moves happens between testcases et al.
- Delete old and now unused fake CAS client classes.
2017-07-28 15:31:37 +02:00

256 lines
7.9 KiB
Python

# -*- coding: utf-8 -*-
try:
from unittest.mock import patch
except ImportError:
from mock import patch
import django
from django.test import RequestFactory, override_settings
from allauth_cas.exceptions import CASAuthenticationError
from allauth_cas.test.testcases import CASTestCase, CASViewTestCase
from allauth_cas.views import CASView
from .example.views import ExampleCASAdapter
if django.VERSION >= (1, 10):
from django.urls import reverse
else:
from django.core.urlresolvers import reverse
class CASAdapterTests(CASTestCase):
def setUp(self):
factory = RequestFactory()
self.request = factory.get('/path/')
self.request.session = {}
self.adapter = ExampleCASAdapter(self.request)
def test_get_service_url(self):
"""
Service url (used by CAS client) is the callback url.
"""
expected = 'http://testserver/accounts/theid/login/callback/'
service_url = self.adapter.get_service_url(self.request)
self.assertEqual(expected, service_url)
def test_get_service_url_keep_next(self):
"""
Current GET paramater next is appended on service url.
"""
expected = (
'http://testserver/accounts/theid/login/callback/?next=%2Fnext%2F'
)
factory = RequestFactory()
request = factory.get('/path/', {'next': '/next/'})
adapter = ExampleCASAdapter(request)
service_url = adapter.get_service_url(request)
self.assertEqual(expected, service_url)
def test_get_callback_url(self):
expected = '/accounts/theid/login/callback/'
callback_url = self.adapter.get_callback_url(self.request)
self.assertEqual(expected, callback_url)
def test_get_callback_url_with_kwargs(self):
expected = (
'/accounts/theid/login/callback/?next=%2Fpath%2F'
)
callback_url = self.adapter.get_callback_url(self.request, **{
'next': '/path/',
})
self.assertEqual(expected, callback_url)
def test_renew(self):
"""
From an anonymous request, renew is False to let using the single
sign-on.
"""
self.assertFalse(self.adapter.renew)
def test_renew_authenticated(self):
"""
If user has been authenticated to the application through CAS, and
tries to reauthenticate, renew is set to True to opt-out the single
sign-on.
"""
r = self.client_cas_login(self.client)
adapter = ExampleCASAdapter(r.wsgi_request)
self.assertTrue(adapter.renew)
class CASViewTests(CASViewTestCase):
class BasicCASView(CASView):
def dispatch(self, request, *args, **kwargs):
return self
def setUp(self):
factory = RequestFactory()
self.request = factory.get('/path/')
self.request.session = {}
self.cas_view = self.BasicCASView.adapter_view(ExampleCASAdapter)
def test_adapter_view(self):
"""
adapter_view prepares the func view from a class view.
"""
view = self.cas_view(
self.request,
'arg1', 'arg2',
kwarg1='kwarg1', kwarg2='kwarg2',
)
self.assertIsInstance(view, CASView)
self.assertEqual(view.request, view.request)
self.assertTupleEqual(view.args, ('arg1', 'arg2'))
self.assertDictEqual(view.kwargs, {
'kwarg1': 'kwarg1',
'kwarg2': 'kwarg2',
})
self.assertIsInstance(view.adapter, ExampleCASAdapter)
@patch('allauth_cas.views.cas.CASClient')
@override_settings(SOCIALACCOUNT_PROVIDERS={
'theid': {
'AUTH_PARAMS': {'key': 'value'},
},
})
def test_get_client(self, mock_casclient_class):
"""
get_client returns a CAS client, configured from settings.
"""
view = self.cas_view(self.request)
view.get_client(self.request)
mock_casclient_class.assert_called_once_with(
service_url='http://testserver/accounts/theid/login/callback/',
server_url='https://server.cas',
version=2,
renew=False,
extra_login_params={'key': 'value'},
)
def test_render_error_on_failure(self):
"""
A common login failure page is rendered if CASAuthenticationError is
raised by dispatch.
"""
def dispatch_raise(self, request):
raise CASAuthenticationError("failure")
with patch.object(self.BasicCASView, 'dispatch', dispatch_raise):
resp = self.cas_view(self.request)
self.assertLoginFailure(resp)
class CASLoginViewTests(CASViewTestCase):
def test_reverse(self):
"""
Login view name is "{provider_id}_login".
"""
url = reverse('theid_login')
self.assertEqual('/accounts/theid/login/', url)
def test_execute(self):
"""
Login view redirects to the CAS server login url.
Service is the callback url, as absolute uri.
"""
r = self.client.get('/accounts/theid/login/')
expected = (
'https://server.cas/login?service=http%3A%2F%2Ftestserver%2F'
'accounts%2Ftheid%2Flogin%2Fcallback%2F'
)
self.assertRedirects(r, expected, fetch_redirect_response=False)
def test_execute_keep_next(self):
"""
Current GET parameter 'next' is kept on service url.
"""
r = self.client.get('/accounts/theid/login/?next=/path/')
expected = (
'https://server.cas/login?service=http%3A%2F%2Ftestserver%2F'
'accounts%2Ftheid%2Flogin%2Fcallback%2F%3Fnext%3D%252Fpath%252F'
)
self.assertRedirects(r, expected, fetch_redirect_response=False)
class CASCallbackViewTests(CASViewTestCase):
def test_reverse(self):
"""
Callback view name is "{provider_id}_callback".
"""
url = reverse('theid_callback')
self.assertEqual('/accounts/theid/login/callback/', url)
def test_ticket_valid(self):
"""
If ticket is valid, the user is logged in.
"""
self.patch_cas_response(username='username', valid_ticket='123456')
r = self.client.get('/accounts/theid/login/callback/', {
'ticket': '123456',
})
self.assertLoginSuccess(r)
def test_ticket_invalid(self):
"""
Login failure page is returned if the ticket is invalid.
"""
self.patch_cas_response(username='username', valid_ticket='123456')
r = self.client.get('/accounts/theid/login/callback/', {
'ticket': '000000',
})
self.assertLoginFailure(r)
def test_ticket_missing(self):
"""
Login failure page is returned if request lacks a ticket.
"""
self.patch_cas_response(username='username', valid_ticket='123456')
r = self.client.get('/accounts/theid/login/callback/')
self.assertLoginFailure(r)
class CASLogoutViewTests(CASViewTestCase):
def test_reverse(self):
"""
Callback view name is "{provider_id}_logout".
"""
url = reverse('theid_logout')
self.assertEqual('/accounts/theid/logout/', url)
def test_execute(self):
"""
Logout view redirects to the CAS server logout url.
Service is a url to here, as absolute uri.
"""
r = self.client.get('/accounts/theid/logout/')
expected = 'https://server.cas/logout?url=http%3A%2F%2Ftestserver%2F'
self.assertRedirects(r, expected, fetch_redirect_response=False)
def test_execute_with_next(self):
"""
GET parameter 'next' is set as service url.
"""
r = self.client.get('/accounts/theid/logout/?next=/path/')
expected = (
'https://server.cas/logout?url=http%3A%2F%2Ftestserver%2Fpath%2F'
)
self.assertRedirects(r, expected, fetch_redirect_response=False)