Skip to content

Commit d45a15b

Browse files
committed
Add tests
1 parent 28d564f commit d45a15b

File tree

11 files changed

+278
-10
lines changed

11 files changed

+278
-10
lines changed

.travis.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
sudo: false
2+
language: python
3+
python:
4+
- "2.7"
5+
- "3.4"
6+
- "3.5"
7+
- "3.6"
8+
9+
cache:
10+
directories:
11+
- $HOME/.cache/pip
12+
- $TRAVIS_BUILD_DIR/.tox
13+
14+
install:
15+
- pip install --upgrade pip wheel setuptools
16+
- pip install tox-travis coveralls
17+
18+
branches:
19+
- develop
20+
- master
21+
22+
script: tox
23+
24+
after_success:
25+
- coveralls

README.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
11
## django-rest-invitations
22

3+
4+
[![Build Status](https://travis-ci.org/fmarco/django-rest-invitations.svg?branch=master)](https://travis-ci.org/fmarco/django-rest-invitations)
5+
6+
[![Coverage Status](https://coveralls.io/repos/fmarco/django-rest-invitations/badge.svg?branch=master&service=github)](https://coveralls.io/github/fmarco/django-rest-invitations?branch=master)
7+
38
Rest customizable extension for [django-invitations](https://github.com/bee-keeper/django-invitations)
49

10+
Supported Django versions:
11+
12+
* 2.7
13+
* 3.4
14+
* 3.5
15+
* 3.6
16+
17+
Supported Django versions:
18+
19+
* Django 1.11
520

621
### Requirements
722

@@ -90,11 +105,6 @@ url(r'^', include('rest_invitations.urls'))
90105
- /invitations/accept-invite/`<key>`/ (get)
91106

92107

93-
### TODOS
94-
95-
* Tests
96-
* ...
97-
98108

99109
### Contributions
100110

manage.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env python
2+
import os
3+
os.environ['DJANGO_SETTINGS_MODULE'] = 'test_settings'
4+
5+
from django.core import management
6+
7+
if __name__ == "__main__":
8+
management.execute_from_command_line()

requirements_test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
coverage>=3.7.1

rest_invitations/views.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
permission_classes)
88
from rest_framework.permissions import AllowAny, IsAuthenticated
99
from rest_framework.response import Response
10-
from rest_framework.reverse import reverse
1110

1211
from .app_settings import (CREATE_AND_SEND_URL, SEND_MULTIPLE_URL, SEND_URL,
1312
InvitationBulkWriteSerializer, InvitationModel,
@@ -24,7 +23,7 @@ class InvitationViewSet(
2423
permission_classes = [IsAuthenticated]
2524

2625
def get_serializer_class(self):
27-
if self.action in ['list', 'retrive']:
26+
if self.action in ['list', 'retrieve']:
2827
return InvitationReadSerializer
2928
elif self.action == 'send_multiple':
3029
return InvitationBulkWriteSerializer

setup.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
keywords=['django', 'invitation', 'django-allauth', 'invite', 'rest', 'django-rest-framework', 'drf', 'invitations'],
1313
zip_safe=False,
1414
install_requires=[
15-
'Django>=1.8.0',
16-
'djangorestframework>=3.1.0',
17-
'django-invitations==1.9.1'
15+
'djangorestframework>=3.7.7',
16+
'django-invitations==1.9.2'
1817
],
1918
include_package_data=True,
2019
classifiers=[

test_settings.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# -*- coding: utf-8 -*-
2+
import django
3+
4+
SECRET_KEY = 'sosecret'
5+
SITE_ID = 1
6+
7+
DATABASES = {
8+
'default': {
9+
'ENGINE': 'django.db.backends.sqlite3',
10+
'NAME': ':memory:',
11+
}
12+
}
13+
14+
ROOT_URLCONF = 'test_urls'
15+
16+
if django.VERSION >= (1, 8):
17+
TEMPLATES = [
18+
{
19+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
20+
'DIRS': [],
21+
'APP_DIRS': True,
22+
'OPTIONS': {
23+
'context_processors': [
24+
'django.template.context_processors.debug',
25+
'django.template.context_processors.request',
26+
'django.contrib.auth.context_processors.auth',
27+
'django.contrib.messages.context_processors.messages'
28+
],
29+
},
30+
},
31+
]
32+
else:
33+
TEMPLATE_CONTEXT_PROCESSORS = (
34+
"django.contrib.auth.context_processors.auth",
35+
"django.core.context_processors.debug",
36+
"django.core.context_processors.i18n",
37+
"django.core.context_processors.media",
38+
"django.core.context_processors.static",
39+
"django.core.context_processors.request",
40+
"django.contrib.messages.context_processors.messages",
41+
)
42+
43+
MIDDLEWARE_CLASSES = (
44+
'django.contrib.sessions.middleware.SessionMiddleware',
45+
'django.middleware.common.CommonMiddleware',
46+
'django.middleware.csrf.CsrfViewMiddleware',
47+
'django.contrib.auth.middleware.AuthenticationMiddleware',
48+
'django.contrib.messages.middleware.MessageMiddleware',
49+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
50+
)
51+
52+
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
53+
54+
INSTALLED_APPS = (
55+
'django.contrib.auth',
56+
'django.contrib.admin',
57+
'django.contrib.contenttypes',
58+
'django.contrib.sessions',
59+
'django.contrib.sites',
60+
'django.contrib.messages',
61+
'invitations',
62+
'rest_framework',
63+
'rest_invitations'
64+
)
65+
AUTHENTICATION_BACKENDS = (
66+
'django.contrib.auth.backends.ModelBackend',
67+
)

test_urls.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# -*- coding: utf-8 -*-
2+
from django.conf.urls import include, url
3+
from django.contrib import admin
4+
5+
6+
urlpatterns = [
7+
url(r'^admin/', admin.site.urls),
8+
url(r'^', include('rest_invitations.urls'))
9+
]

tests/__init__.py

Whitespace-only changes.

tests/tests.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
from django.contrib.auth import get_user_model
2+
from django.core import mail
3+
from django.urls import reverse
4+
from django.utils import timezone
5+
from invitations.utils import get_invitation_model
6+
from rest_framework import status
7+
from rest_framework.test import APITestCase
8+
9+
User = get_user_model()
10+
Invitation = get_invitation_model()
11+
12+
13+
class TestInvitationAPI(APITestCase):
14+
15+
@classmethod
16+
def setUpClass(cls):
17+
super(TestInvitationAPI, cls).setUpClass()
18+
cls.user = User.objects.create_user(
19+
email='[email protected]', username='test_user', password='test'
20+
)
21+
22+
def test_invitation_send(self):
23+
self.assertEqual(len(mail.outbox), 0)
24+
invitation = Invitation.create(email='[email protected]')
25+
url = reverse('invitation-send', kwargs={'pk': invitation.pk})
26+
response = self.client.post(url, format='json')
27+
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
28+
self.assertEqual(len(mail.outbox), 0)
29+
self.client.login(username=self.user.username, password='test')
30+
url = reverse('invitation-send', kwargs={'pk': invitation.pk})
31+
response = self.client.post(url, format='json')
32+
self.assertEqual(response.status_code, status.HTTP_200_OK)
33+
self.assertEqual(len(mail.outbox), 1)
34+
35+
def test_invitation_create_and_send(self):
36+
self.assertEqual(len(mail.outbox), 0)
37+
self.assertEqual(Invitation.objects.count(), 0)
38+
url = reverse('invitation-create-and-send')
39+
data = {}
40+
response = self.client.post(url, data, format='json')
41+
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
42+
self.assertEqual(Invitation.objects.count(), 0)
43+
self.client.login(username=self.user.username, password='test')
44+
response = self.client.post(url, data, format='json')
45+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
46+
self.assertEqual(Invitation.objects.count(), 0)
47+
self.assertEqual(len(mail.outbox), 0)
48+
data = {'email': '[email protected]'}
49+
response = self.client.post(url, data, format='json')
50+
self.assertEqual(response.status_code, status.HTTP_200_OK)
51+
self.assertEqual(len(mail.outbox), 1)
52+
self.assertEqual(Invitation.objects.count(), 1)
53+
54+
def test_invitation_send_multiple(self):
55+
self.assertEqual(len(mail.outbox), 0)
56+
self.assertEqual(Invitation.objects.count(), 0)
57+
url = reverse('invitation-send-multiple')
58+
data = {}
59+
response = self.client.post(url, data, format='json')
60+
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
61+
self.assertEqual(Invitation.objects.count(), 0)
62+
self.client.login(username=self.user.username, password='test')
63+
response = self.client.post(url, data, format='json')
64+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
65+
self.assertEqual(Invitation.objects.count(), 0)
66+
self.assertEqual(len(mail.outbox), 0)
67+
data = {'email': []}
68+
response = self.client.post(url, data, format='json')
69+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
70+
self.assertEqual(len(mail.outbox), 0)
71+
self.assertEqual(Invitation.objects.count(), 0)
72+
data = {'email': ['[email protected]', '[email protected]']}
73+
response = self.client.post(url, data, format='json')
74+
self.assertEqual(response.status_code, status.HTTP_200_OK)
75+
self.assertEqual(len(mail.outbox), 2)
76+
self.assertEqual(Invitation.objects.count(), 2)
77+
data = {'email': ['[email protected]', '[email protected]']}
78+
response = self.client.post(url, data, format='json')
79+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
80+
self.assertEqual(len(mail.outbox), 2)
81+
self.assertEqual(Invitation.objects.count(), 2)
82+
data = {'email': ['[email protected]']}
83+
response = self.client.post(url, data, format='json')
84+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
85+
self.assertEqual(len(mail.outbox), 2)
86+
self.assertEqual(Invitation.objects.count(), 2)
87+
data = {'email': ['[email protected]']}
88+
response = self.client.post(url, data, format='json')
89+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
90+
self.assertEqual(len(mail.outbox), 2)
91+
self.assertEqual(Invitation.objects.count(), 2)
92+
93+
def test_invitation_accept(self):
94+
invitation = Invitation.create(
95+
96+
inviter=self.user
97+
)
98+
invitation_pk = invitation.pk
99+
invitation.sent = timezone.now()
100+
invitation.save()
101+
url = reverse('invitations:accept-invite', kwargs={'key': 'something'})
102+
data = {}
103+
response = self.client.post(url, data, format='json')
104+
self.assertEqual(response.status_code, status.HTTP_410_GONE)
105+
self.assertFalse(invitation.accepted)
106+
url = reverse(
107+
'invitations:accept-invite',
108+
kwargs={'key': invitation.key}
109+
)
110+
response = self.client.post(url, data, format='json')
111+
self.assertEqual(response.status_code, status.HTTP_200_OK)
112+
invitation = Invitation.objects.get(pk=invitation_pk)
113+
self.assertTrue(invitation.accepted)
114+
response = self.client.post(url, data, format='json')
115+
self.assertEqual(response.status_code, status.HTTP_410_GONE)
116+
117+
def tearDown(self):
118+
self.client.logout()

tox.ini

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[tox]
2+
envlist =
3+
py27-django111
4+
py34-django111
5+
py35-django111
6+
py36-django111
7+
flake8
8+
isort
9+
10+
[testenv]
11+
setenv =
12+
PYTHONWARNINGS = all
13+
deps =
14+
-rrequirements_test.txt
15+
django111: Django>=1.11,<2.0
16+
commands =
17+
python -V
18+
coverage run manage.py test --settings=test_settings
19+
coverage report
20+
21+
[testenv:flake8]
22+
skip_install = True
23+
deps=flake8
24+
commands=flake8 rest_invitations tests --exclude=migrations
25+
26+
[testenv:isort]
27+
deps = isort
28+
commands = isort -c -rc -df rest_invitations tests
29+
skip_install = true
30+
31+
[coverage:run]
32+
include = rest_invitations*

0 commit comments

Comments
 (0)