django-allauth-cas/tests/test_views.py
2024-01-25 14:33:24 +00:00

259 lines
7.9 KiB
Python

try:
from unittest.mock import patch
except ImportError:
from unittest.mock import patch
from django.test import RequestFactory, override_settings
from django.urls import reverse
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
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_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, self.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 setUp(self):
self.client.get("/accounts/theid/login/")
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)
def test_attributes_is_none(self):
"""
Without extra attributes, CASClientV2 of python-cas returns None.
"""
self.patch_cas_response(
username="username", valid_ticket="123456", attributes=None
)
r = self.client.get(
"/accounts/theid/login/callback/",
{
"ticket": "123456",
},
)
self.assertLoginSuccess(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)