From 1a9e2b0e0d8aea12caa8afc63b68dffc12eebd89 Mon Sep 17 00:00:00 2001 From: Matthias Kestenholz Date: Wed, 17 May 2017 11:07:40 +0200 Subject: [PATCH] Add minimal tests --- .editorconfig | 22 ++++++++ .gitignore | 2 + .travis.yml | 8 +-- README.rst | 3 ++ tests/cov.sh | 3 ++ tests/manage.py | 14 ++++++ tests/requirements.txt | 4 ++ tests/testapp/__init__.py | 0 tests/testapp/settings.py | 83 +++++++++++++++++++++++++++++++ tests/testapp/templates/404.html | 5 ++ tests/testapp/templates/base.html | 16 ++++++ tests/testapp/test_authlib.py | 54 ++++++++++++++++++++ tests/testapp/urls.py | 10 ++++ 13 files changed, 220 insertions(+), 4 deletions(-) create mode 100644 .editorconfig create mode 100755 tests/cov.sh create mode 100755 tests/manage.py create mode 100644 tests/requirements.txt create mode 100644 tests/testapp/__init__.py create mode 100644 tests/testapp/settings.py create mode 100644 tests/testapp/templates/404.html create mode 100644 tests/testapp/templates/base.html create mode 100644 tests/testapp/test_authlib.py create mode 100644 tests/testapp/urls.py diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b12c322 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +# top-most EditorConfig file +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 + +# HTML: 2 spaces +[*.html] +indent_size = 2 + +# SCSS: 2 spaces +[*.scss] +indent_size = 2 + +# JS : 2 spaces +[*.js] +indent_size = 2 diff --git a/.gitignore b/.gitignore index f68f7ce..6a15a91 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ _build build dist venv +htmlcov +.coverage diff --git a/.travis.yml b/.travis.yml index fd1c735..26e7aa5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,15 @@ language: python sudo: false python: - - "3.4" - - "2.7" + - "3.5" env: - REQ="Django>=1.8,<1.9" - REQ="Django>=1.9,<1.10" - REQ="Django>=1.10,<1.11" + - REQ="Django>=1.11,<2.0" # command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors install: - - pip install -q $REQ towel==0.8.0 --use-mirrors - - python setup.py -q install + - pip install $REQ pytz requests_oauthlib + - python setup.py install # command to run tests, e.g. python setup.py test script: "cd tests && ./manage.py test testapp" diff --git a/README.rst b/README.rst index 64faf82..42f776e 100644 --- a/README.rst +++ b/README.rst @@ -2,6 +2,9 @@ django-authlib - Authentication utils for Django ================================================ +.. image:: https://travis-ci.org/matthiask/django-authlib.svg?branch=master + :target: https://travis-ci.org/matthiask/django-authlib + authlib is a collection of authentication utilities for implementing passwordless authentication. This is achieved by either sending cryptographically signed links by email, or by fetching the email diff --git a/tests/cov.sh b/tests/cov.sh new file mode 100755 index 0000000..ce9d7c0 --- /dev/null +++ b/tests/cov.sh @@ -0,0 +1,3 @@ +#!/bin/sh +venv/bin/coverage run --branch --include="*authlib/*" --omit="*tests*" ./manage.py test -v 2 testapp +venv/bin/coverage html diff --git a/tests/manage.py b/tests/manage.py new file mode 100755 index 0000000..5e8c6ca --- /dev/null +++ b/tests/manage.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +import os +import sys +from os.path import abspath, dirname + + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testapp.settings") + + sys.path.insert(0, dirname(dirname(abspath(__file__)))) + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..4a07d17 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,4 @@ +Django +pytz +coverage +requests_oauthlib diff --git a/tests/testapp/__init__.py b/tests/testapp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/testapp/settings.py b/tests/testapp/settings.py new file mode 100644 index 0000000..e8daf15 --- /dev/null +++ b/tests/testapp/settings.py @@ -0,0 +1,83 @@ +import os +import warnings + +SITE_ID = 1 + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ':memory:', + } +} + +INSTALLED_APPS = [ + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.staticfiles', + 'django.contrib.messages', + 'testapp', + 'authlib', + 'authlib.admin_oauth', + 'authlib.little_auth', + 'django.contrib.admin', +] + +MEDIA_ROOT = '/media/' +STATIC_URL = '/static/' +BASEDIR = os.path.dirname(__file__) +MEDIA_ROOT = os.path.join(BASEDIR, 'media/') +STATIC_ROOT = os.path.join(BASEDIR, 'static/') +SECRET_KEY = 'supersikret' +LOGIN_REDIRECT_URL = '/?login=1' + +ROOT_URLCONF = 'testapp.urls' +LANGUAGES = (('en', 'English'),) + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +MIDDLEWARE_CLASSES = MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] +# Do not warn about MIDDLEWARE_CLASSES +SILENCED_SYSTEM_CHECKS = ['1_10.W001'] + +try: + # We do not yet care about those. + from django.utils.deprecation import RemovedInDjango21Warning + + warnings.simplefilter('ignore', RemovedInDjango21Warning) +except ImportError: # pragma: no cover + pass + +AUTH_USER_MODEL = 'little_auth.User' +GOOGLE_CLIENT_ID = 'empty' +GOOGLE_CLIENT_SECRET = 'empty' +TWITTER_CLIENT_ID = 'empty' +TWITTER_CLIENT_SECRET = 'empty' +FACEBOOK_CLIENT_ID = 'empty' +FACEBOOK_CLIENT_SECRET = 'empty' +ADMIN_OAUTH_PATTERNS = [ + (r'@example\.com', 'admin@example.com'), +] diff --git a/tests/testapp/templates/404.html b/tests/testapp/templates/404.html new file mode 100644 index 0000000..fad64ec --- /dev/null +++ b/tests/testapp/templates/404.html @@ -0,0 +1,5 @@ +{% extends "base.html" %} + +{% block content %} +

