Skip to content

Commit

Permalink
Enable knox tests and split tests (#83)
Browse files Browse the repository at this point in the history
Enable knox tests and split tests
  • Loading branch information
st4lk committed Mar 22, 2019
1 parent b60af8f commit 648d1c4
Show file tree
Hide file tree
Showing 10 changed files with 593 additions and 531 deletions.
7 changes: 7 additions & 0 deletions example_project/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@

# DRF settings

SIMPLE_JWT = {
'AUTH_TOKEN_CLASSES': (
'rest_framework_simplejwt.tokens.AccessToken',
'rest_framework_simplejwt.tokens.SlidingToken',
),
}

# social auth settings
# valid redirect domain for all apps: http://restsocialexample.com:8000/
SOCIAL_AUTH_FACEBOOK_KEY = '295137440610143'
Expand Down
7 changes: 6 additions & 1 deletion example_project/config/settings_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
" Settings for tests. "
from .settings import *
INSTALLED_APPS = []

from .settings import * # NOQA: E402

# Databases
DATABASES = {
Expand All @@ -8,3 +10,6 @@
'NAME': ':memory:',
}
}

if 'knox' not in INSTALLED_APPS:
INSTALLED_APPS += ('knox', )
60 changes: 60 additions & 0 deletions tests/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import json

from httpretty import HTTPretty
from social_core.backends.utils import load_backends
from social_core.tests.backends.test_facebook import FacebookOAuth2Test
from social_core.tests.backends.test_twitter import TwitterOAuth1Test
from social_core.utils import module_member

from rest_social_auth import views


# don't run third party tests
for attr in (attr for attr in dir(FacebookOAuth2Test) if attr.startswith('test_')):
delattr(FacebookOAuth2Test, attr)
for attr in (attr for attr in dir(TwitterOAuth1Test) if attr.startswith('test_')):
delattr(TwitterOAuth1Test, attr)


class RestSocialMixin(object):
def setUp(self):
HTTPretty.enable()
Backend = module_member(self.backend_path)
self.strategy = views.load_strategy()
self.backend = Backend(self.strategy, redirect_uri=self.complete_url)
self.name = self.backend.name.upper().replace('-', '_')
self.complete_url = self.strategy.build_absolute_uri(
self.raw_complete_url.format(self.backend.name)
)
backends = (self.backend_path, )
load_backends(backends, force_load=True)

user_data_body = json.loads(self.user_data_body)
self.email = 'example@mail.com'
user_data_body['email'] = self.email
self.user_data_body = json.dumps(user_data_body)

self.do_rest_login()

def tearDown(self):
HTTPretty.disable()
HTTPretty.reset()
self.backend = None
self.strategy = None
self.name = None
self.complete_url = None


class BaseFacebookAPITestCase(RestSocialMixin, FacebookOAuth2Test):

def do_rest_login(self):
start_url = self.backend.start().url
self.auth_handlers(start_url)


class BaseTwitterApiTestCase(RestSocialMixin, TwitterOAuth1Test):

def do_rest_login(self):
self.request_token_handler()
start_url = self.backend.start().url
self.auth_handlers(start_url)
89 changes: 89 additions & 0 deletions tests/test_jwt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from django.test import modify_settings
from django.urls import reverse
from rest_framework.test import APITestCase
from rest_framework_jwt.settings import api_settings as jwt_api_settings
from social_core.utils import parse_qs

from .base import BaseFacebookAPITestCase, BaseTwitterApiTestCase


jwt_modify_settings = dict(
INSTALLED_APPS={
'remove': [
'django.contrib.sessions',
'rest_framework.authtoken',
'knox',
]
},
MIDDLEWARE_CLASSES={
'remove': [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
],
}
)


class TestSocialAuth1JWT(APITestCase, BaseTwitterApiTestCase):

@modify_settings(INSTALLED_APPS={'remove': ['rest_framework.authtoken', ]})
def test_login_social_oauth1_jwt(self):
"""
Currently oauth1 works only if session is enabled.
Probably it is possible to make it work without session, but
it will be needed to change the logic in python-social-auth.
"""
resp = self.client.post(
reverse('login_social_jwt_user'), data={'provider': 'twitter'})
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.data, parse_qs(self.request_token_body))
resp = self.client.post(reverse('login_social_jwt_user'), data={
'provider': 'twitter',
'oauth_token': 'foobar',
'oauth_verifier': 'overifier'
})
self.assertEqual(resp.status_code, 200)


