2017-01-11 01:53:10 +03:00
|
|
|
import json
|
|
|
|
|
2018-05-16 11:45:09 +03:00
|
|
|
from django.core.management import call_command
|
2018-02-14 21:36:00 +03:00
|
|
|
from django.test import TestCase, Client, RequestFactory
|
|
|
|
from django.core.urlresolvers import reverse
|
2017-06-16 20:45:45 +03:00
|
|
|
from django.contrib.auth.models import Group, Permission
|
2018-02-14 21:36:00 +03:00
|
|
|
from rest_framework import exceptions
|
2016-11-19 01:09:08 +03:00
|
|
|
|
2018-02-14 21:36:00 +03:00
|
|
|
from pulseapi.settings import API_VERSION_LIST
|
2017-06-16 20:45:45 +03:00
|
|
|
from pulseapi.users.models import EmailUser
|
2018-04-26 22:13:17 +03:00
|
|
|
from pulseapi.users.factory import BasicEmailUserFactory
|
|
|
|
from pulseapi.profiles.factory import BasicUserProfileFactory
|
|
|
|
from pulseapi.creators.factory import EntryCreatorFactory
|
2018-03-15 20:16:59 +03:00
|
|
|
from pulseapi.entries.factory import EntryFactory
|
2018-02-14 21:36:00 +03:00
|
|
|
from pulseapi.versioning import PulseAPIVersioning
|
2017-05-03 21:06:26 +03:00
|
|
|
|
2017-06-16 20:45:45 +03:00
|
|
|
from pulseapi.utility.userpermissions import (
|
|
|
|
is_staff_address,
|
|
|
|
assign_group_policy,
|
|
|
|
add_user_to_main_site,
|
|
|
|
)
|
2017-05-03 21:06:26 +03:00
|
|
|
|
2017-08-15 01:27:30 +03:00
|
|
|
|
2017-10-19 20:41:27 +03:00
|
|
|
CONTENT_TYPE_JSON = 'application/json'
|
|
|
|
|
|
|
|
|
2017-06-16 20:45:45 +03:00
|
|
|
def setup_groups():
|
|
|
|
staff, created = Group.objects.get_or_create(name='staff')
|
2018-03-15 20:16:59 +03:00
|
|
|
moderator, created = Group.objects.get_or_create(name='moderator')
|
2017-05-03 21:06:26 +03:00
|
|
|
|
2018-03-15 20:16:59 +03:00
|
|
|
add_entry = Permission.objects.get(codename='add_entry')
|
|
|
|
change_entry = Permission.objects.get(codename='change_entry')
|
|
|
|
delete_entry = Permission.objects.get(codename='delete_entry')
|
2017-06-16 20:45:45 +03:00
|
|
|
|
2018-03-15 20:16:59 +03:00
|
|
|
staff.permissions.add(add_entry, change_entry, delete_entry)
|
2017-06-16 20:45:45 +03:00
|
|
|
staff.save()
|
|
|
|
|
2018-03-15 20:16:59 +03:00
|
|
|
moderator.permissions.add(add_entry, change_entry, delete_entry)
|
|
|
|
moderator.save()
|
2017-06-16 20:45:45 +03:00
|
|
|
|
|
|
|
|
2017-09-29 22:23:50 +03:00
|
|
|
def setup_entries(test, creator_users):
|
|
|
|
test.entries = []
|
|
|
|
test.creators = []
|
|
|
|
|
|
|
|
for i in range(2):
|
|
|
|
entry = EntryFactory()
|
2017-06-16 20:45:45 +03:00
|
|
|
entry.save()
|
|
|
|
|
2018-04-26 22:13:17 +03:00
|
|
|
creators = [BasicUserProfileFactory(use_custom_name=True)]
|
2017-09-29 22:23:50 +03:00
|
|
|
if creator_users and len(creator_users) > i:
|
2017-10-10 21:21:37 +03:00
|
|
|
# If we were passed in users, create a creator attached to a user profile
|
2017-10-19 20:41:27 +03:00
|
|
|
for user in creator_users:
|
2018-04-26 22:13:17 +03:00
|
|
|
creators.append(user.profile)
|
2017-09-29 22:23:50 +03:00
|
|
|
for creator in creators:
|
|
|
|
creator.save()
|
|
|
|
# Connect the creator with the entry
|
2018-04-26 22:13:17 +03:00
|
|
|
EntryCreatorFactory(entry=entry, profile=creator)
|
2017-09-29 22:23:50 +03:00
|
|
|
|
|
|
|
test.creators.extend(creators)
|
|
|
|
test.entries.append(entry)
|
|
|
|
|
|
|
|
|
|
|
|
def setup_users_with_profiles(test):
|
2017-10-03 23:47:56 +03:00
|
|
|
users = []
|
2018-04-26 22:13:17 +03:00
|
|
|
profiles = [
|
|
|
|
BasicUserProfileFactory(active=True, use_custom_name=(i % 2 == 0))
|
|
|
|
for i in range(3)
|
|
|
|
]
|
2017-10-03 23:47:56 +03:00
|
|
|
for profile in profiles:
|
2018-04-26 22:13:17 +03:00
|
|
|
user = BasicEmailUserFactory(profile=profile)
|
2017-10-03 23:47:56 +03:00
|
|
|
users.append(user)
|
2017-09-29 22:23:50 +03:00
|
|
|
|
|
|
|
test.users_with_profiles = users
|
|
|
|
|
2017-06-16 20:45:45 +03:00
|
|
|
|
2017-10-19 20:41:27 +03:00
|
|
|
class JSONDefaultClient(Client):
|
|
|
|
"""
|
|
|
|
Same as a regular test client except the default content type is 'application/json'
|
|
|
|
for the post method instead of 'multipart/form-data'
|
|
|
|
"""
|
|
|
|
def post(self, path, data=None, content_type=CONTENT_TYPE_JSON,
|
|
|
|
follow=False, secure=False, **extra):
|
|
|
|
return super(JSONDefaultClient, self).post(
|
|
|
|
path,
|
|
|
|
data=data,
|
|
|
|
content_type=content_type,
|
|
|
|
follow=follow,
|
|
|
|
secure=secure,
|
|
|
|
**extra
|
|
|
|
)
|
|
|
|
|
2018-02-05 23:42:58 +03:00
|
|
|
def put(self, path, data=None, content_type=CONTENT_TYPE_JSON,
|
|
|
|
follow=False, secure=False, **extra):
|
|
|
|
return super(JSONDefaultClient, self).put(
|
|
|
|
path,
|
|
|
|
data=data,
|
|
|
|
content_type=content_type,
|
|
|
|
follow=follow,
|
|
|
|
secure=secure,
|
|
|
|
**extra
|
|
|
|
)
|
|
|
|
|
2017-10-19 20:41:27 +03:00
|
|
|
|
2018-03-15 20:16:59 +03:00
|
|
|
def create_logged_in_user(test, name, email, password="password1234", is_moderator=False):
|
2017-06-16 20:45:45 +03:00
|
|
|
test.name = name
|
|
|
|
|
|
|
|
# create use instance
|
|
|
|
User = EmailUser
|
2017-08-10 08:22:43 +03:00
|
|
|
user = User.objects.create_user(name=name, email=email, password=password)
|
2017-06-16 20:45:45 +03:00
|
|
|
user.save()
|
2017-05-03 21:06:26 +03:00
|
|
|
|
2017-06-16 20:45:45 +03:00
|
|
|
# make sure this user is in the staff group, too
|
|
|
|
if is_staff_address(email):
|
|
|
|
assign_group_policy(user, "staff")
|
|
|
|
add_user_to_main_site(user)
|
|
|
|
|
2018-03-15 20:16:59 +03:00
|
|
|
if is_moderator:
|
|
|
|
assign_group_policy(user, "moderator")
|
|
|
|
|
2017-06-16 20:45:45 +03:00
|
|
|
# log this user in for further testing purposes
|
|
|
|
test.user = user
|
2017-10-19 20:41:27 +03:00
|
|
|
test.client = JSONDefaultClient()
|
2017-06-16 20:45:45 +03:00
|
|
|
test.client.force_login(user)
|
|
|
|
|
|
|
|
|
|
|
|
def generate_default_payload(values):
|
|
|
|
return {
|
|
|
|
'title': 'default title',
|
|
|
|
'nonce': values['nonce'],
|
|
|
|
'csrfmiddlewaretoken': values['csrf_token'],
|
|
|
|
'content_url': 'http://example.com/',
|
|
|
|
'tags': ['tag1', 'tag2']
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-23 21:15:58 +03:00
|
|
|
def generate_payload(test, data={}, exclude={}, payload=False):
|
2017-06-16 20:45:45 +03:00
|
|
|
values = json.loads(
|
|
|
|
str(test.client.get('/api/pulse/nonce/').content, 'utf-8')
|
|
|
|
)
|
|
|
|
|
|
|
|
if payload is False:
|
|
|
|
payload = generate_default_payload(values)
|
|
|
|
|
|
|
|
for key in data:
|
|
|
|
payload[key] = data[key]
|
|
|
|
|
2019-05-23 21:15:58 +03:00
|
|
|
for key in exclude:
|
|
|
|
del payload[key]
|
|
|
|
|
2017-10-19 20:41:27 +03:00
|
|
|
return json.dumps(payload)
|
2017-06-16 20:45:45 +03:00
|
|
|
|
|
|
|
|
2018-03-15 20:16:59 +03:00
|
|
|
def boostrap(test, name, email, is_moderator=False):
|
2017-06-16 20:45:45 +03:00
|
|
|
setup_groups()
|
|
|
|
create_logged_in_user(
|
|
|
|
test,
|
|
|
|
name=name,
|
2018-03-15 20:16:59 +03:00
|
|
|
email=email,
|
|
|
|
is_moderator=is_moderator
|
2017-06-16 20:45:45 +03:00
|
|
|
)
|
2017-09-29 22:23:50 +03:00
|
|
|
setup_users_with_profiles(test)
|
|
|
|
setup_entries(test, creator_users=test.users_with_profiles)
|
2017-05-03 21:06:26 +03:00
|
|
|
|
|
|
|
|
|
|
|
class PulseMemberTestCase(TestCase):
|
2017-06-16 20:45:45 +03:00
|
|
|
"""
|
|
|
|
A test case wrapper for "plain users" without any staff or admin rights
|
|
|
|
"""
|
2018-03-28 20:38:08 +03:00
|
|
|
maxDiff = None
|
|
|
|
|
2017-01-11 01:53:10 +03:00
|
|
|
def setUp(self):
|
2017-06-16 20:45:45 +03:00
|
|
|
boostrap(
|
|
|
|
self,
|
|
|
|
name="plain user",
|
|
|
|
email="test@example.org"
|
|
|
|
)
|
2017-01-11 01:53:10 +03:00
|
|
|
|
2019-05-23 21:15:58 +03:00
|
|
|
def generatePostPayload(self, data={}, exclude=[]):
|
|
|
|
return generate_payload(self, data, exclude)
|
2017-01-11 01:53:10 +03:00
|
|
|
|
|
|
|
|
2017-06-16 20:45:45 +03:00
|
|
|
class PulseStaffTestCase(TestCase):
|
|
|
|
"""
|
|
|
|
A test case wrapper for "staff" users, due to having a mozilla login
|
|
|
|
"""
|
2018-03-28 20:38:08 +03:00
|
|
|
maxDiff = None
|
|
|
|
|
2017-06-16 20:45:45 +03:00
|
|
|
def setUp(self):
|
|
|
|
boostrap(
|
|
|
|
self,
|
|
|
|
name="staff user",
|
2018-11-14 19:37:07 +03:00
|
|
|
email="test@mozillafoundation.org"
|
2017-06-16 20:45:45 +03:00
|
|
|
)
|
2017-01-11 01:53:10 +03:00
|
|
|
|
2019-05-23 21:15:58 +03:00
|
|
|
def generatePostPayload(self, data={}, exclude=[]):
|
|
|
|
return generate_payload(self, data, exclude)
|
2018-02-14 21:36:00 +03:00
|
|
|
|
|
|
|
|
2018-03-15 20:16:59 +03:00
|
|
|
class PulseModeratorTestCase(TestCase):
|
|
|
|
"""
|
|
|
|
A test case wrapper for "moderator" users
|
|
|
|
"""
|
|
|
|
def setUp(self):
|
|
|
|
boostrap(
|
|
|
|
self,
|
|
|
|
name="Moderator user",
|
|
|
|
email="moderator@example.org",
|
|
|
|
is_moderator=True
|
|
|
|
)
|
|
|
|
|
2019-05-23 21:15:58 +03:00
|
|
|
def generatePostPayload(self, data={}, exclude=[]):
|
|
|
|
return generate_payload(self, data, exclude)
|
2018-03-15 20:16:59 +03:00
|
|
|
|
2018-03-15 20:30:22 +03:00
|
|
|
|
2018-02-14 21:36:00 +03:00
|
|
|
class TestAPIVersioning(TestCase):
|
|
|
|
"""
|
|
|
|
Test API versioning
|
|
|
|
"""
|
|
|
|
def setUp(self):
|
|
|
|
self.client = JSONDefaultClient()
|
|
|
|
self.factory = RequestFactory()
|
|
|
|
self.version_scheme = PulseAPIVersioning()
|
|
|
|
|
|
|
|
def test_status_route(self):
|
|
|
|
response = self.client.get(reverse('api-status'))
|
|
|
|
status = json.loads(str(response.content, 'utf-8'))
|
|
|
|
|
|
|
|
self.assertDictEqual(status, {
|
|
|
|
'latestApiVersion': API_VERSION_LIST[-1][1],
|
|
|
|
})
|
|
|
|
|
|
|
|
def test_versioning_scheme_default_version(self):
|
|
|
|
request = self.factory.get(reverse('api-status'))
|
|
|
|
version = self.version_scheme.determine_version(request, version=None)
|
|
|
|
|
|
|
|
self.assertEqual(version, self.version_scheme.default_version)
|
|
|
|
|
|
|
|
def test_invalid_version(self):
|
|
|
|
request = self.factory.get(reverse('entries-list'))
|
|
|
|
|
|
|
|
with self.assertRaises(exceptions.NotFound) as context_manager:
|
|
|
|
self.version_scheme.determine_version(request, version='v100')
|
|
|
|
|
|
|
|
self.assertEqual(context_manager.exception.detail, self.version_scheme.invalid_version_message)
|
2018-05-16 11:45:09 +03:00
|
|
|
|
|
|
|
|
|
|
|
class MissingMigrationsTests(TestCase):
|
|
|
|
|
|
|
|
def test_no_migrations_missing(self):
|
|
|
|
"""
|
|
|
|
Ensure we didn't forget a migration
|
|
|
|
"""
|
|
|
|
call_command('makemigrations', interactive=False, dry_run=True, check_changes=True)
|