commit
246c7a456a
|
@ -4,6 +4,7 @@
|
||||||
*~
|
*~
|
||||||
settings.py
|
settings.py
|
||||||
database.sqlite
|
database.sqlite
|
||||||
|
!tests/settings.py
|
||||||
|
|
||||||
# Package building
|
# Package building
|
||||||
docs/_build/*
|
docs/_build/*
|
||||||
|
|
|
@ -6,6 +6,7 @@ install:
|
||||||
- pip install -r requirements.txt --use-mirrors
|
- pip install -r requirements.txt --use-mirrors
|
||||||
- python extras/scripts/create_local_settings.py
|
- python extras/scripts/create_local_settings.py
|
||||||
script:
|
script:
|
||||||
|
- export DJANGO_SETTINGS_MODULE=tests.settings
|
||||||
- coverage run ./manage.py test tests && coverage report -m
|
- coverage run ./manage.py test tests && coverage report -m
|
||||||
- pep8 --max-line-length=150 --exclude="urls.py," --statistics openslides
|
- pep8 --max-line-length=150 --exclude="urls.py," --statistics openslides
|
||||||
- pep8 --max-line-length=150 --statistics tests
|
- pep8 --max-line-length=150 --statistics tests
|
||||||
|
|
|
@ -12,6 +12,7 @@ from django.core.management import execute_from_command_line
|
||||||
from openslides.main import get_user_config_path, setup_django_environment
|
from openslides.main import get_user_config_path, setup_django_environment
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
setup_django_environment(
|
if 'DJANGO_SETTINGS_MODULE' not in os.environ:
|
||||||
get_user_config_path('openslides', 'settings.py'))
|
setup_django_environment(
|
||||||
|
get_user_config_path('openslides', 'settings.py'))
|
||||||
execute_from_command_line(sys.argv)
|
execute_from_command_line(sys.argv)
|
||||||
|
|
|
@ -23,7 +23,6 @@ from django.utils import formats
|
||||||
from django.utils.translation import pgettext
|
from django.utils.translation import pgettext
|
||||||
from django.utils.translation import ugettext_lazy, ugettext_noop, ugettext as _
|
from django.utils.translation import ugettext_lazy, ugettext_noop, ugettext as _
|
||||||
|
|
||||||
from openslides.utils.utils import _propper_unicode
|
|
||||||
from openslides.utils.person import PersonField
|
from openslides.utils.person import PersonField
|
||||||
from openslides.config.models import config
|
from openslides.config.models import config
|
||||||
from openslides.config.signals import default_config_value
|
from openslides.config.signals import default_config_value
|
||||||
|
@ -339,13 +338,16 @@ class Motion(SlideMixin, models.Model):
|
||||||
|
|
||||||
def is_submitter(self, person):
|
def is_submitter(self, person):
|
||||||
"""Return True, if person is a submitter of this motion. Else: False."""
|
"""Return True, if person is a submitter of this motion. Else: False."""
|
||||||
self.submitter.filter(person=person).exists()
|
return self.submitter.filter(person=person).exists()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supporters(self):
|
def supporters(self):
|
||||||
return sorted([object.person for object in self.supporter.all()],
|
return sorted([object.person for object in self.supporter.all()],
|
||||||
key=lambda person: person.sort_name)
|
key=lambda person: person.sort_name)
|
||||||
|
|
||||||
|
def add_submitter(self, person):
|
||||||
|
MotionSubmitter.objects.create(motion=self, person=person)
|
||||||
|
|
||||||
def is_supporter(self, person):
|
def is_supporter(self, person):
|
||||||
"""Return True, if person is a supporter of this motion. Else: False."""
|
"""Return True, if person is a supporter of this motion. Else: False."""
|
||||||
return self.supporter.filter(person=person).exists()
|
return self.supporter.filter(person=person).exists()
|
||||||
|
|
|
@ -165,6 +165,11 @@ class MotionCreateView(MotionMixin, CreateView):
|
||||||
self.object.write_log(ugettext_noop('Motion created'), self.request.user)
|
self.object.write_log(ugettext_noop('Motion created'), self.request.user)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def post_save(self, form):
|
||||||
|
super(MotionCreateView, self).post_save(form)
|
||||||
|
if not 'submitter' in form.cleaned_data:
|
||||||
|
self.object.add_submitter(self.request.user)
|
||||||
|
|
||||||
motion_create = MotionCreateView.as_view()
|
motion_create = MotionCreateView.as_view()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ from django.utils.translation import ugettext as _, ugettext_lazy, activate
|
||||||
from openslides.utils.pdf import stylesheet
|
from openslides.utils.pdf import stylesheet
|
||||||
from openslides.utils.template import Tab
|
from openslides.utils.template import Tab
|
||||||
from openslides.utils.utils import (
|
from openslides.utils.utils import (
|
||||||
template, decodedict, encodedict, delete_default_permissions, html_strong)
|
template, delete_default_permissions, html_strong)
|
||||||
from openslides.utils.views import (
|
from openslides.utils.views import (
|
||||||
FormView, PDFView, CreateView, UpdateView, DeleteView, PermissionMixin,
|
FormView, PDFView, CreateView, UpdateView, DeleteView, PermissionMixin,
|
||||||
RedirectView, SingleObjectMixin, ListView, QuestionMixin, DetailView)
|
RedirectView, SingleObjectMixin, ListView, QuestionMixin, DetailView)
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from .forms import PersonFormField
|
from .forms import PersonFormField
|
||||||
from .api import get_person, generate_person_id, Person
|
from .api import get_person, generate_person_id
|
||||||
|
|
||||||
|
|
||||||
class PersonField(models.fields.Field):
|
class PersonField(models.fields.Field):
|
||||||
|
@ -29,7 +29,7 @@ class PersonField(models.fields.Field):
|
||||||
"""
|
"""
|
||||||
Convert string value to a User Object.
|
Convert string value to a User Object.
|
||||||
"""
|
"""
|
||||||
if isinstance(value, Person):
|
if isinstance(value, PersonMixin):
|
||||||
return value
|
return value
|
||||||
elif value is None:
|
elif value is None:
|
||||||
return None
|
return None
|
||||||
|
@ -60,5 +60,11 @@ class PersonMixin(object):
|
||||||
raise AttributeError("%s has to have a attribute 'person_prefix'"
|
raise AttributeError("%s has to have a attribute 'person_prefix'"
|
||||||
% self)
|
% self)
|
||||||
|
|
||||||
def __repr__(self):
|
def __unicode__(self):
|
||||||
return 'Person: %s' % self.person_id
|
return 'MyPerson: %s' % self.person_id
|
||||||
|
|
||||||
|
def prepare_database_save(self, field):
|
||||||
|
if type(field) is PersonField:
|
||||||
|
return self.person_id
|
||||||
|
else:
|
||||||
|
return super(PersonMixin, self).prepare_database_save(field)
|
||||||
|
|
|
@ -16,11 +16,6 @@ from openslides.config.models import config
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
|
||||||
def get_min_supporters():
|
|
||||||
return config['motion_min_supporters']
|
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def get_config(key):
|
def get_config(key):
|
||||||
return config[key]
|
return config[key]
|
||||||
|
|
|
@ -132,27 +132,6 @@ def ajax_request(data):
|
||||||
return HttpResponse(json.dumps(data))
|
return HttpResponse(json.dumps(data))
|
||||||
|
|
||||||
|
|
||||||
def _propper_unicode(text):
|
|
||||||
if not isinstance(text, unicode):
|
|
||||||
return u"%s" % text.decode('UTF-8')
|
|
||||||
else:
|
|
||||||
return text
|
|
||||||
|
|
||||||
|
|
||||||
def decodedict(dict):
|
|
||||||
newdict = {}
|
|
||||||
for key in dict:
|
|
||||||
newdict[key] = [dict[key][0].encode('utf-8')]
|
|
||||||
return newdict
|
|
||||||
|
|
||||||
|
|
||||||
def encodedict(dict):
|
|
||||||
newdict = {}
|
|
||||||
for key in dict:
|
|
||||||
newdict[key] = [unicode(dict[key][0].decode('utf-8'))]
|
|
||||||
return newdict
|
|
||||||
|
|
||||||
|
|
||||||
def html_strong(string):
|
def html_strong(string):
|
||||||
return u"<strong>%s</strong>" % string
|
return u"<strong>%s</strong>" % string
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Tests for openslides.motion.models
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
:copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
|
||||||
|
:license: GNU GPL, see LICENSE for more details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.test.client import Client
|
||||||
|
|
||||||
|
from openslides.utils.test import TestCase
|
||||||
|
from openslides.participant.models import User, Group
|
||||||
|
from openslides.motion.models import Motion
|
||||||
|
|
||||||
|
|
||||||
|
class MotionViewTestCase(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
# Admin
|
||||||
|
self.admin = User.objects.create_superuser('admin', 'admin@admin.admin', 'admin')
|
||||||
|
self.admin_client = Client()
|
||||||
|
self.admin_client.login(username='admin', password='admin')
|
||||||
|
|
||||||
|
# Delegate
|
||||||
|
self.delegate = User.objects.create_user('delegate', 'delegate@user.user', 'delegate')
|
||||||
|
delegate_group = Group.objects.get(name='Delegates')
|
||||||
|
self.delegate.groups.add(delegate_group)
|
||||||
|
self.delegate.save()
|
||||||
|
self.delegate_client = Client()
|
||||||
|
self.delegate_client.login(username='delegate', password='delegate')
|
||||||
|
|
||||||
|
# Registered
|
||||||
|
self.registered = User.objects.create_user('registered', 'registered@user.user', 'registered')
|
||||||
|
self.registered_client = Client()
|
||||||
|
self.registered_client.login(username='registered', password='registered')
|
||||||
|
|
||||||
|
self.motion1 = Motion.objects.create(title='motion1')
|
||||||
|
self.motion2 = Motion.objects.create(title='motion2')
|
||||||
|
|
||||||
|
def check_url(self, url, test_client, response_cose):
|
||||||
|
response = test_client.get(url)
|
||||||
|
self.assertEqual(response.status_code, response_cose)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class TestMotionListView(MotionViewTestCase):
|
||||||
|
def test_get(self):
|
||||||
|
self.check_url('/motion/', self.admin_client, 200)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMotionDetailView(MotionViewTestCase):
|
||||||
|
def test_get(self):
|
||||||
|
self.check_url('/motion/1/', self.admin_client, 200)
|
||||||
|
self.check_url('/motion/2/', self.admin_client, 200)
|
||||||
|
self.check_url('/motion/500/', self.admin_client, 404)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMotionCreateView(MotionViewTestCase):
|
||||||
|
url = '/motion/new/'
|
||||||
|
|
||||||
|
def test_get(self):
|
||||||
|
self.check_url(self.url, self.admin_client, 200)
|
||||||
|
|
||||||
|
def test_admin(self):
|
||||||
|
self.assertFalse(Motion.objects.filter(versions__title='new motion').exists())
|
||||||
|
response = self.admin_client.post(self.url, {'title': 'new motion',
|
||||||
|
'text': 'motion text',
|
||||||
|
'reason': 'motion reason',
|
||||||
|
'submitter': self.admin})
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
self.assertTrue(Motion.objects.filter(versions__title='new motion').exists())
|
||||||
|
|
||||||
|
def test_delegate(self):
|
||||||
|
self.assertFalse(Motion.objects.filter(versions__title='delegate motion').exists())
|
||||||
|
response = self.delegate_client.post(self.url, {'title': 'delegate motion',
|
||||||
|
'text': 'motion text',
|
||||||
|
'reason': 'motion reason',
|
||||||
|
'submitter': self.admin})
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
motion = Motion.objects.get(versions__title='delegate motion')
|
||||||
|
self.assertTrue(motion.is_submitter(self.delegate))
|
||||||
|
|
||||||
|
def test_registered(self):
|
||||||
|
self.assertFalse(Motion.objects.filter(versions__title='registered motion').exists())
|
||||||
|
response = self.registered_client.post(self.url, {'title': 'registered motion',
|
||||||
|
'text': 'motion text',
|
||||||
|
'reason': 'motion reason',
|
||||||
|
'submitter': self.admin})
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
self.assertFalse(Motion.objects.filter(versions__title='registered motion').exists())
|
||||||
|
|
||||||
|
|
||||||
|
class TestMotionUpdateView(MotionViewTestCase):
|
||||||
|
url = '/motion/1/edit/'
|
||||||
|
|
||||||
|
def test_get(self):
|
||||||
|
self.check_url(self.url, self.admin_client, 200)
|
||||||
|
|
||||||
|
def test_admin(self):
|
||||||
|
response = self.admin_client.post(self.url, {'title': 'new motion_title',
|
||||||
|
'text': 'motion text',
|
||||||
|
'reason': 'motion reason',
|
||||||
|
'submitter': self.admin})
|
||||||
|
self.assertRedirects(response, '/motion/1/')
|
||||||
|
motion = Motion.objects.get(pk=1)
|
||||||
|
self.assertEqual(motion.title, 'new motion_title')
|
||||||
|
|
||||||
|
def test_delegate(self):
|
||||||
|
response = self.delegate_client.post(self.url, {'title': 'my title',
|
||||||
|
'text': 'motion text',
|
||||||
|
'reason': 'motion reason'})
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
motion = Motion.objects.get(pk=1)
|
||||||
|
motion.add_submitter(self.delegate)
|
||||||
|
response = self.delegate_client.post(self.url, {'title': 'my title',
|
||||||
|
'text': 'motion text',
|
||||||
|
'reason': 'motion reason'})
|
||||||
|
self.assertRedirects(response, '/motion/1/')
|
||||||
|
motion = Motion.objects.get(pk=1)
|
||||||
|
self.assertEqual(motion.title, 'my title')
|
||||||
|
|
||||||
|
|
||||||
|
class TestMotionDeleteView(MotionViewTestCase):
|
||||||
|
def test_get(self):
|
||||||
|
response = self.check_url('/motion/2/del/', self.admin_client, 302)
|
||||||
|
self.assertRedirects(response, '/motion/2/')
|
||||||
|
|
||||||
|
def test_admin(self):
|
||||||
|
response = self.admin_client.post('/motion/2/del/', {})
|
||||||
|
self.assertRedirects(response, '/motion/')
|
||||||
|
|
||||||
|
def test_delegate(self):
|
||||||
|
response = self.delegate_client.post('/motion/2/del/', {})
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
motion = Motion.objects.get(pk=2).add_submitter(self.delegate)
|
||||||
|
response = self.delegate_client.post('/motion/2/del/', {})
|
||||||
|
self.assertRedirects(response, '/motion/')
|
|
@ -0,0 +1,46 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from openslides.utils.person.models import PersonMixin, PersonField
|
||||||
|
from openslides.utils.person.signals import receive_persons
|
||||||
|
from openslides.utils.person.api import Person
|
||||||
|
|
||||||
|
|
||||||
|
class TestPerson(PersonMixin, models.Model):
|
||||||
|
person_prefix = 'test'
|
||||||
|
name = models.CharField(max_length='255')
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class TestPersonToPerson(object):
|
||||||
|
def __init__(self, person_prefix_filter=None, id_filter=None):
|
||||||
|
self.person_prefix_filter = person_prefix_filter
|
||||||
|
self.id_filter = id_filter
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
if (not self.person_prefix_filter or
|
||||||
|
self.person_prefix_filter == TestPerson.person_prefix):
|
||||||
|
if self.id_filter:
|
||||||
|
try:
|
||||||
|
yield TestPerson.objects.get(pk=self.id_filter)
|
||||||
|
except TestPerson.DoesNotExist:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
for user in TestPerson.objects.all():
|
||||||
|
yield user
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(receive_persons, dispatch_uid="test_person")
|
||||||
|
def receive_persons(sender, **kwargs):
|
||||||
|
return TestPersonToPerson(
|
||||||
|
person_prefix_filter=kwargs['person_prefix_filter'],
|
||||||
|
id_filter=kwargs['id_filter'])
|
||||||
|
|
||||||
|
|
||||||
|
class TestModel(models.Model):
|
||||||
|
person = PersonField()
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return self.person
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
openslides.person_api.tests
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Unit test for the person api.
|
||||||
|
|
||||||
|
:copyright: 2011 - 2013 by OpenSlides team, see AUTHORS.
|
||||||
|
:license: GNU GPL, see LICENSE for more details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.test.client import Client
|
||||||
|
from django.db.models.query import EmptyQuerySet
|
||||||
|
|
||||||
|
from openslides.utils.test import TestCase
|
||||||
|
|
||||||
|
from .models import TestPerson, TestModel
|
||||||
|
|
||||||
|
|
||||||
|
class ItemTest(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.person1 = TestPerson.objects.create(name='test1')
|
||||||
|
|
||||||
|
def test_update_of_person_field(self):
|
||||||
|
self.assertEqual(self.person1.person_id, 'test:1')
|
||||||
|
|
||||||
|
# save person field
|
||||||
|
test_object = TestModel.objects.create(person=self.person1)
|
||||||
|
self.assertEqual(test_object.person, self.person1)
|
||||||
|
|
||||||
|
# update person field
|
||||||
|
test_object.save()
|
||||||
|
self.assertEqual(TestModel.objects.get(pk=test_object.pk).person, self.person1)
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import openslides.main
|
||||||
|
from openslides.global_settings import *
|
||||||
|
|
||||||
|
# Use 'DEBUG = True' to get more details for server errors
|
||||||
|
# (Default for releases: 'False')
|
||||||
|
DEBUG = True
|
||||||
|
TEMPLATE_DEBUG = DEBUG
|
||||||
|
|
||||||
|
DBPATH = u'database.sqlite'
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': DBPATH,
|
||||||
|
'USER': '',
|
||||||
|
'PASSWORD': '',
|
||||||
|
'HOST': '',
|
||||||
|
'PORT': '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set timezone
|
||||||
|
TIME_ZONE = 'Europe/Berlin'
|
||||||
|
|
||||||
|
# Make this unique, and don't share it with anybody.
|
||||||
|
SECRET_KEY = 'secred'
|
||||||
|
|
||||||
|
# Add OpenSlides plugins to this list (see example entry in comment)
|
||||||
|
INSTALLED_PLUGINS = (
|
||||||
|
'tests.person_api',
|
||||||
|
)
|
||||||
|
|
||||||
|
INSTALLED_APPS += INSTALLED_PLUGINS
|
Loading…
Reference in New Issue