New Test order.
* seperate unittests and integration tests * moved old tests in seperat folder 'old' * created a testrunner that does not create a testdatabase, if only unittests are run * wrote some unit- and integration tests as examples * fixed user.get_short_name() to use the sort order from config * fixed wrong url_pattern in the user app
This commit is contained in:
parent
ea45469338
commit
e7230b7391
10
.travis.yml
10
.travis.yml
@ -8,6 +8,12 @@ install:
|
|||||||
- "node_modules/.bin/bower install"
|
- "node_modules/.bin/bower install"
|
||||||
- "node_modules/.bin/gulp --production"
|
- "node_modules/.bin/gulp --production"
|
||||||
script:
|
script:
|
||||||
- "DJANGO_SETTINGS_MODULE='tests.settings' coverage run ./manage.py test"
|
|
||||||
- "coverage report -m --fail-under=80"
|
|
||||||
- "flake8 --max-line-length=150 --statistics openslides tests"
|
- "flake8 --max-line-length=150 --statistics openslides tests"
|
||||||
|
|
||||||
|
- "DJANGO_SETTINGS_MODULE='tests.settings' coverage run ./manage.py test tests.unit"
|
||||||
|
- "coverage report --show-missing --fail-under=35"
|
||||||
|
|
||||||
|
- "DJANGO_SETTINGS_MODULE='tests.settings' coverage run ./manage.py test tests.integration"
|
||||||
|
- "coverage report --show-missing --fail-under=45"
|
||||||
|
|
||||||
|
- "DJANGO_SETTINGS_MODULE='tests.old.settings' ./manage.py test tests.old"
|
||||||
|
@ -2,6 +2,10 @@ import re
|
|||||||
|
|
||||||
from parser import command, argument, call
|
from parser import command, argument, call
|
||||||
|
|
||||||
|
FAIL = '\033[91m'
|
||||||
|
SUCCESS = '\033[92m'
|
||||||
|
RESET = '\033[0m'
|
||||||
|
|
||||||
|
|
||||||
@argument('module', nargs='?', default='')
|
@argument('module', nargs='?', default='')
|
||||||
@command('test', help='runs the tests')
|
@command('test', help='runs the tests')
|
||||||
@ -10,8 +14,8 @@ def test(args=None):
|
|||||||
Runs the tests.
|
Runs the tests.
|
||||||
"""
|
"""
|
||||||
module = getattr(args, 'module', '')
|
module = getattr(args, 'module', '')
|
||||||
return call("DJANGO_SETTINGS_MODULE='tests.settings' coverage run "
|
return call("DJANGO_SETTINGS_MODULE='tests.integration.settings' coverage run "
|
||||||
"./manage.py test %s" % module)
|
"./manage.py test tests.%s" % module)
|
||||||
|
|
||||||
|
|
||||||
@argument('--plain', action='store_true')
|
@argument('--plain', action='store_true')
|
||||||
@ -51,11 +55,17 @@ def travis(args=None):
|
|||||||
if line == 'script:':
|
if line == 'script:':
|
||||||
script_lines = True
|
script_lines = True
|
||||||
continue
|
continue
|
||||||
if not script_lines:
|
if not script_lines or not line:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
match = re.search(r'"(.*)"', line)
|
match = re.search(r'"(.*)"', line)
|
||||||
return_codes.append(call(match.group(1)))
|
print('Run: %s' % match.group(1))
|
||||||
|
return_code = call(match.group(1))
|
||||||
|
return_codes.append(return_code)
|
||||||
|
if return_code:
|
||||||
|
print(FAIL + 'fail!\n' + RESET)
|
||||||
|
else:
|
||||||
|
print(SUCCESS + 'success!\n' + RESET)
|
||||||
|
|
||||||
# Retuns True if one command exited with a different statuscode then 1
|
# Retuns True if one command exited with a different statuscode then 1
|
||||||
return bool(list(filter(bool, return_codes)))
|
return bool(list(filter(bool, return_codes)))
|
||||||
@ -81,3 +91,14 @@ def min_requirements(args=None):
|
|||||||
yield '%s==%s' % (line.req.key, line.req.specs[0][1])
|
yield '%s==%s' % (line.req.key, line.req.specs[0][1])
|
||||||
|
|
||||||
print('pip install %s' % ' '.join(get_lowest_versions(args.requirements)))
|
print('pip install %s' % ' '.join(get_lowest_versions(args.requirements)))
|
||||||
|
|
||||||
|
|
||||||
|
@command('clear',
|
||||||
|
help='Deletes unneeded files and folders')
|
||||||
|
def clear(args=None):
|
||||||
|
"""
|
||||||
|
Deletes all .pyc and .orig files and empty folders.
|
||||||
|
"""
|
||||||
|
call('find -name "*.pyc" -delete')
|
||||||
|
call('find -name "*.orig" -delete')
|
||||||
|
call('find -type d -empty -delete')
|
||||||
|
@ -159,7 +159,7 @@
|
|||||||
{{ field }}
|
{{ field }}
|
||||||
<button class="btn btn-primary tooltip-bottom" type="submit" data-original-title="{% trans 'Apply' %}"><i class="icon-ok icon-white"></i></button>
|
<button class="btn btn-primary tooltip-bottom" type="submit" data-original-title="{% trans 'Apply' %}"><i class="icon-ok icon-white"></i></button>
|
||||||
{% if perms.users.can_see and perms.users.can_manage %}
|
{% if perms.users.can_see and perms.users.can_manage %}
|
||||||
<a href="{% url 'user_new' %}" class="btn" rel="tooltip" data-original-title="{% trans 'Add new user' %}"><i class="icon-add-user"></i></a>
|
<a href="{% url 'user_create' %}" class="btn" rel="tooltip" data-original-title="{% trans 'Add new user' %}"><i class="icon-add-user"></i></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if field.errors %}
|
{% if field.errors %}
|
||||||
<span class="help-inline">{{ field.errors }}</span>
|
<span class="help-inline">{{ field.errors }}</span>
|
||||||
|
@ -149,7 +149,7 @@
|
|||||||
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
|
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
{% if perms.users.can_see and perms.users.can_manage %}
|
{% if perms.users.can_see and perms.users.can_manage %}
|
||||||
<a href="{% url 'user_new' %}" target="_blank" class="btn btn-default"
|
<a href="{% url 'user_create' %}" target="_blank" class="btn btn-default"
|
||||||
rel="tooltip" data-original-title="{% trans 'Add new participant' %}">
|
rel="tooltip" data-original-title="{% trans 'Add new participant' %}">
|
||||||
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
|
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -173,3 +173,5 @@ CKEDITOR_CONFIGS = {
|
|||||||
# Use small alternative with tornado as frontend or big alternative with a
|
# Use small alternative with tornado as frontend or big alternative with a
|
||||||
# webserver as wsgi server.
|
# webserver as wsgi server.
|
||||||
USE_TORNADO_AS_WSGI_SERVER = True
|
USE_TORNADO_AS_WSGI_SERVER = True
|
||||||
|
|
||||||
|
TEST_RUNNER = 'openslides.utils.test.OpenSlidesDiscoverRunner'
|
||||||
|
@ -162,6 +162,5 @@ def get_protected_perm():
|
|||||||
Returns the permission to manage users. This function is a helper
|
Returns the permission to manage users. This function is a helper
|
||||||
function used to protect manager users from locking out themselves.
|
function used to protect manager users from locking out themselves.
|
||||||
"""
|
"""
|
||||||
return Permission.objects.get(
|
return Permission.objects.get_by_natural_key(
|
||||||
content_type=ContentType.objects.get(app_label='users', model='user'),
|
app_label='users', model='user', codename='can_manage')
|
||||||
codename='can_manage')
|
|
||||||
|
@ -9,12 +9,17 @@ from django.core.urlresolvers import reverse
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||||
|
|
||||||
|
from openslides.config.api import config
|
||||||
from openslides.projector.models import SlideMixin
|
from openslides.projector.models import SlideMixin
|
||||||
from openslides.utils.models import AbsoluteUrlMixin
|
from openslides.utils.models import AbsoluteUrlMixin
|
||||||
from openslides.utils.rest_api import RESTModelMixin
|
from openslides.utils.rest_api import RESTModelMixin
|
||||||
|
|
||||||
|
|
||||||
class UserManager(BaseUserManager):
|
class UserManager(BaseUserManager):
|
||||||
|
"""
|
||||||
|
UserManager that creates new users only with a password and a username.
|
||||||
|
"""
|
||||||
|
|
||||||
def create_user(self, username, password, **kwargs):
|
def create_user(self, username, password, **kwargs):
|
||||||
user = self.model(username=username, **kwargs)
|
user = self.model(username=username, **kwargs)
|
||||||
user.set_password(password)
|
user.set_password(password)
|
||||||
@ -87,9 +92,9 @@ class User(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, PermissionsMixin, Abstr
|
|||||||
Returns the URL to the user.
|
Returns the URL to the user.
|
||||||
"""
|
"""
|
||||||
if link == 'detail':
|
if link == 'detail':
|
||||||
url = reverse('user_view', args=[str(self.pk)])
|
url = reverse('user_detail', args=[str(self.pk)])
|
||||||
elif link == 'update':
|
elif link == 'update':
|
||||||
url = reverse('user_edit', args=[str(self.pk)])
|
url = reverse('user_update', args=[str(self.pk)])
|
||||||
elif link == 'delete':
|
elif link == 'delete':
|
||||||
url = reverse('user_delete', args=[str(self.pk)])
|
url = reverse('user_delete', args=[str(self.pk)])
|
||||||
else:
|
else:
|
||||||
@ -111,10 +116,7 @@ class User(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, PermissionsMixin, Abstr
|
|||||||
E. g.: * Dr. Max Mustermann (Villingen)
|
E. g.: * Dr. Max Mustermann (Villingen)
|
||||||
* Professor Dr. Enders, Christoph (Leipzig)
|
* Professor Dr. Enders, Christoph (Leipzig)
|
||||||
"""
|
"""
|
||||||
if self.structure_level:
|
structure = '(%s)' % self.structure_level if self.structure_level else ''
|
||||||
structure = '(%s)' % self.structure_level
|
|
||||||
else:
|
|
||||||
structure = ''
|
|
||||||
|
|
||||||
return ' '.join((self.title, self.get_short_name(), structure)).strip()
|
return ' '.join((self.title, self.get_short_name(), structure)).strip()
|
||||||
|
|
||||||
@ -125,9 +127,21 @@ class User(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, PermissionsMixin, Abstr
|
|||||||
E. g.: * Max Mustermann
|
E. g.: * Max Mustermann
|
||||||
* Enders, Christoph
|
* Enders, Christoph
|
||||||
"""
|
"""
|
||||||
# TODO: Order of name. See config.
|
# Strip white spaces from the name parts
|
||||||
name = ('%s %s' % (self.first_name, self.last_name)).strip()
|
first_name = self.first_name.strip()
|
||||||
return name or self.username
|
last_name = self.last_name.strip()
|
||||||
|
|
||||||
|
# The user has a last_name and a first_name
|
||||||
|
if first_name and last_name:
|
||||||
|
if config['users_sort_users_by_first_name']:
|
||||||
|
name = ' '.join((first_name, last_name))
|
||||||
|
else:
|
||||||
|
name = ', '.join((last_name, first_name))
|
||||||
|
|
||||||
|
# The user has only a first_name or a last_name or no name
|
||||||
|
else:
|
||||||
|
name = first_name or last_name or self.username
|
||||||
|
return name
|
||||||
|
|
||||||
def reset_password(self, password=None):
|
def reset_password(self, password=None):
|
||||||
"""
|
"""
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load tags %}
|
||||||
|
|
||||||
{% block title %}{{ shown_user }} – {{ block.super }}{% endblock %}
|
{% block title %}{{ shown_user }} – {{ block.super }}{% endblock %}
|
||||||
|
|
||||||
@ -29,7 +30,7 @@
|
|||||||
<ul class="dropdown-menu pull-right">
|
<ul class="dropdown-menu pull-right">
|
||||||
<!-- edit -->
|
<!-- edit -->
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'user_edit' shown_user.id %}">
|
<a href="{{ user|absolute_url:'update' }}">
|
||||||
<i class="icon-pencil"></i>
|
<i class="icon-pencil"></i>
|
||||||
{% trans 'Edit user' %}
|
{% trans 'Edit user' %}
|
||||||
</a>
|
</a>
|
||||||
|
@ -20,11 +20,11 @@
|
|||||||
{% trans "Users" %}
|
{% trans "Users" %}
|
||||||
<small class="pull-right">
|
<small class="pull-right">
|
||||||
{% if perms.users.can_manage %}
|
{% if perms.users.can_manage %}
|
||||||
<a href="{% url 'user_new' %}" class="btn btn-mini btn-primary" rel="tooltip" data-original-title="{% trans 'New user' %}">
|
<a href="{% url 'user_create' %}" class="btn btn-mini btn-primary" rel="tooltip" data-original-title="{% trans 'New user' %}">
|
||||||
<i class="icon-plus icon-white"></i>
|
<i class="icon-plus icon-white"></i>
|
||||||
{% trans "New" %}
|
{% trans "New" %}
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url 'user_new_multiple' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'New multiple users' %}">
|
<a href="{% url 'user_create_multiple' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'New multiple users' %}">
|
||||||
<i class="icon-plus"></i>
|
<i class="icon-plus"></i>
|
||||||
{% trans 'New multiple' %}
|
{% trans 'New multiple' %}
|
||||||
</a>
|
</a>
|
||||||
@ -102,9 +102,9 @@
|
|||||||
<td class="optional">{{ user.title }}</td>
|
<td class="optional">{{ user.title }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if 'users_sort_users_by_first_name'|get_config %}
|
{% if 'users_sort_users_by_first_name'|get_config %}
|
||||||
<a href="{% url 'user_view' user.id %}">{{ user.first_name }} {{ user.last_name }}</a>
|
<a href="{{ user|absolute_url }}">{{ user.first_name }} {{ user.last_name }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{% url 'user_view' user.id %}">{{ user.last_name }}{% if user.last_name and user.first_name %},{% endif %} {{ user.first_name }}</a>
|
<a href="{{ user|absolute_url }}">{{ user.last_name }}{% if user.last_name and user.first_name %},{% endif %} {{ user.first_name }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="optional">{{ user.structure_level }}</td>
|
<td class="optional">{{ user.structure_level }}</td>
|
||||||
@ -138,7 +138,7 @@
|
|||||||
<i class="icon-facetime-video {% if user.is_active_slide %}icon-white{% endif %}"></i>
|
<i class="icon-facetime-video {% if user.is_active_slide %}icon-white{% endif %}"></i>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{% url 'user_edit' user.id %}" rel="tooltip" data-original-title="{% trans 'Edit' %}"
|
<a href="{{ user|absolute_url:'update' }}" rel="tooltip" data-original-title="{% trans 'Edit' %}"
|
||||||
class="btn btn-mini">
|
class="btn btn-mini">
|
||||||
<i class="icon-pencil"></i>
|
<i class="icon-pencil"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -11,19 +11,19 @@ urlpatterns = patterns(
|
|||||||
|
|
||||||
url(r'^new/$',
|
url(r'^new/$',
|
||||||
views.UserCreateView.as_view(),
|
views.UserCreateView.as_view(),
|
||||||
name='user_new'),
|
name='user_create'),
|
||||||
|
|
||||||
url(r'^new_multiple/$',
|
url(r'^new_multiple/$',
|
||||||
views.UserMultipleCreateView.as_view(),
|
views.UserMultipleCreateView.as_view(),
|
||||||
name='user_new_multiple'),
|
name='user_create_multiple'),
|
||||||
|
|
||||||
url(r'^(?P<pk>\d+)/$',
|
url(r'^(?P<pk>\d+)/$',
|
||||||
views.UserDetailView.as_view(),
|
views.UserDetailView.as_view(),
|
||||||
name='user_view'),
|
name='user_detail'),
|
||||||
|
|
||||||
url(r'^(?P<pk>\d+)/edit/$',
|
url(r'^(?P<pk>\d+)/edit/$',
|
||||||
views.UserUpdateView.as_view(),
|
views.UserUpdateView.as_view(),
|
||||||
name='user_edit'),
|
name='user_update'),
|
||||||
|
|
||||||
url(r'^(?P<pk>\d+)/del/$',
|
url(r'^(?P<pk>\d+)/del/$',
|
||||||
views.UserDeleteView.as_view(),
|
views.UserDeleteView.as_view(),
|
||||||
|
@ -251,7 +251,7 @@ class ResetPasswordView(SingleObjectMixin, QuestionView):
|
|||||||
question_message = ugettext_lazy('Do you really want to reset the password?')
|
question_message = ugettext_lazy('Do you really want to reset the password?')
|
||||||
|
|
||||||
def get_redirect_url(self, **kwargs):
|
def get_redirect_url(self, **kwargs):
|
||||||
return reverse('user_edit', args=[self.get_object().id])
|
return self.get_object().get_absolute_url('update')
|
||||||
|
|
||||||
def on_clicked_yes(self):
|
def on_clicked_yes(self):
|
||||||
self.get_object().reset_password()
|
self.get_object().reset_password()
|
||||||
|
@ -1,9 +1,32 @@
|
|||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
from django.test import TestCase as _TestCase
|
from django.test import TestCase as _TestCase
|
||||||
|
from django.test.runner import DiscoverRunner
|
||||||
|
|
||||||
from openslides.config.api import config
|
from openslides.config.api import config
|
||||||
|
|
||||||
|
|
||||||
|
class OpenSlidesDiscoverRunner(DiscoverRunner):
|
||||||
|
def run_tests(self, test_labels, extra_tests=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Test Runner which does not create a database, if only unittest are run.
|
||||||
|
"""
|
||||||
|
if len(test_labels) == 1 and test_labels[0].startswith('tests.unit'):
|
||||||
|
# Do not create a test database, if only unittests are tested
|
||||||
|
create_database = False
|
||||||
|
else:
|
||||||
|
create_database = True
|
||||||
|
|
||||||
|
self.setup_test_environment()
|
||||||
|
suite = self.build_suite(test_labels, extra_tests)
|
||||||
|
if create_database:
|
||||||
|
old_config = self.setup_databases()
|
||||||
|
result = self.run_suite(suite)
|
||||||
|
if create_database:
|
||||||
|
self.teardown_databases(old_config)
|
||||||
|
self.teardown_test_environment()
|
||||||
|
return self.suite_result(suite, result)
|
||||||
|
|
||||||
|
|
||||||
class TestCase(_TestCase):
|
class TestCase(_TestCase):
|
||||||
"""
|
"""
|
||||||
Overwrites Django's TestCase class to refreshs the config cache.
|
Overwrites Django's TestCase class to refreshs the config cache.
|
||||||
|
@ -2,44 +2,15 @@ import difflib
|
|||||||
import roman
|
import roman
|
||||||
|
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.shortcuts import render_to_response
|
|
||||||
from django.template import RequestContext
|
|
||||||
|
|
||||||
from .signals import template_manipulation
|
|
||||||
|
|
||||||
|
|
||||||
def template(template_name):
|
|
||||||
"""
|
|
||||||
Decorator to set a template for a view.
|
|
||||||
|
|
||||||
Deprecated. Use class based views instead.
|
|
||||||
"""
|
|
||||||
# TODO: Write the login page an the usersettings page with class based views
|
|
||||||
# Remove this function afterwards
|
|
||||||
def renderer(func):
|
|
||||||
def wrapper(request, *args, **kwargs):
|
|
||||||
output = func(request, *args, **kwargs)
|
|
||||||
if not isinstance(output, dict):
|
|
||||||
return output
|
|
||||||
context = {}
|
|
||||||
template_manipulation.send(
|
|
||||||
sender='utils_template', request=request, context=context)
|
|
||||||
output.update(context)
|
|
||||||
response = render_to_response(
|
|
||||||
template_name, output, context_instance=RequestContext(request))
|
|
||||||
if 'cookie' in output:
|
|
||||||
response.set_cookie(output['cookie'][0], output['cookie'][1])
|
|
||||||
return response
|
|
||||||
return wrapper
|
|
||||||
return renderer
|
|
||||||
|
|
||||||
|
|
||||||
def delete_default_permissions(**kwargs):
|
def delete_default_permissions(**kwargs):
|
||||||
"""
|
"""
|
||||||
Deletes the permissions, django creates by default for the admin.
|
Deletes the permissions, django creates by default for the admin.
|
||||||
"""
|
"""
|
||||||
# TODO: Create an participant app which does not create the permissions.
|
# TODO: Find a way not to create the permissions in the first place.
|
||||||
# Delete this function afterwards
|
# Meta.default_permissions does not work, because django will
|
||||||
|
# nevertheless create permissions for its own models like "group"
|
||||||
for p in Permission.objects.all():
|
for p in Permission.objects.all():
|
||||||
if (p.codename.startswith('add') or
|
if (p.codename.startswith('add') or
|
||||||
p.codename.startswith('delete') or
|
p.codename.startswith('delete') or
|
||||||
@ -51,7 +22,7 @@ def html_strong(string):
|
|||||||
"""
|
"""
|
||||||
Returns the text wrapped in an HTML-Strong element.
|
Returns the text wrapped in an HTML-Strong element.
|
||||||
"""
|
"""
|
||||||
return u"<strong>%s</strong>" % string
|
return "<strong>%s</strong>" % string
|
||||||
|
|
||||||
|
|
||||||
def htmldiff(text1, text2):
|
def htmldiff(text1, text2):
|
||||||
|
@ -33,7 +33,7 @@ class LoginMixin(object):
|
|||||||
"""
|
"""
|
||||||
Check if the user is loged in.
|
Check if the user is loged in.
|
||||||
"""
|
"""
|
||||||
return super(LoginMixin, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class PermissionMixin(object):
|
class PermissionMixin(object):
|
||||||
@ -68,7 +68,7 @@ class PermissionMixin(object):
|
|||||||
"%s?next=%s" % (settings.LOGIN_URL, path))
|
"%s?next=%s" % (settings.LOGIN_URL, path))
|
||||||
else:
|
else:
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
return super(PermissionMixin, self).dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class AjaxMixin(object):
|
class AjaxMixin(object):
|
||||||
@ -103,7 +103,7 @@ class ExtraContextMixin(object):
|
|||||||
"""
|
"""
|
||||||
context = super(ExtraContextMixin, self).get_context_data(**kwargs)
|
context = super(ExtraContextMixin, self).get_context_data(**kwargs)
|
||||||
template_manipulation.send(
|
template_manipulation.send(
|
||||||
sender=self.__class__, request=self.request, context=context)
|
sender=type(self), request=self.request, context=context)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
@ -130,11 +130,13 @@ class UrlMixin(object):
|
|||||||
elif url:
|
elif url:
|
||||||
value = url
|
value = url
|
||||||
else:
|
else:
|
||||||
|
if use_absolute_url_link is None:
|
||||||
|
get_absolute_url_args = []
|
||||||
|
else:
|
||||||
|
get_absolute_url_args = [use_absolute_url_link]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if use_absolute_url_link is None:
|
value = self.object.get_absolute_url(*get_absolute_url_args)
|
||||||
value = self.object.get_absolute_url()
|
|
||||||
else:
|
|
||||||
value = self.object.get_absolute_url(use_absolute_url_link)
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise ImproperlyConfigured(
|
raise ImproperlyConfigured(
|
||||||
'No url to redirect to. See openslides.utils.views.UrlMixin '
|
'No url to redirect to. See openslides.utils.views.UrlMixin '
|
||||||
@ -155,10 +157,7 @@ class UrlMixin(object):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
value = []
|
value = []
|
||||||
else:
|
else:
|
||||||
if pk:
|
value = [pk] if pk else []
|
||||||
value = [pk]
|
|
||||||
else:
|
|
||||||
value = []
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
14
tests/integration/users/test_views.py
Normal file
14
tests/integration/users/test_views.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from openslides.utils.test import TestCase
|
||||||
|
from django.test.client import Client
|
||||||
|
|
||||||
|
|
||||||
|
class UserViews(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.client = Client()
|
||||||
|
self.client.login(username='admin', password='admin')
|
||||||
|
|
||||||
|
def test_user_list(self):
|
||||||
|
response = self.client.get('/user/')
|
||||||
|
|
||||||
|
self.assertTemplateUsed(response, 'users/user_list.html')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
@ -5,6 +5,7 @@ from openslides.motion.csv_import import import_motions
|
|||||||
from openslides.motion.models import Category, Motion
|
from openslides.motion.models import Category, Motion
|
||||||
from openslides.users.models import User
|
from openslides.users.models import User
|
||||||
from openslides.utils.test import TestCase
|
from openslides.utils.test import TestCase
|
||||||
|
from openslides.config.api import config
|
||||||
|
|
||||||
|
|
||||||
class CSVImport(TestCase):
|
class CSVImport(TestCase):
|
||||||
@ -20,6 +21,9 @@ class CSVImport(TestCase):
|
|||||||
Category.objects.create(name='Bildung', prefix='B2')
|
Category.objects.create(name='Bildung', prefix='B2')
|
||||||
|
|
||||||
def test_example_file_de(self):
|
def test_example_file_de(self):
|
||||||
|
# Set config to sort names by first_name because the example csv-file
|
||||||
|
# expect this.
|
||||||
|
config['users_sort_users_by_first_name'] = True
|
||||||
special_user = User.objects.create_user(username='Harry_Holland',
|
special_user = User.objects.create_user(username='Harry_Holland',
|
||||||
password='iegheeChaje7guthie4a',
|
password='iegheeChaje7guthie4a',
|
||||||
first_name='Harry',
|
first_name='Harry',
|
||||||
@ -31,7 +35,7 @@ class CSVImport(TestCase):
|
|||||||
first_name='John',
|
first_name='John',
|
||||||
last_name='Doe')
|
last_name='Doe')
|
||||||
|
|
||||||
csv_dir = os.path.join(os.path.dirname(__file__), '..', '..', 'extras', 'csv-examples')
|
csv_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', 'extras', 'csv-examples')
|
||||||
self.assertEqual(Motion.objects.count(), 0)
|
self.assertEqual(Motion.objects.count(), 0)
|
||||||
with open(csv_dir + '/motions-demo_de.csv', 'rb') as f:
|
with open(csv_dir + '/motions-demo_de.csv', 'rb') as f:
|
||||||
success_message, warning_message, error_message = import_motions(
|
success_message, warning_message, error_message = import_motions(
|
@ -7,7 +7,7 @@ from django.core.urlresolvers import clear_url_caches
|
|||||||
from openslides.utils.test import TestCase
|
from openslides.utils.test import TestCase
|
||||||
|
|
||||||
|
|
||||||
@override_settings(INSTALLED_PLUGINS=('tests.plugin_api.test_plugin_one',))
|
@override_settings(INSTALLED_PLUGINS=('tests.old.plugin_api.test_plugin_one',))
|
||||||
class TestPluginOne(TestCase):
|
class TestPluginOne(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.admin_client = Client()
|
self.admin_client = Client()
|
||||||
@ -27,11 +27,11 @@ class TestPluginOne(TestCase):
|
|||||||
self.assertRedirects(response, '/version/')
|
self.assertRedirects(response, '/version/')
|
||||||
|
|
||||||
|
|
||||||
@override_settings(INSTALLED_PLUGINS=('tests.plugin_api.test_plugin_two',))
|
@override_settings(INSTALLED_PLUGINS=('tests.old.plugin_api.test_plugin_two',))
|
||||||
class TestPluginTwo(TestCase):
|
class TestPluginTwo(TestCase):
|
||||||
def test_version_page(self):
|
def test_version_page(self):
|
||||||
admin_client = Client()
|
admin_client = Client()
|
||||||
admin_client.login(username='admin', password='admin')
|
admin_client.login(username='admin', password='admin')
|
||||||
response = admin_client.get('/version/')
|
response = admin_client.get('/version/')
|
||||||
self.assertContains(response, 'tests.plugin_api.test_plugin_two')
|
self.assertContains(response, 'tests.old.plugin_api.test_plugin_two')
|
||||||
self.assertContains(response, '– Version unknown')
|
self.assertContains(response, '– Version unknown')
|
0
tests/old/projector/__init__.py
Normal file
0
tests/old/projector/__init__.py
Normal file
56
tests/old/settings.py
Normal file
56
tests/old/settings.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
"""
|
||||||
|
Settings file for OpenSlides' tests
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from openslides.global_settings import * # noqa
|
||||||
|
|
||||||
|
# Path to the directory for user specific data files
|
||||||
|
OPENSLIDES_USER_DATA_PATH = os.path.realpath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
# SECURITY WARNING: Keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'secret'
|
||||||
|
|
||||||
|
# OpenSlides plugins
|
||||||
|
# Add plugins to this list.
|
||||||
|
|
||||||
|
INSTALLED_PLUGINS += (
|
||||||
|
'tests.old.utils',
|
||||||
|
)
|
||||||
|
|
||||||
|
INSTALLED_APPS += INSTALLED_PLUGINS
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# Change this to use MySQL or PostgreSQL.
|
||||||
|
# See https://docs.djangoproject.com/en/1.7/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Some other settings
|
||||||
|
|
||||||
|
TIME_ZONE = 'Europe/Berlin'
|
||||||
|
|
||||||
|
MEDIA_ROOT = os.path.join(OPENSLIDES_USER_DATA_PATH, '')
|
||||||
|
|
||||||
|
TEMPLATE_DIRS = (
|
||||||
|
os.path.join(OPENSLIDES_USER_DATA_PATH, 'templates'),
|
||||||
|
)
|
||||||
|
|
||||||
|
STATICFILES_DIRS.insert(0, os.path.join(OPENSLIDES_USER_DATA_PATH, 'static'))
|
||||||
|
|
||||||
|
HAYSTACK_CONNECTIONS['default']['STORAGE'] = 'ram'
|
||||||
|
|
||||||
|
|
||||||
|
# Special test settings
|
||||||
|
# Use a faster password hasher.
|
||||||
|
|
||||||
|
PASSWORD_HASHERS = (
|
||||||
|
'django.contrib.auth.hashers.MD5PasswordHasher',
|
||||||
|
)
|
0
tests/old/users/__init__.py
Normal file
0
tests/old/users/__init__.py
Normal file
@ -85,10 +85,10 @@ class GroupViews(TestCase):
|
|||||||
|
|
||||||
def test_detail(self):
|
def test_detail(self):
|
||||||
response = self.client.get('/user/group/3/')
|
response = self.client.get('/user/group/3/')
|
||||||
pattern = r'admins_first_name Administrator|aWei4ien6Se0vie0xeiv uquahx3Wohtieph9baer'
|
pattern = r'Administrator, admins_first_name|uquahx3Wohtieph9baer, aWei4ien6Se0vie0xeiv'
|
||||||
match = re.findall(pattern, response.content.decode('utf8'))
|
match = re.findall(pattern, response.content.decode('utf8'))
|
||||||
self.assertEqual(match[0], 'admins_first_name Administrator')
|
self.assertEqual(match[0], 'Administrator, admins_first_name')
|
||||||
self.assertEqual(match[1], 'aWei4ien6Se0vie0xeiv uquahx3Wohtieph9baer')
|
self.assertEqual(match[1], 'uquahx3Wohtieph9baer, aWei4ien6Se0vie0xeiv')
|
||||||
|
|
||||||
config['users_sort_users_by_first_name'] = True
|
config['users_sort_users_by_first_name'] = True
|
||||||
self.assertTrue(config['users_sort_users_by_first_name'])
|
self.assertTrue(config['users_sort_users_by_first_name'])
|
0
tests/old/utils/__init__.py
Normal file
0
tests/old/utils/__init__.py
Normal file
@ -27,12 +27,12 @@ class TestBaseTwo(object, metaclass=SignalConnectMetaClass):
|
|||||||
class TestSignalConnectMetaClass(TestCase):
|
class TestSignalConnectMetaClass(TestCase):
|
||||||
request_factory = RequestFactory()
|
request_factory = RequestFactory()
|
||||||
|
|
||||||
@patch('tests.utils.test_dispatch.TestBaseOne.signal')
|
@patch('tests.old.utils.test_dispatch.TestBaseOne.signal')
|
||||||
def test_call_signal_send(self, mock_signal):
|
def test_call_signal_send(self, mock_signal):
|
||||||
TestBaseOne.get_all(self.request_factory.request)
|
TestBaseOne.get_all(self.request_factory.request)
|
||||||
self.assertTrue(mock_signal.send.called)
|
self.assertTrue(mock_signal.send.called)
|
||||||
|
|
||||||
@patch('tests.utils.test_dispatch.TestBaseOne.signal')
|
@patch('tests.old.utils.test_dispatch.TestBaseOne.signal')
|
||||||
def test_call_signal_connect(self, mock_signal):
|
def test_call_signal_connect(self, mock_signal):
|
||||||
class TestChildOne(TestBaseOne):
|
class TestChildOne(TestBaseOne):
|
||||||
pass
|
pass
|
@ -6,20 +6,18 @@ import os
|
|||||||
from openslides.global_settings import * # noqa
|
from openslides.global_settings import * # noqa
|
||||||
|
|
||||||
# Path to the directory for user specific data files
|
# Path to the directory for user specific data files
|
||||||
|
|
||||||
OPENSLIDES_USER_DATA_PATH = os.path.realpath(os.path.dirname(__file__))
|
OPENSLIDES_USER_DATA_PATH = os.path.realpath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
# SECURITY WARNING: Keep the secret key used in production secret!
|
# SECURITY WARNING: Keep the secret key used in production secret!
|
||||||
|
|
||||||
SECRET_KEY = 'secret'
|
SECRET_KEY = 'secret'
|
||||||
|
|
||||||
|
# OpenSlides plugins
|
||||||
|
# Add plugins to this list.
|
||||||
|
|
||||||
# Use 'DEBUG = True' to get more details for server errors.
|
INSTALLED_PLUGINS += (
|
||||||
# SECURITY WARNING: Don't run with debug turned on in production!
|
'tests.old.utils',
|
||||||
|
)
|
||||||
DEBUG = True
|
|
||||||
TEMPLATE_DEBUG = DEBUG
|
|
||||||
|
|
||||||
INSTALLED_APPS += INSTALLED_PLUGINS
|
INSTALLED_APPS += INSTALLED_PLUGINS
|
||||||
|
|
||||||
@ -31,7 +29,6 @@ INSTALLED_APPS += INSTALLED_PLUGINS
|
|||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': ''
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
tests/unit/__init__.py
Normal file
0
tests/unit/__init__.py
Normal file
0
tests/unit/users/__init__.py
Normal file
0
tests/unit/users/__init__.py
Normal file
184
tests/unit/users/test_api.py
Normal file
184
tests/unit/users/test_api.py
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
from unittest.mock import patch, call, MagicMock
|
||||||
|
|
||||||
|
from openslides.users.api import (
|
||||||
|
gen_username,
|
||||||
|
gen_password,
|
||||||
|
get_registered_group,
|
||||||
|
create_or_reset_admin_user,
|
||||||
|
get_protected_perm)
|
||||||
|
|
||||||
|
|
||||||
|
@patch('openslides.users.api.User')
|
||||||
|
class UserGenUsername(TestCase):
|
||||||
|
"""
|
||||||
|
Tests for the function gen_username.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_clear_strings(self, mock_user):
|
||||||
|
mock_user.objects.filter().exists.return_value = False
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
gen_username('foo', 'bar'),
|
||||||
|
'foo bar')
|
||||||
|
|
||||||
|
def test_unstripped_strings(self, mock_user):
|
||||||
|
mock_user.objects.filter().exists.return_value = False
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
gen_username('foo ', ' bar\n'),
|
||||||
|
'foo bar',
|
||||||
|
"The retuned value should only have one whitespace between the names")
|
||||||
|
|
||||||
|
def test_empty_second_string(self, mock_user):
|
||||||
|
mock_user.objects.filter().exists.return_value = False
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
gen_username('foobar', ''),
|
||||||
|
'foobar',
|
||||||
|
"The returned value should not have whitespaces at the end")
|
||||||
|
|
||||||
|
def test_empty_first_string(self, mock_user):
|
||||||
|
mock_user.objects.filter().exists.return_value = False
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
gen_username('', 'foobar'),
|
||||||
|
'foobar',
|
||||||
|
"The returned value should not have whitespaces at the beginning")
|
||||||
|
|
||||||
|
def test_two_empty_strings(self, mock_user):
|
||||||
|
mock_user.objects.filter().exists.return_value = False
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError,
|
||||||
|
msg="A ValueError should be raised"):
|
||||||
|
gen_username('', '')
|
||||||
|
|
||||||
|
def test_used_username(self, mock_user):
|
||||||
|
mock_user.objects.filter().exists.side_effect = (True, False)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
gen_username('user', 'name'),
|
||||||
|
'user name 1',
|
||||||
|
"If the username already exist, a number should be added to the name")
|
||||||
|
|
||||||
|
def test_two_used_username(self, mock_user):
|
||||||
|
mock_user.objects.filter().exists.side_effect = (True, True, False)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
gen_username('user', 'name'),
|
||||||
|
'user name 2',
|
||||||
|
"If the username with a number already exist, a higher number should "
|
||||||
|
"be added to the name")
|
||||||
|
|
||||||
|
def test_umlauts(self, mock_user):
|
||||||
|
mock_user.objects.filter().exists.return_value = False
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
gen_username('äöü', 'ßüäö'),
|
||||||
|
'äöü ßüäö',
|
||||||
|
"gen_username has also to work with umlauts")
|
||||||
|
|
||||||
|
|
||||||
|
@patch('openslides.users.api.choice')
|
||||||
|
class GenPassword(TestCase):
|
||||||
|
def test_normal(self, mock_choice):
|
||||||
|
"""
|
||||||
|
Test normal run of the function
|
||||||
|
"""
|
||||||
|
mock_choice.side_effect = tuple('test_password')
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
gen_password(),
|
||||||
|
'test_pas')
|
||||||
|
# choice has to be called 8 times
|
||||||
|
mock_choice.assert_has_calls(
|
||||||
|
[call("abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789")
|
||||||
|
for _ in range(8)])
|
||||||
|
|
||||||
|
|
||||||
|
@patch('openslides.users.api.Group')
|
||||||
|
class GetRegisteredGroup(TestCase):
|
||||||
|
def test_normal(self, mock_group):
|
||||||
|
mock_group.objects.get.return_value = 'test_group'
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
get_registered_group(),
|
||||||
|
'test_group')
|
||||||
|
mock_group.objects.getassert_called_once_with(pk=2)
|
||||||
|
|
||||||
|
|
||||||
|
@patch('openslides.users.api.Group')
|
||||||
|
@patch('openslides.users.api.User')
|
||||||
|
class CreateOrResetAdminUser(TestCase):
|
||||||
|
def test_get_admin_group(self, mock_user, mock_group):
|
||||||
|
"""
|
||||||
|
Tests, that the Group with pk4 is added to the admin
|
||||||
|
"""
|
||||||
|
admin_user = MagicMock(name='admin_user')
|
||||||
|
mock_user.objects.get.return_value = admin_user
|
||||||
|
mock_group.objects.get.return_value = 'admin_group'
|
||||||
|
|
||||||
|
create_or_reset_admin_user()
|
||||||
|
|
||||||
|
mock_group.objects.get.assert_called_once_with(pk=4)
|
||||||
|
admin_user.groups.add.assert_called_once_with('admin_group')
|
||||||
|
|
||||||
|
def test_password_set_to_admin(self, mock_user, mock_group):
|
||||||
|
"""
|
||||||
|
Tests, that the password of the admin is set to 'admin'.
|
||||||
|
"""
|
||||||
|
admin_user = MagicMock(name='admin_user')
|
||||||
|
mock_user.objects.get.return_value = admin_user
|
||||||
|
|
||||||
|
create_or_reset_admin_user()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
admin_user.default_password,
|
||||||
|
'admin')
|
||||||
|
admin_user.set_password.assert_called_once_with('admin')
|
||||||
|
admin_user.save.assert_called_once_with()
|
||||||
|
|
||||||
|
def test_return_value(self, mock_user, mock_group):
|
||||||
|
"""
|
||||||
|
Test, that the function retruns True, when a user is created.
|
||||||
|
"""
|
||||||
|
mock_user.DoesNotExist = Exception
|
||||||
|
mock_user.objects.get.side_effect = Exception
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
create_or_reset_admin_user(),
|
||||||
|
True,
|
||||||
|
"create_or_reset_admin_user should return True when a new user is "
|
||||||
|
" created")
|
||||||
|
|
||||||
|
def test_attributes_of_created_user(self, mock_user, mock_group):
|
||||||
|
admin_user = MagicMock(name='admin_user')
|
||||||
|
mock_user.return_value = admin_user
|
||||||
|
mock_user.DoesNotExist = Exception
|
||||||
|
mock_user.objects.get.side_effect = Exception
|
||||||
|
|
||||||
|
create_or_reset_admin_user()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
admin_user.username,
|
||||||
|
'admin',
|
||||||
|
"The username of a new created admin should be 'admin'")
|
||||||
|
self.assertEqual(
|
||||||
|
admin_user.last_name,
|
||||||
|
'Administrator',
|
||||||
|
"The last_name of a new created admin should be 'Administrator'")
|
||||||
|
|
||||||
|
|
||||||
|
@patch('openslides.users.api.Permission')
|
||||||
|
class GetProtectedPerm(TestCase):
|
||||||
|
def test_normal(self, mock_permission):
|
||||||
|
mock_permission.objects.get_by_natural_key.return_value = 'test_permission'
|
||||||
|
|
||||||
|
value = get_protected_perm()
|
||||||
|
|
||||||
|
mock_permission.objects.get_by_natural_key.assert_called_once_with(
|
||||||
|
app_label='users', model='user', codename='can_manage')
|
||||||
|
self.assertEqual(
|
||||||
|
value,
|
||||||
|
'test_permission',
|
||||||
|
"The function should return the user.can_manage permission")
|
140
tests/unit/users/test_auth.py
Normal file
140
tests/unit/users/test_auth.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
|
from openslides.users.auth import AnonymousUser, get_user, auth
|
||||||
|
|
||||||
|
|
||||||
|
class TestAnonymousUser(TestCase):
|
||||||
|
def test_get_all_permissions_from_group_1(self):
|
||||||
|
"""
|
||||||
|
Tests, that get_all_permissions looks in the permissions of the group with
|
||||||
|
pk=1
|
||||||
|
"""
|
||||||
|
anonymous = AnonymousUser()
|
||||||
|
|
||||||
|
with patch('openslides.users.auth.Permission') as mock_permission:
|
||||||
|
anonymous.get_all_permissions()
|
||||||
|
|
||||||
|
mock_permission.objects.filter.assert_called_once_with(group__pk=1)
|
||||||
|
|
||||||
|
def test_has_perm_in_list(self):
|
||||||
|
anonymous = AnonymousUser()
|
||||||
|
anonymous.get_all_permissions = MagicMock(return_value=('p1', 'p2'))
|
||||||
|
|
||||||
|
self.assertTrue(
|
||||||
|
anonymous.has_perm('p1'),
|
||||||
|
"has_perm() should return True when the user has the permission")
|
||||||
|
|
||||||
|
def test_has_perm_not_in_list(self):
|
||||||
|
anonymous = AnonymousUser()
|
||||||
|
anonymous.get_all_permissions = MagicMock(return_value=('p1', 'p2'))
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
anonymous.has_perm('p3'),
|
||||||
|
"has_perm() should return False when the user has not the permission")
|
||||||
|
|
||||||
|
def test_has_module_perms_in_list(self):
|
||||||
|
anonymous = AnonymousUser()
|
||||||
|
anonymous.get_all_permissions = MagicMock(return_value=('test_app.perm', ))
|
||||||
|
|
||||||
|
self.assertTrue(
|
||||||
|
anonymous.has_module_perms('test_app'),
|
||||||
|
"has_module_perms() should return True when the user has the "
|
||||||
|
"permission test_app.perm")
|
||||||
|
|
||||||
|
def test_has_module_perms_not_in_list(self):
|
||||||
|
anonymous = AnonymousUser()
|
||||||
|
anonymous.get_all_permissions = MagicMock(return_value=('test_otherapp.perm', ))
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
anonymous.has_module_perms('test_app'),
|
||||||
|
"has_module_perms() should return False when the user does not have "
|
||||||
|
"the permission test_app.perm")
|
||||||
|
|
||||||
|
|
||||||
|
@patch('openslides.users.auth.config')
|
||||||
|
@patch('openslides.users.auth._get_user')
|
||||||
|
class TestGetUser(TestCase):
|
||||||
|
def test_not_in_cache(self, mock_get_user, mock_config):
|
||||||
|
mock_config.__getitem__.return_value = True
|
||||||
|
mock_get_user.return_value = AnonymousUser()
|
||||||
|
request = MagicMock()
|
||||||
|
del request._cached_user
|
||||||
|
|
||||||
|
user = get_user(request)
|
||||||
|
|
||||||
|
mock_get_user.assert_called_once_with(request)
|
||||||
|
self.assertEqual(user, AnonymousUser())
|
||||||
|
self.assertEqual(request._cached_user, AnonymousUser())
|
||||||
|
|
||||||
|
def test_in_cache(self, mock_get_user, mock_config):
|
||||||
|
request = MagicMock()
|
||||||
|
request._cached_user = 'my_user'
|
||||||
|
|
||||||
|
user = get_user(request)
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
mock_get_user.called,
|
||||||
|
"_get_user should not have been called when the user object is in cache")
|
||||||
|
self.assertEqual(
|
||||||
|
user,
|
||||||
|
'my_user',
|
||||||
|
"The user in cache should be returned")
|
||||||
|
|
||||||
|
def test_disabled_anonymous_user(self, mock_get_user, mock_config):
|
||||||
|
mock_config.__getitem__.return_value = False
|
||||||
|
mock_get_user.return_value = 'django_anonymous_user'
|
||||||
|
request = MagicMock()
|
||||||
|
del request._cached_user
|
||||||
|
|
||||||
|
user = get_user(request)
|
||||||
|
|
||||||
|
mock_get_user.assert_called_once_with(request)
|
||||||
|
self.assertEqual(
|
||||||
|
user,
|
||||||
|
'django_anonymous_user',
|
||||||
|
"The django user should be returned")
|
||||||
|
self.assertEqual(
|
||||||
|
request._cached_user,
|
||||||
|
'django_anonymous_user',
|
||||||
|
"The django user should be cached")
|
||||||
|
|
||||||
|
|
||||||
|
@patch('openslides.users.auth.config')
|
||||||
|
@patch('openslides.users.auth._auth')
|
||||||
|
class TestAuth(TestCase):
|
||||||
|
def test_anonymous_enabled(self, mock_auth, mock_config):
|
||||||
|
mock_config.__getitem__.return_value = True
|
||||||
|
request = MagicMock()
|
||||||
|
mock_auth.return_value = {'user': AnonymousUser()}
|
||||||
|
|
||||||
|
context = auth(request)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
context,
|
||||||
|
{'user': AnonymousUser(),
|
||||||
|
'os_enable_anonymous_login': True})
|
||||||
|
|
||||||
|
def test_anonymous_disabled(self, mock_auth, mock_config):
|
||||||
|
mock_config.__getitem__.return_value = False
|
||||||
|
request = MagicMock()
|
||||||
|
mock_auth.return_value = {'user': AnonymousUser()}
|
||||||
|
|
||||||
|
context = auth(request)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
context,
|
||||||
|
{'user': AnonymousUser(),
|
||||||
|
'os_enable_anonymous_login': False})
|
||||||
|
|
||||||
|
def test_logged_in_user_in_request(self, mock_auth, mock_config):
|
||||||
|
mock_config.__getitem__.return_value = True
|
||||||
|
request = MagicMock()
|
||||||
|
mock_auth.return_value = {'user': 'logged_in_user'}
|
||||||
|
|
||||||
|
context = auth(request)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
context,
|
||||||
|
{'user': 'logged_in_user',
|
||||||
|
'os_enable_anonymous_login': True})
|
312
tests/unit/users/test_models.py
Normal file
312
tests/unit/users/test_models.py
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
from openslides.users.models import User, UserManager
|
||||||
|
|
||||||
|
|
||||||
|
class UserTest(TestCase):
|
||||||
|
def test_str(self):
|
||||||
|
"""
|
||||||
|
Tests, that the str representaion of a User object returns the same as
|
||||||
|
User.get_full_name().
|
||||||
|
"""
|
||||||
|
user = User()
|
||||||
|
user.get_full_name = MagicMock(return_value='Test Value')
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
str(user),
|
||||||
|
'Test Value',
|
||||||
|
"The str representation of User is not user.get_full_name()")
|
||||||
|
|
||||||
|
def test_get_slide_context(self):
|
||||||
|
"""
|
||||||
|
Tests, that get_slide_context returns:
|
||||||
|
|
||||||
|
{'shown_user': self}
|
||||||
|
"""
|
||||||
|
user = User()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
user.get_slide_context(),
|
||||||
|
{'shown_user': user},
|
||||||
|
"User.get_slide_context returns a wrong context")
|
||||||
|
|
||||||
|
|
||||||
|
class UserGetAbsoluteUrlTest(TestCase):
|
||||||
|
def test_get_absolute_url_default(self):
|
||||||
|
"""
|
||||||
|
Tests get_absolute_url() with no argument.
|
||||||
|
|
||||||
|
It should return the url for the url-pattern of user_detail
|
||||||
|
"""
|
||||||
|
user = User(pk=5)
|
||||||
|
|
||||||
|
with patch('openslides.users.models.reverse') as mock_reverse:
|
||||||
|
mock_reverse.return_value = 'test url'
|
||||||
|
url = user.get_absolute_url()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
url,
|
||||||
|
'test url',
|
||||||
|
"User.get_absolute_url() does not return the result of reverse")
|
||||||
|
mock_reverse.assert_called_once_with('user_detail', args=['5'])
|
||||||
|
|
||||||
|
def test_get_absolute_url_detail(self):
|
||||||
|
"""
|
||||||
|
Tests get_absolute_url() with 'detail' as argument
|
||||||
|
"""
|
||||||
|
user = User(pk=5)
|
||||||
|
|
||||||
|
with patch('openslides.users.models.reverse') as mock_reverse:
|
||||||
|
mock_reverse.return_value = 'test url'
|
||||||
|
url = user.get_absolute_url('detail')
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
url,
|
||||||
|
'test url',
|
||||||
|
"User.get_absolute_url('detail') does not return the result of reverse")
|
||||||
|
mock_reverse.assert_called_once_with('user_detail', args=['5'])
|
||||||
|
|
||||||
|
def test_get_absolute_url_update(self):
|
||||||
|
"""
|
||||||
|
Tests get_absolute_url() with 'update' as argument
|
||||||
|
"""
|
||||||
|
user = User(pk=5)
|
||||||
|
|
||||||
|
with patch('openslides.users.models.reverse') as mock_reverse:
|
||||||
|
mock_reverse.return_value = 'test url'
|
||||||
|
url = user.get_absolute_url('update')
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
url,
|
||||||
|
'test url',
|
||||||
|
"User.get_absolute_url('update') does not return the result of reverse")
|
||||||
|
mock_reverse.assert_called_once_with('user_update', args=['5'])
|
||||||
|
|
||||||
|
def test_get_absolute_url_delete(self):
|
||||||
|
"""
|
||||||
|
Tests get_absolute_url() with 'delete' as argument
|
||||||
|
"""
|
||||||
|
user = User(pk=5)
|
||||||
|
|
||||||
|
with patch('openslides.users.models.reverse') as mock_reverse:
|
||||||
|
mock_reverse.return_value = 'test url'
|
||||||
|
url = user.get_absolute_url('delete')
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
url,
|
||||||
|
'test url',
|
||||||
|
"User.get_absolute_url('delete') does not return the result of reverse")
|
||||||
|
mock_reverse.assert_called_once_with('user_delete', args=['5'])
|
||||||
|
|
||||||
|
def test_get_absolute_url_other(self):
|
||||||
|
"""
|
||||||
|
Tests get_absolute_url() with any other argument
|
||||||
|
"""
|
||||||
|
user = User(pk=5)
|
||||||
|
dummy_argument = MagicMock()
|
||||||
|
|
||||||
|
with patch('builtins.super') as mock_super:
|
||||||
|
mock_super().get_absolute_url.return_value = 'test url'
|
||||||
|
url = user.get_absolute_url(dummy_argument)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
url,
|
||||||
|
'test url',
|
||||||
|
"User.get_absolute_url(OTHER) does not return the result of reverse")
|
||||||
|
mock_super().get_absolute_url.assert_called_once_with(dummy_argument)
|
||||||
|
|
||||||
|
|
||||||
|
class UserGetFullName(TestCase):
|
||||||
|
def test_get_full_name_with_structure_level_and_title(self):
|
||||||
|
"""
|
||||||
|
Tests, that get_full_name returns the write string.
|
||||||
|
"""
|
||||||
|
user = User()
|
||||||
|
user.title = 'test_title'
|
||||||
|
user.structure_level = 'test_structure_level'
|
||||||
|
user.get_short_name = MagicMock(return_value='test_short_name')
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
user.get_full_name(),
|
||||||
|
'test_title test_short_name (test_structure_level)',
|
||||||
|
"User.get_full_name() returns wrong string when it has a structure_level and title")
|
||||||
|
|
||||||
|
def test_get_full_name_without_structure_level_and_with_title(self):
|
||||||
|
"""
|
||||||
|
Tests, that get_full_name returns the write string.
|
||||||
|
"""
|
||||||
|
user = User()
|
||||||
|
user.title = 'test_title'
|
||||||
|
user.structure_level = ''
|
||||||
|
user.get_short_name = MagicMock(return_value='test_short_name')
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
user.get_full_name(),
|
||||||
|
'test_title test_short_name',
|
||||||
|
"User.get_full_name() returns wrong string when it has no structure_level but a title")
|
||||||
|
|
||||||
|
def test_get_full_name_without_structure_level_and_without_title(self):
|
||||||
|
"""
|
||||||
|
Tests, that get_full_name returns the write string.
|
||||||
|
"""
|
||||||
|
user = User()
|
||||||
|
user.title = ''
|
||||||
|
user.structure_level = ''
|
||||||
|
user.get_short_name = MagicMock(return_value='test_short_name')
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
user.get_full_name(),
|
||||||
|
'test_short_name',
|
||||||
|
"User.get_full_name() returns wrong string when it has no structure_level and no title")
|
||||||
|
|
||||||
|
|
||||||
|
class UserGetShortName(TestCase):
|
||||||
|
def test_get_short_name_sort_first_name_only_first_name(self):
|
||||||
|
"""
|
||||||
|
Tests the output of get_short_name.
|
||||||
|
"""
|
||||||
|
user = User()
|
||||||
|
user.first_name = 'test_first_name'
|
||||||
|
|
||||||
|
with patch('openslides.users.models.config') as mock_config:
|
||||||
|
mock_config.__getitem__.return_value = True
|
||||||
|
short_name = user.get_short_name()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
short_name,
|
||||||
|
'test_first_name',
|
||||||
|
"User.get_short_name() returns wrong string when it has only a "
|
||||||
|
"first_name and is sorted by first_name")
|
||||||
|
|
||||||
|
def test_get_short_name_sort_first_name_both_names(self):
|
||||||
|
"""
|
||||||
|
Tests the output of get_short_name.
|
||||||
|
"""
|
||||||
|
user = User()
|
||||||
|
user.first_name = 'test_first_name'
|
||||||
|
user.last_name = 'test_last_name'
|
||||||
|
|
||||||
|
with patch('openslides.users.models.config') as mock_config:
|
||||||
|
mock_config.__getitem__.return_value = True
|
||||||
|
short_name = user.get_short_name()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
short_name,
|
||||||
|
'test_first_name test_last_name',
|
||||||
|
"User.get_short_name() returns wrong string when it has a fist_name "
|
||||||
|
"and a last_name and is sorted by first_name")
|
||||||
|
|
||||||
|
def test_get_short_name_sort_last_name_only_first_name(self):
|
||||||
|
"""
|
||||||
|
Tests the output of get_short_name.
|
||||||
|
"""
|
||||||
|
user = User()
|
||||||
|
user.first_name = 'test_first_name'
|
||||||
|
|
||||||
|
with patch('openslides.users.models.config') as mock_config:
|
||||||
|
mock_config.__getitem__.return_value = False
|
||||||
|
short_name = user.get_short_name()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
short_name,
|
||||||
|
'test_first_name',
|
||||||
|
"User.get_short_name() returns wrong string when it has only a "
|
||||||
|
"first_name and is sorted by last_name")
|
||||||
|
|
||||||
|
def test_get_short_name_sort_last_name_both_names(self):
|
||||||
|
"""
|
||||||
|
Tests the output of get_short_name.
|
||||||
|
"""
|
||||||
|
user = User()
|
||||||
|
user.first_name = 'test_first_name'
|
||||||
|
user.last_name = 'test_last_name'
|
||||||
|
|
||||||
|
with patch('openslides.users.models.config') as mock_config:
|
||||||
|
mock_config.__getitem__.return_value = False
|
||||||
|
short_name = user.get_short_name()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
short_name,
|
||||||
|
'test_last_name, test_first_name',
|
||||||
|
"User.get_short_name() returns wrong string when it has a fist_name "
|
||||||
|
"and a last_name and is sorted by last_name")
|
||||||
|
|
||||||
|
def test_get_short_name_no_names(self):
|
||||||
|
"""
|
||||||
|
Tests the output of get_short_name.
|
||||||
|
"""
|
||||||
|
user = User(username='test_username')
|
||||||
|
|
||||||
|
with patch('openslides.users.models.config') as mock_config:
|
||||||
|
mock_config.__getitem__.return_value = False
|
||||||
|
short_name = user.get_short_name()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
short_name,
|
||||||
|
'test_username',
|
||||||
|
"User.get_short_name() returns wrong string when it has no fist_name "
|
||||||
|
"and no last_name and is sorted by last_name")
|
||||||
|
|
||||||
|
def test_while_spaces_in_name_parts(self):
|
||||||
|
"""
|
||||||
|
Tests the output if the name parts have white spaces at the begin or
|
||||||
|
end.
|
||||||
|
"""
|
||||||
|
user = User()
|
||||||
|
user.first_name = ' test_first_name\n '
|
||||||
|
user.last_name = ' test_last_name \n'
|
||||||
|
|
||||||
|
with patch('openslides.users.models.config') as mock_config:
|
||||||
|
mock_config.__getitem__.return_value = True
|
||||||
|
short_name = user.get_short_name()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
short_name,
|
||||||
|
'test_first_name test_last_name',
|
||||||
|
"User.get_short_name() has to strip whitespaces from the name parts")
|
||||||
|
|
||||||
|
|
||||||
|
class UserResetPassword(TestCase):
|
||||||
|
def test_reset_password_no_attribute(self):
|
||||||
|
"""
|
||||||
|
Tests reset_password with no attribute.
|
||||||
|
"""
|
||||||
|
user = User(default_password='test_default_password')
|
||||||
|
user.set_password = MagicMock()
|
||||||
|
|
||||||
|
user.reset_password()
|
||||||
|
|
||||||
|
user.set_password.assert_called_once_with('test_default_password')
|
||||||
|
|
||||||
|
def test_reset_password_with_attribute(self):
|
||||||
|
"""
|
||||||
|
Tests reset_password with no attribute.
|
||||||
|
"""
|
||||||
|
user = User(default_password='test_default_password')
|
||||||
|
user.set_password = MagicMock()
|
||||||
|
|
||||||
|
user.reset_password('test_password')
|
||||||
|
|
||||||
|
user.set_password.assert_called_once_with('test_password')
|
||||||
|
|
||||||
|
|
||||||
|
class UserManagerTest(TestCase):
|
||||||
|
def test_create_user(self):
|
||||||
|
"""
|
||||||
|
Tests, that create_user saves a new user with a set password.
|
||||||
|
"""
|
||||||
|
user = MagicMock()
|
||||||
|
user_manager = UserManager()
|
||||||
|
user_manager.model = MagicMock(return_value=user)
|
||||||
|
user_manager._db = 'my_test_db'
|
||||||
|
|
||||||
|
return_user = user_manager.create_user('test_username', 'test_password', test_kwarg='test_kwarg')
|
||||||
|
|
||||||
|
user_manager.model.assert_called_once_with(username='test_username', test_kwarg='test_kwarg')
|
||||||
|
user.set_password.assert_called_once_with('test_password')
|
||||||
|
user.save.assert_called_once_with(using='my_test_db')
|
||||||
|
self.assertEqual(
|
||||||
|
return_user,
|
||||||
|
user,
|
||||||
|
"The returned user is not the created user")
|
0
tests/unit/utils/__init__.py
Normal file
0
tests/unit/utils/__init__.py
Normal file
16
tests/unit/utils/test_models.py
Normal file
16
tests/unit/utils/test_models.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from openslides.utils.models import AbsoluteUrlMixin
|
||||||
|
|
||||||
|
|
||||||
|
class TestAbsoluteUrlMixin(TestCase):
|
||||||
|
def test_get_absolute_url(self):
|
||||||
|
"""
|
||||||
|
Tests, that AbsoluteUrlMixin raises a ValueError if called.
|
||||||
|
"""
|
||||||
|
object = AbsoluteUrlMixin()
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
ValueError,
|
||||||
|
'Unknown Link "argument" for model "<class \'openslides.utils.models.AbsoluteUrlMixin\'>"'):
|
||||||
|
object.get_absolute_url('argument')
|
@ -1,9 +1,10 @@
|
|||||||
from openslides.utils.test import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from openslides.utils.utils import html_strong, int_or_none
|
from openslides.utils.utils import html_strong, int_or_none
|
||||||
|
|
||||||
|
|
||||||
class Test_functions(TestCase):
|
class Test_functions(TestCase):
|
||||||
def test_string(self):
|
def test_html_strong(self):
|
||||||
self.assertEqual(html_strong('some text'), '<strong>some text</strong>')
|
self.assertEqual(html_strong('some text'), '<strong>some text</strong>')
|
||||||
|
|
||||||
def test_int_or_none(self):
|
def test_int_or_none(self):
|
318
tests/unit/utils/test_views.py
Normal file
318
tests/unit/utils/test_views.py
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
|
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
||||||
|
|
||||||
|
from openslides.utils import views
|
||||||
|
|
||||||
|
|
||||||
|
@patch('builtins.super')
|
||||||
|
class LoginMixinTest(TestCase):
|
||||||
|
def test_dispatch(self, mock_super):
|
||||||
|
"""
|
||||||
|
Tests that the function calls super
|
||||||
|
"""
|
||||||
|
# TODO: find a way to test the call of the decorator.
|
||||||
|
view = views.LoginMixin()
|
||||||
|
request = MagicMock()
|
||||||
|
|
||||||
|
view.dispatch(request)
|
||||||
|
|
||||||
|
mock_super().dispatch.assert_called_once_with(request)
|
||||||
|
|
||||||
|
|
||||||
|
class PermissionMixinTest(TestCase):
|
||||||
|
def test_check_permission_non_required_permission(self):
|
||||||
|
view = views.PermissionMixin()
|
||||||
|
view.required_permission = None
|
||||||
|
request = MagicMock()
|
||||||
|
|
||||||
|
self.assertTrue(view.check_permission(request))
|
||||||
|
|
||||||
|
def test_check_permission_with_required_permission(self):
|
||||||
|
view = views.PermissionMixin()
|
||||||
|
view.required_permission = 'required_permission'
|
||||||
|
request = MagicMock()
|
||||||
|
|
||||||
|
view.check_permission(request)
|
||||||
|
|
||||||
|
request.user.has_perm.assert_called_once_with('required_permission')
|
||||||
|
|
||||||
|
@patch('builtins.super')
|
||||||
|
def test_dispatch_with_perm(self, mock_super):
|
||||||
|
view = views.PermissionMixin()
|
||||||
|
view.check_permission = MagicMock(return_value=True)
|
||||||
|
request = MagicMock()
|
||||||
|
|
||||||
|
view.dispatch(request)
|
||||||
|
|
||||||
|
mock_super().dispatch.called_once_with(request)
|
||||||
|
|
||||||
|
@patch('openslides.utils.views.settings')
|
||||||
|
@patch('openslides.utils.views.HttpResponseRedirect')
|
||||||
|
@patch('builtins.super')
|
||||||
|
def test_dispatch_without_perm_logged_out(self, mock_super, mock_response, mock_settings):
|
||||||
|
view = views.PermissionMixin()
|
||||||
|
view.check_permission = MagicMock(return_value=False)
|
||||||
|
request = MagicMock()
|
||||||
|
request.user.is_authenticated.return_value = False
|
||||||
|
request.get_full_path.return_value = '/requested/path/'
|
||||||
|
mock_settings.LOGIN_URL = 'my_login_url'
|
||||||
|
|
||||||
|
value = view.dispatch(request)
|
||||||
|
|
||||||
|
mock_response.assert_called_once_with('my_login_url?next=/requested/path/')
|
||||||
|
self.assertEqual(value, mock_response())
|
||||||
|
|
||||||
|
@patch('openslides.utils.views.settings')
|
||||||
|
@patch('openslides.utils.views.HttpResponseRedirect')
|
||||||
|
@patch('builtins.super')
|
||||||
|
def test_dispatch_without_perm_logged_in(self, mock_super, mock_response, mock_settings):
|
||||||
|
view = views.PermissionMixin()
|
||||||
|
view.check_permission = MagicMock(return_value=False)
|
||||||
|
request = MagicMock()
|
||||||
|
request.user.is_authenticated.return_value = True
|
||||||
|
|
||||||
|
with self.assertRaises(PermissionDenied):
|
||||||
|
view.dispatch(request)
|
||||||
|
|
||||||
|
|
||||||
|
class AjaxMixinTest(TestCase):
|
||||||
|
@patch('openslides.utils.views.json')
|
||||||
|
@patch('openslides.utils.views.HttpResponse')
|
||||||
|
def test_ajax_get(self, mock_response, mock_json):
|
||||||
|
view = views.AjaxMixin()
|
||||||
|
view.get_ajax_context = MagicMock(return_value='context')
|
||||||
|
mock_json.dumps.return_value = 'json'
|
||||||
|
|
||||||
|
view.ajax_get(MagicMock())
|
||||||
|
|
||||||
|
mock_response.assert_called_once_with('json')
|
||||||
|
mock_json.dumps.assert_called_once_with('context')
|
||||||
|
|
||||||
|
def test_get_ajax_context(self):
|
||||||
|
view = views.AjaxMixin()
|
||||||
|
|
||||||
|
context = view.get_ajax_context(t1=1, t2=2, t3=3)
|
||||||
|
|
||||||
|
self.assertEqual(context, {'t1': 1, 't2': 2, 't3': 3})
|
||||||
|
|
||||||
|
|
||||||
|
class ExtraContextMixin(TestCase):
|
||||||
|
@patch('openslides.utils.views.template_manipulation')
|
||||||
|
@patch('builtins.super')
|
||||||
|
def test_get_context_data(self, mock_super, mock_signal):
|
||||||
|
"""
|
||||||
|
Tests that super is called with the kwargs, that the signal is called
|
||||||
|
with the returnd context and that the context is returned.
|
||||||
|
"""
|
||||||
|
view = views.ExtraContextMixin()
|
||||||
|
view.request = 'test_request'
|
||||||
|
mock_super().get_context_data.return_value = 'new_context'
|
||||||
|
|
||||||
|
returned_context = view.get_context_data(a1=1, a2=2)
|
||||||
|
|
||||||
|
mock_super().get_context_data.assert_called_once_with(a1=1, a2=2)
|
||||||
|
mock_signal.send.assert_called_once_with(
|
||||||
|
sender=views.ExtraContextMixin,
|
||||||
|
request='test_request',
|
||||||
|
context='new_context')
|
||||||
|
self.assertEqual(returned_context, 'new_context')
|
||||||
|
|
||||||
|
|
||||||
|
@patch('openslides.utils.views.reverse')
|
||||||
|
class UrlMixinGetUrl(TestCase):
|
||||||
|
"""
|
||||||
|
Tests the method 'get_url' from the UrlMixin.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_url_name(self, reverse):
|
||||||
|
"""
|
||||||
|
Tests that the return value of reverse(url_pattern) is returned.
|
||||||
|
"""
|
||||||
|
view = views.UrlMixin()
|
||||||
|
reverse.return_value = 'reverse_url'
|
||||||
|
|
||||||
|
returned_url = view.get_url('test_url_name')
|
||||||
|
|
||||||
|
reverse.assert_called_once_with('test_url_name', args=[])
|
||||||
|
self.assertEqual(returned_url, 'reverse_url')
|
||||||
|
|
||||||
|
def test_url_name_with_args(self, reverse):
|
||||||
|
"""
|
||||||
|
Tests that the return value of reverse(url_pattern) with args is returned.
|
||||||
|
"""
|
||||||
|
view = views.UrlMixin()
|
||||||
|
reverse.return_value = 'reverse_url'
|
||||||
|
|
||||||
|
returned_url = view.get_url('test_url_name', args=[1, 2, 3])
|
||||||
|
|
||||||
|
reverse.assert_called_once_with('test_url_name', args=[1, 2, 3])
|
||||||
|
self.assertEqual(returned_url, 'reverse_url')
|
||||||
|
|
||||||
|
def test_url(self, reverse):
|
||||||
|
view = views.UrlMixin()
|
||||||
|
|
||||||
|
returned_url = view.get_url(url='my_url')
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
reverse.called,
|
||||||
|
"reverse should not be called")
|
||||||
|
self.assertEqual(returned_url, 'my_url')
|
||||||
|
|
||||||
|
def test_priority_of_url_name(self, reverse):
|
||||||
|
view = views.UrlMixin()
|
||||||
|
reverse.return_value = 'reverse_url'
|
||||||
|
|
||||||
|
returned_url = view.get_url(url_name='test_url_name', url='my_url')
|
||||||
|
|
||||||
|
reverse.assert_called_once_with('test_url_name', args=[])
|
||||||
|
self.assertEqual(returned_url, 'reverse_url')
|
||||||
|
|
||||||
|
def test_get_absolute_url(self, reverse):
|
||||||
|
view = views.UrlMixin()
|
||||||
|
view.object = MagicMock()
|
||||||
|
view.object.get_absolute_url.return_value = 'object_url'
|
||||||
|
|
||||||
|
returned_url = view.get_url()
|
||||||
|
|
||||||
|
view.object.get_absolute_url.assert_called_once_with()
|
||||||
|
self.assertEqual(returned_url, 'object_url')
|
||||||
|
self.assertFalse(
|
||||||
|
reverse.called,
|
||||||
|
"reverse should not be called")
|
||||||
|
|
||||||
|
def test_get_absolute_url_with_link(self, reverse):
|
||||||
|
view = views.UrlMixin()
|
||||||
|
view.object = MagicMock()
|
||||||
|
view.object.get_absolute_url.return_value = 'object_url'
|
||||||
|
|
||||||
|
returned_url = view.get_url(use_absolute_url_link='test_link')
|
||||||
|
|
||||||
|
view.object.get_absolute_url.assert_called_once_with('test_link')
|
||||||
|
self.assertEqual(returned_url, 'object_url')
|
||||||
|
self.assertFalse(
|
||||||
|
reverse.called,
|
||||||
|
"reverse should not be called")
|
||||||
|
|
||||||
|
def test_get_absolute_url_with_invalid_object(self, reverse):
|
||||||
|
view = views.UrlMixin()
|
||||||
|
view.object = MagicMock()
|
||||||
|
del view.object.get_absolute_url
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
ImproperlyConfigured,
|
||||||
|
'No url to redirect to\. See openslides\.utils\.views\.UrlMixin '
|
||||||
|
'for more details\.'):
|
||||||
|
view.get_url()
|
||||||
|
|
||||||
|
|
||||||
|
class UrlMixinGetUrlNameArgs(TestCase):
|
||||||
|
"""
|
||||||
|
Tests the method 'get_url_name_args' from the UrlMixin.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_has_attribute(self):
|
||||||
|
view = views.UrlMixin()
|
||||||
|
view.url_name_args = 'name_args'
|
||||||
|
|
||||||
|
returned_args = view.get_url_name_args()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
returned_args,
|
||||||
|
'name_args',
|
||||||
|
"The object attribute 'url_name_args' should be returned")
|
||||||
|
|
||||||
|
def test_without_attribute_with_object_with_pk(self):
|
||||||
|
view = views.UrlMixin()
|
||||||
|
view.object = MagicMock()
|
||||||
|
view.object.pk = 5
|
||||||
|
|
||||||
|
returned_args = view.get_url_name_args()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
returned_args,
|
||||||
|
[5],
|
||||||
|
"object.pk should be returned as a one element list")
|
||||||
|
|
||||||
|
def test_without_attribute_with_object_with_pk_is_none(self):
|
||||||
|
view = views.UrlMixin()
|
||||||
|
view.object = MagicMock()
|
||||||
|
view.object.pk = None
|
||||||
|
|
||||||
|
returned_args = view.get_url_name_args()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
returned_args,
|
||||||
|
[],
|
||||||
|
"An empty list should be returned")
|
||||||
|
|
||||||
|
def test_without_attribute_with_object_without_pk(self):
|
||||||
|
view = views.UrlMixin()
|
||||||
|
view.object = MagicMock()
|
||||||
|
del view.object.pk
|
||||||
|
|
||||||
|
returned_args = view.get_url_name_args()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
returned_args,
|
||||||
|
[],
|
||||||
|
"An empty list should be returned")
|
||||||
|
|
||||||
|
def test_without_attribute_without_object(self):
|
||||||
|
view = views.UrlMixin()
|
||||||
|
|
||||||
|
returned_args = view.get_url_name_args()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
returned_args,
|
||||||
|
[],
|
||||||
|
"An empty list should be returned")
|
||||||
|
|
||||||
|
|
||||||
|
@patch('builtins.super')
|
||||||
|
class SingleObjectMixinTest(TestCase):
|
||||||
|
def test_get_object_cache(self, mock_super):
|
||||||
|
"""
|
||||||
|
Test that the method get_object caches his result.
|
||||||
|
|
||||||
|
Tests that get_object from the django view is only called once, even if
|
||||||
|
get_object on our class is called twice.
|
||||||
|
"""
|
||||||
|
view = views.SingleObjectMixin()
|
||||||
|
|
||||||
|
view.get_object()
|
||||||
|
view.get_object()
|
||||||
|
|
||||||
|
mock_super().get_object.assert_called_once_with()
|
||||||
|
|
||||||
|
def test_dispatch_with_existin_object(self, mock_super):
|
||||||
|
view = views.SingleObjectMixin()
|
||||||
|
view.object = 'old_object'
|
||||||
|
view.get_object = MagicMock()
|
||||||
|
|
||||||
|
view.dispatch()
|
||||||
|
|
||||||
|
mock_super().dispatch.assert_called_with()
|
||||||
|
self.assertEqual(
|
||||||
|
view.object,
|
||||||
|
'old_object',
|
||||||
|
"view.object should not be changed")
|
||||||
|
self.assertFalse(
|
||||||
|
view.get_object.called,
|
||||||
|
"view.get_object() should not be called")
|
||||||
|
|
||||||
|
def test_dispatch_without_existin_object(self, mock_super):
|
||||||
|
view = views.SingleObjectMixin()
|
||||||
|
view.get_object = MagicMock(return_value='new_object')
|
||||||
|
|
||||||
|
view.dispatch()
|
||||||
|
|
||||||
|
mock_super().dispatch.assert_called_with()
|
||||||
|
self.assertEqual(
|
||||||
|
view.object,
|
||||||
|
'new_object',
|
||||||
|
"view.object should be changed")
|
||||||
|
self.assertTrue(
|
||||||
|
view.get_object.called,
|
||||||
|
"view.get_object() should be called")
|
@ -1,65 +0,0 @@
|
|||||||
from openslides.users.api import gen_password, gen_username
|
|
||||||
from openslides.users.models import Group, User
|
|
||||||
from openslides.utils.test import TestCase
|
|
||||||
|
|
||||||
|
|
||||||
class UserTest(TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.user1 = User()
|
|
||||||
self.user1.first_name = 'Max'
|
|
||||||
self.user1.last_name = 'Mustermann'
|
|
||||||
self.user1.username = gen_username(
|
|
||||||
self.user1.first_name, self.user1.last_name)
|
|
||||||
self.user1.default_password = gen_password()
|
|
||||||
self.user1.save()
|
|
||||||
|
|
||||||
def test_str(self):
|
|
||||||
self.assertEqual(str(self.user1), 'Max Mustermann')
|
|
||||||
|
|
||||||
def test_name_suffix(self):
|
|
||||||
self.user1.structure_level = 'München'
|
|
||||||
self.user1.save()
|
|
||||||
self.assertEqual(str(self.user1), 'Max Mustermann (München)')
|
|
||||||
|
|
||||||
def test_reset_password(self):
|
|
||||||
self.assertIsInstance(self.user1.default_password, str)
|
|
||||||
self.assertEqual(len(self.user1.default_password), 8)
|
|
||||||
self.user1.set_unusable_password()
|
|
||||||
self.assertFalse(self.user1.check_password(self.user1.default_password))
|
|
||||||
self.user1.reset_password()
|
|
||||||
self.assertTrue(self.user1.check_password(self.user1.default_password))
|
|
||||||
|
|
||||||
def test_get_absolute_url(self):
|
|
||||||
urls = (('detail', '/user/2/'),
|
|
||||||
('update', '/user/2/edit/'),
|
|
||||||
('delete', '/user/2/del/'))
|
|
||||||
for link, url in urls:
|
|
||||||
self.assertEqual(self.user1.get_absolute_url(link), url)
|
|
||||||
|
|
||||||
|
|
||||||
class DefaultGroups(TestCase):
|
|
||||||
|
|
||||||
def test_pks_of_default_groups(self):
|
|
||||||
default_groups = ((1, 'Anonymous'),
|
|
||||||
(2, 'Registered'),
|
|
||||||
(3, 'Delegates'),
|
|
||||||
(4, 'Staff'))
|
|
||||||
for pk, name in default_groups:
|
|
||||||
self.assertEqual(Group.objects.get(pk=pk).name, name)
|
|
||||||
|
|
||||||
def test_default_perms_anonymous(self):
|
|
||||||
anonymous = Group.objects.get(pk=1)
|
|
||||||
default_perms = ('core.can_see_projector',
|
|
||||||
'core.can_see_dashboard',
|
|
||||||
'agenda.can_see_agenda',
|
|
||||||
'agenda.can_see_orga_items',
|
|
||||||
'motion.can_see_motion',
|
|
||||||
'assignment.can_see_assignment',
|
|
||||||
'users.can_see_name',
|
|
||||||
'users.can_see_extra_data',
|
|
||||||
'mediafile.can_see')
|
|
||||||
for perm_string in default_perms:
|
|
||||||
perm_string_list = []
|
|
||||||
for perm in anonymous.permissions.all():
|
|
||||||
perm_string_list.append('%s.%s' % (perm.content_type.app_label, perm.codename))
|
|
||||||
self.assertTrue(perm_string in perm_string_list)
|
|
@ -1,26 +0,0 @@
|
|||||||
from openslides.users.api import gen_username
|
|
||||||
from openslides.users.models import User
|
|
||||||
from openslides.utils.test import TestCase
|
|
||||||
|
|
||||||
|
|
||||||
class UserGenUsername(TestCase):
|
|
||||||
"""
|
|
||||||
Tests for the function gen_username.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def test_base(self):
|
|
||||||
self.assertEqual(gen_username('foo', 'bar'), 'foo bar')
|
|
||||||
self.assertEqual(gen_username('foo ', ' bar\n'), 'foo bar')
|
|
||||||
self.assertEqual(gen_username('foobar', ''), 'foobar')
|
|
||||||
self.assertEqual(gen_username('', 'foobar'), 'foobar')
|
|
||||||
self.assertRaises(ValueError, gen_username, '', '')
|
|
||||||
|
|
||||||
def test_used_username(self):
|
|
||||||
User.objects.create(username='user name')
|
|
||||||
self.assertEqual(gen_username('user', 'name'), 'user name 1')
|
|
||||||
|
|
||||||
User.objects.create(username='user name 1')
|
|
||||||
self.assertEqual(gen_username('user', 'name'), 'user name 2')
|
|
||||||
|
|
||||||
def test_umlauts(self):
|
|
||||||
self.assertEqual(gen_username('äöü', 'ßüäö'), 'äöü ßüäö')
|
|
@ -1,5 +0,0 @@
|
|||||||
<html>
|
|
||||||
<body>
|
|
||||||
{{ object.title }}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,26 +0,0 @@
|
|||||||
from openslides.utils.models import AbsoluteUrlMixin
|
|
||||||
from openslides.utils.test import TestCase
|
|
||||||
|
|
||||||
|
|
||||||
class MyModel(AbsoluteUrlMixin):
|
|
||||||
""""
|
|
||||||
Model for testing
|
|
||||||
"""
|
|
||||||
def get_absolute_url(self, link='default'):
|
|
||||||
if link == 'default' or link == 'known':
|
|
||||||
url = 'my url'
|
|
||||||
else:
|
|
||||||
url = super(MyModel, self).get_absolute_url(link)
|
|
||||||
return url
|
|
||||||
|
|
||||||
|
|
||||||
class TestAbsoluteUrlMixin(TestCase):
|
|
||||||
def test_get_absolute_url(self):
|
|
||||||
my_object = MyModel()
|
|
||||||
|
|
||||||
self.assertEqual(my_object.get_absolute_url(), 'my url')
|
|
||||||
self.assertEqual(my_object.get_absolute_url('known'), 'my url')
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError,
|
|
||||||
'Unknown Link "unknown" for model "<class \'tests.utils.test_models.MyModel\'>"',
|
|
||||||
my_object.get_absolute_url, 'unknown')
|
|
@ -1,217 +0,0 @@
|
|||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from django.contrib.auth.models import AnonymousUser
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
|
||||||
from django.core.urlresolvers import clear_url_caches
|
|
||||||
from django.test import RequestFactory
|
|
||||||
from django.test.client import Client
|
|
||||||
from django.test.utils import override_settings
|
|
||||||
|
|
||||||
from openslides.utils import views
|
|
||||||
from openslides.utils.signals import template_manipulation
|
|
||||||
from openslides.utils.test import TestCase
|
|
||||||
|
|
||||||
from . import views as test_views
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ROOT_URLCONF='tests.utils.urls')
|
|
||||||
class ViewTestCase(TestCase):
|
|
||||||
rf = RequestFactory()
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
# Clear the cache for the urlresolver, so the overriden settings works.
|
|
||||||
clear_url_caches()
|
|
||||||
|
|
||||||
|
|
||||||
class LoginMixinTest(ViewTestCase):
|
|
||||||
def test_dispatch(self):
|
|
||||||
client = Client()
|
|
||||||
response = client.get('/login_mixin/')
|
|
||||||
self.assertEqual(response['Location'], 'http://testserver/login/?next=/login_mixin/')
|
|
||||||
|
|
||||||
client.login(username='admin', password='admin')
|
|
||||||
response = client.get('/login_mixin/')
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
self.assertEqual(response.content, b'Well done.')
|
|
||||||
|
|
||||||
|
|
||||||
class PermissionMixinTest(ViewTestCase):
|
|
||||||
def test_dispatch(self):
|
|
||||||
client = Client()
|
|
||||||
|
|
||||||
# View without required_permission
|
|
||||||
response = client.get('/permission_mixin1/')
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
self.assertEqual(response.content, b'Well done.')
|
|
||||||
|
|
||||||
# View with required_permission without login
|
|
||||||
response = client.get('/permission_mixin2/')
|
|
||||||
self.assertEqual(response.status_code, 302)
|
|
||||||
self.assertEqual(response['Location'], 'http://testserver/login/?next=/permission_mixin2/')
|
|
||||||
|
|
||||||
# View with required_permission, with login, without permission
|
|
||||||
client.login(username='admin', password='admin')
|
|
||||||
response = client.get('/permission_mixin2/')
|
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
|
|
||||||
# View with required_permission, with login, with permission
|
|
||||||
response = client.get('/permission_mixin3/')
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
|
|
||||||
class AjaxMixinTest(ViewTestCase):
|
|
||||||
def test_ajax_get(self):
|
|
||||||
view = test_views.AjaxMixinView()
|
|
||||||
ajax_get = view.ajax_get
|
|
||||||
response = ajax_get(self.rf.get('/', {}))
|
|
||||||
self.assertEqual(response.content, b'{"new_context": "newer_context"}')
|
|
||||||
|
|
||||||
def test_get_ajax_context(self):
|
|
||||||
get_ajax_context = test_views.AjaxMixinView().get_ajax_context
|
|
||||||
self.assertEqual(get_ajax_context()['new_context'], 'newer_context')
|
|
||||||
self.assertEqual(
|
|
||||||
get_ajax_context(test_content='some_content')['test_content'],
|
|
||||||
'some_content')
|
|
||||||
|
|
||||||
|
|
||||||
class ExtraContextMixinTest(ViewTestCase):
|
|
||||||
"""
|
|
||||||
Tests the ExtraContextMixin by testing the TemplateView.
|
|
||||||
"""
|
|
||||||
def test_get_context_data(self):
|
|
||||||
view = views.TemplateView()
|
|
||||||
get_context_data = view.get_context_data
|
|
||||||
view.request = self.rf.get('/', {})
|
|
||||||
view.request.user = AnonymousUser()
|
|
||||||
|
|
||||||
context = get_context_data()
|
|
||||||
self.assertIn('extra_stylefiles', context)
|
|
||||||
self.assertIn('extra_javascript', context)
|
|
||||||
|
|
||||||
context = get_context_data(some_context='context')
|
|
||||||
self.assertIn('some_context', context)
|
|
||||||
|
|
||||||
template_manipulation.connect(set_context, dispatch_uid='set_context_test')
|
|
||||||
context = get_context_data()
|
|
||||||
self.assertIn('new_context', context)
|
|
||||||
template_manipulation.disconnect(set_context, dispatch_uid='set_context_test')
|
|
||||||
|
|
||||||
|
|
||||||
class UrlMixinTest(ViewTestCase):
|
|
||||||
def test_get_url(self):
|
|
||||||
get_url = test_views.UrlMixinView().get_url
|
|
||||||
|
|
||||||
# url_name has the higher priority
|
|
||||||
self.assertEqual(get_url('test_url_mixin', 'view_url'),
|
|
||||||
'/url_mixin/')
|
|
||||||
|
|
||||||
# If the url_name is none, return the second argument
|
|
||||||
self.assertEqual(get_url(None, 'view_url'),
|
|
||||||
'view_url')
|
|
||||||
|
|
||||||
# Test argument in url
|
|
||||||
self.assertEqual(get_url('test_url_mixin_args', None,
|
|
||||||
args=[1]),
|
|
||||||
'/url_mixin_args/1/')
|
|
||||||
|
|
||||||
# No Url given.
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ImproperlyConfigured,
|
|
||||||
'No url to redirect to. See openslides.utils.views.UrlMixin for more details.',
|
|
||||||
get_url, None, None)
|
|
||||||
|
|
||||||
def test_get_url_with_object(self):
|
|
||||||
get_url = test_views.UrlMixinViewWithObject().get_url
|
|
||||||
|
|
||||||
self.assertEqual(get_url(None, None),
|
|
||||||
'default_url')
|
|
||||||
self.assertEqual(get_url(None, None, use_absolute_url_link='detail'),
|
|
||||||
'detail_url')
|
|
||||||
|
|
||||||
def test_get_url_name_args(self):
|
|
||||||
view = test_views.UrlMixinViewWithObject()
|
|
||||||
get_url_name_args = view.get_url_name_args
|
|
||||||
view.url_name_args = [1]
|
|
||||||
|
|
||||||
self.assertEqual(get_url_name_args(), [1])
|
|
||||||
|
|
||||||
view.url_name_args = None
|
|
||||||
self.assertEqual(get_url_name_args(), [])
|
|
||||||
|
|
||||||
view.object.pk = 5
|
|
||||||
self.assertEqual(get_url_name_args(), [5])
|
|
||||||
|
|
||||||
|
|
||||||
class QuestionViewTest(ViewTestCase):
|
|
||||||
def test_get_redirect_url(self):
|
|
||||||
view = views.QuestionView()
|
|
||||||
get_redirect_url = view.get_redirect_url
|
|
||||||
|
|
||||||
view.request = self.rf.get('/')
|
|
||||||
view.question_url = 'redirect_to_get_url'
|
|
||||||
self.assertEqual(get_redirect_url(), 'redirect_to_get_url')
|
|
||||||
|
|
||||||
view.request = self.rf.post('/')
|
|
||||||
view.url = 'redirect_to_post_url'
|
|
||||||
self.assertEqual(get_redirect_url(), 'redirect_to_post_url')
|
|
||||||
|
|
||||||
def test_get_question_message(self):
|
|
||||||
view = views.QuestionView()
|
|
||||||
get_question_message = view.get_question_message
|
|
||||||
|
|
||||||
self.assertEqual(get_question_message(), 'Are you sure?')
|
|
||||||
|
|
||||||
view.question_message = 'new_question'
|
|
||||||
self.assertEqual(get_question_message(), 'new_question')
|
|
||||||
|
|
||||||
self.assertIsInstance(get_question_message(), str)
|
|
||||||
|
|
||||||
def test_get_answer_options(self):
|
|
||||||
view = views.QuestionView()
|
|
||||||
get_answer_options = view.get_answer_options
|
|
||||||
|
|
||||||
self.assertIn('yes', dict(get_answer_options()))
|
|
||||||
self.assertIn('no', dict(get_answer_options()))
|
|
||||||
|
|
||||||
view.answer_options = [('new_answer', 'Answer')]
|
|
||||||
self.assertNotIn('yes', dict(get_answer_options()))
|
|
||||||
self.assertIn('new_answer', dict(get_answer_options()))
|
|
||||||
|
|
||||||
@patch('openslides.utils.views.messages')
|
|
||||||
def test_confirm_form(self, mock_messages):
|
|
||||||
view = views.QuestionView()
|
|
||||||
view.question_message = 'the question'
|
|
||||||
confirm_form = view.confirm_form
|
|
||||||
view.request = self.rf.get('/')
|
|
||||||
|
|
||||||
confirm_form()
|
|
||||||
|
|
||||||
self.assertTrue(mock_messages.warning.called)
|
|
||||||
|
|
||||||
question = mock_messages.warning.call_args[0][1]
|
|
||||||
self.assertIn('the question', question)
|
|
||||||
|
|
||||||
|
|
||||||
class SingleObjectMixinTest(TestCase):
|
|
||||||
|
|
||||||
@patch('openslides.utils.views.django_views.detail.SingleObjectMixin.get_object')
|
|
||||||
def test_get_object_cache(self, mock_super_class_get_object):
|
|
||||||
"""
|
|
||||||
Test that the method get_object caches his result.
|
|
||||||
|
|
||||||
Tests that get_object from the django view is only called once, even if
|
|
||||||
get_object on our class is called twice.
|
|
||||||
"""
|
|
||||||
view = views.SingleObjectMixin()
|
|
||||||
|
|
||||||
view.get_object()
|
|
||||||
view.get_object()
|
|
||||||
|
|
||||||
mock_super_class_get_object.assert_called_once_with()
|
|
||||||
|
|
||||||
|
|
||||||
def set_context(sender, request, context, **kwargs):
|
|
||||||
"""
|
|
||||||
receiver for testing the ExtraContextMixin
|
|
||||||
"""
|
|
||||||
context.update({'new_context': 'some new context'})
|
|
@ -1,29 +0,0 @@
|
|||||||
from django.conf.urls import patterns, url
|
|
||||||
|
|
||||||
from openslides.urls import urlpatterns
|
|
||||||
|
|
||||||
from . import views
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns += patterns(
|
|
||||||
'',
|
|
||||||
url(r'^url_mixin/$',
|
|
||||||
views.UrlMixinView.as_view(),
|
|
||||||
name='test_url_mixin'),
|
|
||||||
|
|
||||||
url(r'^url_mixin_args/(?P<arg>\d+)/$',
|
|
||||||
views.UrlMixinView.as_view(),
|
|
||||||
name='test_url_mixin_args'),
|
|
||||||
|
|
||||||
url(r'^login_mixin/$',
|
|
||||||
views.LoginMixinView.as_view()),
|
|
||||||
|
|
||||||
url(r'^permission_mixin1/$',
|
|
||||||
views.PermissionMixinView.as_view()),
|
|
||||||
|
|
||||||
url(r'^permission_mixin2/$',
|
|
||||||
views.PermissionMixinView.as_view(required_permission='permission_string')),
|
|
||||||
|
|
||||||
url(r'^permission_mixin3/$',
|
|
||||||
views.PermissionMixinView.as_view(required_permission='agenda.can_see_agenda')),
|
|
||||||
)
|
|
@ -1,47 +0,0 @@
|
|||||||
from django.http import HttpResponse
|
|
||||||
|
|
||||||
from openslides.utils import views
|
|
||||||
|
|
||||||
|
|
||||||
class GetAbsoluteUrl(object):
|
|
||||||
"""
|
|
||||||
Generates objects with a get_absolute_url method.
|
|
||||||
|
|
||||||
Helper Class for the tests.
|
|
||||||
"""
|
|
||||||
def get_absolute_url(self, link='default'):
|
|
||||||
if link == 'detail':
|
|
||||||
url = 'detail_url'
|
|
||||||
elif link == 'update':
|
|
||||||
url = 'update_url'
|
|
||||||
elif link == 'default':
|
|
||||||
url = 'default_url'
|
|
||||||
return url
|
|
||||||
|
|
||||||
|
|
||||||
class LoginMixinView(views.LoginMixin, views.View):
|
|
||||||
def get(self, *args, **kwargs):
|
|
||||||
response = HttpResponse('Well done.')
|
|
||||||
response.status_code = 200
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
class PermissionMixinView(views.PermissionMixin, views.View):
|
|
||||||
def get(self, *args, **kwargs):
|
|
||||||
response = HttpResponse('Well done.')
|
|
||||||
response.status_code = 200
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
class AjaxMixinView(views.AjaxMixin, views.View):
|
|
||||||
def get_ajax_context(self, **kwargs):
|
|
||||||
return super(AjaxMixinView, self).get_ajax_context(
|
|
||||||
new_context='newer_context', **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class UrlMixinView(views.UrlMixin, views.View):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class UrlMixinViewWithObject(views.UrlMixin, views.View):
|
|
||||||
object = GetAbsoluteUrl()
|
|
Loading…
Reference in New Issue
Block a user