class TestSocialAuth2JWT(APITestCase, BaseFacebookAPITestCase):

@modify_settings(**jwt_modify_settings)
def _check_login_social_jwt_only(self, url, data):
jwt_decode_handler = jwt_api_settings.JWT_DECODE_HANDLER
resp = self.client.post(url, data)
self.assertEqual(resp.status_code, 200)
# check token valid
jwt_data = jwt_decode_handler(resp.data['token'])
self.assertEqual(jwt_data['email'], self.email)

@modify_settings(**jwt_modify_settings)
def _check_login_social_jwt_user(self, url, data):
jwt_decode_handler = jwt_api_settings.JWT_DECODE_HANDLER
resp = self.client.post(url, data)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.data['email'], self.email)
# check token valid
jwt_data = jwt_decode_handler(resp.data['token'])
self.assertEqual(jwt_data['email'], self.email)

def test_login_social_jwt_only(self):
self._check_login_social_jwt_only(
reverse('login_social_jwt'),
data={'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw'})

def test_login_social_jwt_only_provider_in_url(self):
self._check_login_social_jwt_only(
reverse('login_social_jwt', kwargs={'provider': 'facebook'}),
data={'code': '3D52VoM1uiw94a1ETnGvYlCw'})

def test_login_social_jwt_user(self):
self._check_login_social_jwt_user(
reverse('login_social_jwt_user'),
data={'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw'})

def test_login_social_jwt_user_provider_in_url(self):
self._check_login_social_jwt_user(
reverse('login_social_jwt_user', kwargs={'provider': 'facebook'}),
data={'code': '3D52VoM1uiw94a1ETnGvYlCw'},
)
66 changes: 66 additions & 0 deletions tests/test_knox.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from django.urls import reverse
from knox.auth import TokenAuthentication as KnoxTokenAuthentication
from rest_framework.test import APITestCase
from social_core.utils import parse_qs

from .base import BaseFacebookAPITestCase, BaseTwitterApiTestCase


class TestSocialAuth1Knox(APITestCase, BaseTwitterApiTestCase):

def test_login_social_oauth1_knox(self):
"""
Currently oauth1 works only if session is enabled.
Probably it is possible to make it work without session, but
it will be needed to change the logic in python-social-auth.
"""
resp = self.client.post(
reverse('login_social_knox_user'), data={'provider': 'twitter'})
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.data, parse_qs(self.request_token_body))
resp = self.client.post(reverse('login_social_knox_user'), data={
'provider': 'twitter',
'oauth_token': 'foobar',
'oauth_verifier': 'overifier'
})
self.assertEqual(resp.status_code, 200)


class TestSocialAuth2Knox(APITestCase, BaseFacebookAPITestCase):

def _check_login_social_knox_only(self, url, data):
resp = self.client.post(url, data)
self.assertEqual(resp.status_code, 200)
# check token valid
knox_auth = KnoxTokenAuthentication()
user, auth_data = knox_auth.authenticate_credentials(resp.data['token'].encode('utf8'))
self.assertEqual(user.email, self.email)

def _check_login_social_knox_user(self, url, data):
resp = self.client.post(url, data)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.data['email'], self.email)
# check token valid
knox_auth = KnoxTokenAuthentication()
user, auth_data = knox_auth.authenticate_credentials(resp.data['token'].encode('utf8'))
self.assertEqual(user.email, self.email)

def test_login_social_knox_only(self):
self._check_login_social_knox_only(
reverse('login_social_knox'),
data={'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw'})

def test_login_social_knox_only_provider_in_url(self):
self._check_login_social_knox_only(
reverse('login_social_knox', kwargs={'provider': 'facebook'}),
data={'code': '3D52VoM1uiw94a1ETnGvYlCw'})

def test_login_social_knox_user(self):
self._check_login_social_knox_user(
reverse('login_social_knox_user'),
data={'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw'})

def test_login_social_knox_user_provider_in_url(self):
self._check_login_social_knox_user(
reverse('login_social_knox_user', kwargs={'provider': 'facebook'}),
data={'code': '3D52VoM1uiw94a1ETnGvYlCw'})
134 changes: 134 additions & 0 deletions tests/test_session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
try:
from urlparse import parse_qsl, urlparse
except ImportError:
# python 3
from urllib.parse import parse_qsl, urlparse