Page not found

+{% endblock %} diff --git a/tests/testapp/templates/base.html b/tests/testapp/templates/base.html new file mode 100644 index 0000000..545c619 --- /dev/null +++ b/tests/testapp/templates/base.html @@ -0,0 +1,16 @@ + + + + {% block title %}testapp{% endblock %} + + + {% if messages %} + + {% endif %} + {% block content %}{% endblock %} + + diff --git a/tests/testapp/test_authlib.py b/tests/testapp/test_authlib.py new file mode 100644 index 0000000..90fbe42 --- /dev/null +++ b/tests/testapp/test_authlib.py @@ -0,0 +1,54 @@ +from django.test import Client, TestCase +from django.utils.translation import deactivate_all + +from authlib.little_auth.models import User + + +def zero_management_form_data(prefix): + return { + '%s-TOTAL_FORMS' % prefix: 0, + '%s-INITIAL_FORMS' % prefix: 0, + '%s-MIN_NUM_FORMS' % prefix: 0, + '%s-MAX_NUM_FORMS' % prefix: 1000, + } + + +def merge_dicts(*dicts): + res = {} + for d in dicts: + res.update(d) + return res + + +class Test(TestCase): + def setUp(self): + self.user = User.objects.create_superuser( + 'admin@example.com', 'blabla') + deactivate_all() + + def login(self): + client = Client() + client.force_login(self.user) + return client + + def test_admin_oauth(self): + client = Client() + + response = client.get('/admin/login/?next=/admin/little_auth/') + self.assertContains( + response, + '' + 'Log in using SSO' + ) + + response = client.get('/admin/__oauth__/?next=/admin/little_auth/') + self.assertEqual(response.status_code, 302) + self.assertIn( + 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code' + '&client_id=empty&redirect_uri=', + response['Location'], + ) + self.assertEqual( + client.session['admin-oauth-next'], + '/admin/little_auth/', + ) diff --git a/tests/testapp/urls.py b/tests/testapp/urls.py new file mode 100644 index 0000000..d00940d --- /dev/null +++ b/tests/testapp/urls.py @@ -0,0 +1,10 @@ +from django.conf.urls import include, url +from django.contrib import admin +from django.shortcuts import render + + +urlpatterns = [ + url(r'', include('authlib.admin_oauth.urls')), + url(r'^admin/', admin.site.urls), + url(r'^404/$', lambda request: render(request, '404.html')), +]