from mock import patch
from django.urls import reverse
from django.contrib.auth import get_user_model
from django.test import modify_settings
from django.test.utils import override_settings
from rest_framework.test import APITestCase
from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly
from httpretty import HTTPretty
from social_core.utils import parse_qs

from .base import BaseFacebookAPITestCase, BaseTwitterApiTestCase


session_modify_settings = dict(
INSTALLED_APPS={
'remove': [
'rest_framework.authtoken',
'knox',
]
},
)


class TestSocialAuth1(APITestCase, BaseTwitterApiTestCase):

@modify_settings(**session_modify_settings)
def test_login_social_oauth1_session(self):
resp = self.client.post(
reverse('login_social_session'), data={'provider': 'twitter'})
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.data, parse_qs(self.request_token_body))
resp = self.client.post(reverse('login_social_session'), data={
'provider': 'twitter',
'oauth_token': 'foobar',
'oauth_verifier': 'overifier'
})
self.assertEqual(resp.status_code, 200)


class TestSocialAuth2(APITestCase, BaseFacebookAPITestCase):

@modify_settings(**session_modify_settings)
def _check_login_social_session(self, url, data):
resp = self.client.post(url, data)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.data['email'], self.email)
# check cookies are set
self.assertTrue('sessionid' in resp.cookies)
# check user is created
self.assertTrue(
get_user_model().objects.filter(email=self.email).exists())

def test_login_social_session(self):
self._check_login_social_session(
reverse('login_social_session'),
{'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw'})

def test_login_social_session_provider_in_url(self):
self._check_login_social_session(
reverse('login_social_session', kwargs={'provider': 'facebook'}),
{'code': '3D52VoM1uiw94a1ETnGvYlCw'})

def test_no_provider_session(self):
resp = self.client.post(
reverse('login_social_session'),
{'code': '3D52VoM1uiw94a1ETnGvYlCw'})
self.assertEqual(resp.status_code, 400)

def test_unknown_provider_session(self):
resp = self.client.post(
reverse('login_social_session', kwargs={'provider': 'unknown'}),
{'code': '3D52VoM1uiw94a1ETnGvYlCw'})
self.assertEqual(resp.status_code, 404)

def test_login_social_http_origin(self):
resp = self.client.post(
reverse('login_social_session'),
data={'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw'},
HTTP_ORIGIN="http://frontend.com")
self.assertEqual(resp.status_code, 200)
url_params = dict(parse_qsl(urlparse(HTTPretty.latest_requests[0].path).query))
self.assertEqual(url_params['redirect_uri'], "http://frontend.com/")

@override_settings(REST_SOCIAL_OAUTH_ABSOLUTE_REDIRECT_URI='http://myproject.com/')
def test_login_absolute_redirect(self):
resp = self.client.post(
reverse('login_social_session'),
data={'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw'})
self.assertEqual(resp.status_code, 200)
url_params = dict(parse_qsl(urlparse(HTTPretty.latest_requests[0].path).query))
self.assertEqual('http://myproject.com/', url_params['redirect_uri'])

@override_settings(REST_SOCIAL_OAUTH_ABSOLUTE_REDIRECT_URI='http://myproject.com/')
def test_login_manual_redirect(self):
resp = self.client.post(
reverse('login_social_session'),
data={'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw',
'redirect_uri': 'http://manualdomain.com/'})
self.assertEqual(resp.status_code, 200)
url_params = dict(parse_qsl(urlparse(HTTPretty.latest_requests[0].path).query))
self.assertEqual('http://manualdomain.com/', url_params['redirect_uri'])

@patch('rest_framework.views.APIView.permission_classes')
def test_login_social_session_model_permission(self, m_permission_classes):
setattr(m_permission_classes, '__get__', lambda *args, **kwargs: (DjangoModelPermissionsOrAnonReadOnly, ))
self._check_login_social_session(
reverse('login_social_session'),
{'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw'})


class TestSocialAuth2Error(APITestCase, BaseFacebookAPITestCase):
access_token_status = 400

def test_login_oauth_provider_error(self):
resp = self.client.post(
reverse('login_social_session'),
data={'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw'})
self.assertEqual(resp.status_code, 400)


class TestSocialAuth2HTTPError(APITestCase, BaseFacebookAPITestCase):
access_token_status = 401

def test_login_oauth_provider_http_error(self):
resp = self.client.post(
reverse('login_social_session'),
data={'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw'})
self.assertEqual(resp.status_code, 400)
Loading

0 comments on commit 648d1c4

Please sign in to comment.