Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 5 commits
  • 15 files changed
  • 0 commit comments
  • 1 contributor
View
1  setup.py
@@ -30,7 +30,6 @@
'betahaus.viewcomponent',
'pyramid_debugtoolbar', #Won't be active unless included
'fanstatic',
- 'iso8601', #I thought this was part of the standard lib?
'repoze.evolution',
'httpagentparser',
)
View
2  voteit/core/deform_bindings.py
@@ -49,4 +49,4 @@ def includeme(config):
RadioChoiceWidget.readonly_template = join(WIDGETS_PATH, 'readonly', 'radio_choice')
#Patches for RichTextWidget templates to display a better editor
- RichTextWidget.template = join(WIDGETS_PATH, 'richtext')
+ RichTextWidget.template = join(WIDGETS_PATH, 'richtext')
View
BIN  voteit/core/locale/sv/LC_MESSAGES/voteit.core.mo
Binary file not shown
View
2  voteit/core/locale/sv/LC_MESSAGES/voteit.core.po
@@ -76,7 +76,7 @@ msgstr "${username} föreslår"
#: ./schemas/tzdatetime.py:31
msgid "'${val}' is not valid as date and time"
-msgstr "'{val}' är inte giltigt som datum och tid"
+msgstr "'${val}' är inte giltigt som datum och tid"
#. Default: "(No polls yet)"
#: ./views/templates/snippets/polls_menu_body.pt:22
View
2  voteit/core/models/base_content.py
@@ -42,7 +42,7 @@ def __init__(self, data=None, **kwargs):
#FIXME: We'd like some sort of logging here,
#but if we log in voteit.core, any poll plugin test will die very strangely
#It has something with cleanup of logging in multithreading in setuptools
- pass
+ pass #pragma : no cover
#Set owner - if it is in kwargs now
if 'creators' in kwargs:
View
2  voteit/core/models/logs.py
@@ -45,7 +45,7 @@ def add(self, context_uid, message, tags=(), userid=None, scripted=None):
if self.log_storage.insert(k, obj):
return
- raise KeyError("Couln't find a free key for logging handler after 10 retries.")
+ raise KeyError("Couln't find a free key for logging handler after 10 retries.") #pragma : no cover
@content_factory('LogEntry', title=_(u"Log entry"))
View
2  voteit/core/models/poll.py
@@ -222,7 +222,7 @@ def render_poll_result(self, request, complete=True):
try:
poll_plugin = self.get_poll_plugin()
return poll_plugin.render_result(request, complete)
- except Exception, exc:
+ except Exception, exc: # pragma : no cover
if request.registry.settings.get('pyramid.debug_templates', False):
raise exc
return _(u"Broken poll plugin. Can't display result. Turn on debug_templates to see the error.")
View
20 voteit/core/models/tests/test_invite_ticket.py
@@ -2,10 +2,13 @@
from datetime import datetime
from pyramid import testing
-from zope.interface.verify import verifyObject, verifyClass
+from zope.interface.verify import verifyClass
+from zope.interface.verify import verifyObject
from pyramid_mailer import get_mailer
from pyramid.exceptions import Forbidden
+from voteit.core.models.interfaces import IInviteTicket
+
class InviteTicketTests(unittest.TestCase):
def setUp(self):
@@ -18,21 +21,22 @@ def tearDown(self):
testing.tearDown()
@property
- def _get_class(self):
+ def _cut(self):
from voteit.core.models.invite_ticket import InviteTicket
return InviteTicket
def _make_obj(self):
- return self._get_class('this@email.com', ['role:Moderator'], 'Welcome to the meeting!')
+ return self._cut('this@email.com', ['role:Moderator'], 'Welcome to the meeting!')
def _make_meeting(self):
from voteit.core.models.meeting import Meeting
return Meeting()
-
- def test_verify_interface(self):
- from voteit.core.models.interfaces import IInviteTicket
- self.assertTrue(verifyClass(IInviteTicket, self._get_class))
+ def test_verify_class(self):
+ self.assertTrue(verifyClass(IInviteTicket, self._cut))
+
+ def test_verify_obj(self):
+ self.assertTrue(verifyObject(IInviteTicket, self._make_obj()))
def test_send_message_sent(self):
meeting = self._make_meeting()
@@ -92,3 +96,5 @@ def test_claim_unathenticated(self):
self.assertRaises(Forbidden, ticket.claim, request)
+ def test_force_selectable_roles(self):
+ self.assertRaises(ValueError, self._cut, 'hello@world.com', 'bad_role', "This won't work")
View
77 voteit/core/models/tests/test_meeting.py
@@ -3,11 +3,14 @@
from pyramid import testing
from pyramid.authorization import ACLAuthorizationPolicy
-
-from voteit.core import security
from pyramid.security import Authenticated
+from pyramid.httpexceptions import HTTPForbidden
+from zope.interface.verify import verifyClass
from zope.interface.verify import verifyObject
+from voteit.core import security
+from voteit.core.models.interfaces import IMeeting
+from voteit.core.testing_helpers import register_workflows
admin = set([security.ROLE_ADMIN])
moderator = set([security.ROLE_MODERATOR])
@@ -22,48 +25,73 @@
class MeetingTests(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
- # load workflow
- self.config.include('pyramid_zcml')
- self.config.load_zcml('voteit.core:configure.zcml')
def tearDown(self):
testing.tearDown()
- def _make_obj(self):
+ @property
+ def _cut(self):
from voteit.core.models.meeting import Meeting
- return Meeting()
-
- def _make_ai(self):
+ return Meeting
+
+ @property
+ def _ai(self):
from voteit.core.models.agenda_item import AgendaItem
- return AgendaItem()
+ return AgendaItem
+
+ def test_verify_class(self):
+ self.assertTrue(verifyClass(IMeeting, self._cut))
+
+ def test_verify_obj(self):
+ self.assertTrue(verifyObject(IMeeting, self._cut()))
- def test_verify_implementation(self):
- from voteit.core.models.interfaces import IMeeting
- obj = self._make_obj()
- self.assertTrue(verifyObject(IMeeting, obj))
+ def test_meeting_with_one_creator_sets_creator_as_moderator(self):
+ obj = self._cut(creators = ['jane'])
+ self.assertIn('role:Moderator', obj.get_groups('jane'))
def test_closing_meeting_with_ongoing_ais(self):
""" Closing a meeting with ongoing agenda items should raise an exception. """
+ register_workflows(self.config)
request = testing.DummyRequest()
- ai = self._make_ai()
+ ai = self._ai()
ai.set_workflow_state(request, 'upcoming')
ai.set_workflow_state(request, 'ongoing')
- obj = self._make_obj()
+ obj = self._cut()
obj['ai'] = ai
obj.set_workflow_state(request, 'ongoing')
self.assertRaises(Exception, obj.set_workflow_state, 'closed')
def test_timestamp_added_on_close(self):
+ register_workflows(self.config)
self.config.scan('voteit.core.subscribers.timestamps') #To add subscriber
request = testing.DummyRequest()
- obj = self._make_obj()
+ obj = self._cut()
obj.set_workflow_state(request, 'ongoing')
self.assertFalse(isinstance(obj.end_time, datetime))
obj.set_workflow_state(request, 'closed')
self.assertTrue(isinstance(obj.end_time, datetime))
-
-
+
+ def test_closing_meeting_callback(self):
+ register_workflows(self.config)
+ request = testing.DummyRequest()
+ obj = self._cut()
+ obj['ai'] = self._ai()
+ obj.set_workflow_state(request, 'ongoing')
+ obj['ai'].set_workflow_state(request, 'upcoming')
+ obj['ai'].set_workflow_state(request, 'ongoing')
+ self.assertRaises(HTTPForbidden, obj.set_workflow_state, request, 'closed')
+
+ def test_add_invite_ticket_traversal(self):
+ from voteit.core.models.invite_ticket import InviteTicket
+ self.config.include('pyramid_mailer.testing')
+ request = testing.DummyRequest()
+ obj = self._cut()
+ ticket = InviteTicket('blabla@hello.se', ['role:Moderator'], 'Hello!')
+ obj.add_invite_ticket(ticket, request)
+ self.assertEqual(obj, ticket.__parent__)
+
+
class MeetingPermissionTests(unittest.TestCase):
""" Check permissions in different meeting states. """
@@ -78,13 +106,14 @@ def setUp(self):
def tearDown(self):
testing.tearDown()
- def _make_obj(self):
+ @property
+ def _cut(self):
from voteit.core.models.meeting import Meeting
- return Meeting()
+ return Meeting
def test_upcoming(self):
request = testing.DummyRequest()
- obj = self._make_obj()
+ obj = self._cut()
#View
self.assertEqual(self.pap(obj, security.VIEW), admin | moderator | viewer )
@@ -115,7 +144,7 @@ def test_upcoming(self):
def test_ongoing(self):
request = testing.DummyRequest()
- obj = self._make_obj()
+ obj = self._cut()
obj.set_workflow_state(request, 'ongoing')
#View
@@ -147,7 +176,7 @@ def test_ongoing(self):
def test_closed(self):
request = testing.DummyRequest()
- obj = self._make_obj()
+ obj = self._cut()
obj.set_workflow_state(request, 'ongoing')
obj.set_workflow_state(request, 'closed')
View
6 voteit/core/schemas/meeting.py
@@ -54,8 +54,10 @@ def deferred_recaptcha_widget(node, kw):
principals = api.context_effective_principals(context)
if api.root.get_field_value('captcha_meeting', False) and security.ROLE_ADMIN not in principals:
- return RecaptchaWidget(api.root.get_field_value('captcha_public_key', ''),
- api.root.get_field_value('captcha_private_key', ''))
+ pub_key = api.root.get_field_value('captcha_public_key', '')
+ priv_key = api.root.get_field_value('captcha_private_key', '')
+ return RecaptchaWidget(captcha_public_key = pub_key,
+ captcha_private_key = priv_key)
return deform.widget.HiddenWidget()
View
48 voteit/core/schemas/tests/test_tzdatetime.py
@@ -1,14 +1,20 @@
import unittest
+from datetime import date
+from datetime import datetime
+import colander
from pyramid import testing
-from zope.interface.verify import verifyClass
-from zope.interface.verify import verifyObject
+
+from voteit.core.models.interfaces import IDateTimeUtil
class TZDateTimeTests(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
+ self.config.registry.settings['default_locale_name'] = 'en'
+ self.config.registry.settings['default_timezone_name'] = "Europe/Stockholm"
+ self.config.include('voteit.core.models.date_time_util')
def tearDown(self):
testing.tearDown()
@@ -18,4 +24,40 @@ def _cut(self):
from voteit.core.schemas.tzdatetime import TZDateTime
return TZDateTime
- #FIXME: When TZDateTime issues are fixed, write tests
+ def test_serialize_datetime(self):
+ obj = self._cut()
+ dt_util = self.config.registry.getUtility(IDateTimeUtil)
+ dt = dt_util.localize(datetime.strptime('2005-03-05 23:00', "%Y-%m-%d %H:%M"))
+ self.assertEqual(obj.serialize(None, dt), '2005-03-05 23:00')
+
+ def test_serialize_date(self):
+ obj = self._cut()
+ self.assertEqual(obj.serialize(None, date(2005, 03, 05)), '2005-03-05 00:00')
+
+ def test_serialize_bad_datetime(self):
+ obj = self._cut()
+ now = datetime.now()
+ self.assertRaises(ValueError, obj.serialize, None, now)
+
+ def test_serialize_null(self):
+ obj = self._cut()
+ self.assertEqual(obj.serialize(None, colander.null), colander.null)
+
+ def test_serialize_bad_data(self):
+ obj = self._cut()
+ self.assertRaises(colander.Invalid, obj.serialize, None, 'Hello!')
+
+ def test_deserialize_null(self):
+ obj = self._cut()
+ self.assertEqual(obj.deserialize(None, colander.null), colander.null)
+
+ def test_deserialize(self):
+ import pytz
+ obj = self._cut()
+ dt = "2005-03-05T23:00"
+ res = obj.deserialize(None, dt)
+ self.assertEqual(res.tzinfo, pytz.utc)
+
+ def test_deserialize_bad_input(self):
+ obj = self._cut()
+ self.assertRaises(colander.Invalid, obj.deserialize, None, 'Hello!')
View
27 voteit/core/schemas/tzdatetime.py
@@ -1,6 +1,5 @@
import datetime
-import iso8601
from zope.component import getUtility
from colander import SchemaType
from colander import Invalid
@@ -25,10 +24,11 @@ def serialize(self, node, appstruct):
if type(appstruct) is datetime.date: # cant use isinstance; dt subs date
appstruct = datetime.datetime.combine(appstruct, datetime.time())
+ appstruct = dt_util.localize(appstruct)
if not isinstance(appstruct, datetime.datetime):
raise Invalid(node,
- _("'${val}' is not valid as date and time",
+ _(u"'${val}' is not valid as date and time",
mapping={'val':appstruct})
)
#FIXME: Don't use strftime, util already has a method for that
@@ -36,26 +36,17 @@ def serialize(self, node, appstruct):
return dt_util.utc_to_tz(appstruct).strftime('%Y-%m-%d %H:%M')
def deserialize(self, node, cstruct):
- dt_util = getUtility(IDateTimeUtil)
if not cstruct:
return null
-
+ dt_util = getUtility(IDateTimeUtil)
try:
#FIXME: Imput format must be from the current locale
result = datetime.datetime.strptime(cstruct, "%Y-%m-%dT%H:%M")
-
- # python's datetime doesn't deal correctly with DST, so we have
- # to use the pytz localize function instead
+ # python's datetime doesn't deal correctly with DST but our util uses pytz
result = result.replace(tzinfo=None)
result = dt_util.localize(result)
-
- except (iso8601.ParseError, TypeError), e:
- try:
- year, month, day = map(int, cstruct.split('-', 2))
- result = datetime.datetime(year, month, day,
- tzinfo=self.default_tzinfo)
- except Exception, e:
- raise Invalid(node, _(self.err_template,
- mapping={'val':cstruct, 'err':e}))
-
- return dt_util.tz_to_utc(result)
+ return dt_util.tz_to_utc(result)
+ except ValueError, e:
+ raise Invalid(node,
+ _(u"'${val}' is not valid as date and time",
+ mapping={'val': unicode(cstruct)}))
View
32 voteit/core/tests/test_login.py
@@ -1,32 +0,0 @@
-import unittest
-
-from pyramid import testing
-
-
-class FunctionalLoginTests(unittest.TestCase):
- def setUp(self):
- self.config = testing.setUp()
-
- def tearDown(self):
- testing.tearDown()
-
- def _make_browser(self):
- #FIXME: We need to check proper testing of ZODB
- from zope.testbrowser.wsgi import Browser
- from voteit.core import main
- settings = {}
- settings['zodb_uri'] = "file:///tmp/Data.fs?connection_cache_size=20000"
- app = main({}, **settings)
- return Browser('http://localhost/', wsgi_app=app)
-
-# def test_failed_login(self):
-# browser = self._make_browser()
-# browser.getLink('Login').click()
-# self.assertEqual(browser.url, 'http://localhost/login')
-#
-# browser.getControl(name='userid').value = 'test'
-# browser.getControl(name='password').value = 'test'
-# browser.getControl('Log In').click()
-# self.assertEqual(browser.url, 'http://localhost/login')
-# self.failUnless('Login failed' in browser.contents)
-#
View
67 voteit/core/tests/test_widgets.py
@@ -0,0 +1,67 @@
+import unittest
+
+import colander
+import deform
+from pyramid import testing
+from fanstatic import get_needed
+from fanstatic import init_needed
+from fanstatic import NeededResources
+
+
+class StarWidgetTests(unittest.TestCase):
+
+ def setUp(self):
+ self.config = testing.setUp()
+
+ def tearDown(self):
+ testing.tearDown()
+
+ @property
+ def _cut(self):
+ from voteit.core.widgets import StarWidget
+ return StarWidget
+
+ def test_start_raiting_included(self):
+ from voteit.core.fanstaticlib import _star_rating_css
+ init_needed()
+ obj = self._cut()
+ needed = get_needed().resources()
+ self.assertIn(_star_rating_css, needed)
+
+
+class RecaptchaWidgetTests(unittest.TestCase):
+
+ def setUp(self):
+ request = testing.DummyRequest(remote_addr = '127.0.0.1')
+ self.config = testing.setUp(request = request)
+ self.config.include('voteit.core.deform_bindings')
+
+ def tearDown(self):
+ testing.tearDown()
+
+ @property
+ def _cut(self):
+ from voteit.core.widgets import RecaptchaWidget
+ return RecaptchaWidget
+
+ def _dummy_field(self):
+ class DummySchema(colander.Schema):
+ this_field = colander.SchemaNode(colander.String(),
+ widget = self._cut())
+ form = deform.Form(DummySchema())
+ return form['this_field']
+
+ def test_serialize(self):
+ obj = self._cut()
+ field = self._dummy_field()
+ self.assertIn('http://www.google.com/recaptcha', obj.serialize(field, ''))
+
+#We can't test this since it requires active network connection and a working API key :/
+# def test_deserialize(self):
+# obj = self._cut(PUBKEY, PRIVKEY)
+# field = self._dummy_field()
+# pstruct = {u'recaptcha_challenge_field': u'dummy', u'recaptcha_response_field': u'sdfs'}
+# try:
+# res = obj.deserialize(field, pstruct)
+# except colander.Invalid, e:
+# self.assertEqual(e.msg, 'invalid-request-cookie')
View
7 voteit/core/widgets.py
@@ -30,21 +30,22 @@ class RecaptchaWidget(CheckedInputWidget):
url = "http://www.google.com/recaptcha/api/verify"
headers = {'Content-type': 'application/x-www-form-urlencoded'}
- def __init__(self, captcha_public_key, captcha_private_key):
+ def __init__(self, captcha_public_key = u'', captcha_private_key = u''):
super(RecaptchaWidget, self).__init__()
self.captcha_public_key = captcha_public_key
self.captcha_private_key = captcha_private_key
def serialize(self, field, cstruct, readonly=False):
if cstruct in (null, None):
- cstruct = ''
+ cstruct = '' #pragma : no cover
confirm = getattr(field, 'confirm', '')
template = readonly and self.readonly_template or self.template
return field.renderer(template, field=field, cstruct=cstruct,
public_key=self.captcha_public_key,
)
- def deserialize(self, field, pstruct):
+ def deserialize(self, field, pstruct): #pragma : no cover
+ #We can't test this part properly since it requires Google API connection :(
if pstruct is null:
return null
challenge = pstruct.get('recaptcha_challenge_field') or ''

No commit comments for this range

Something went wrong with that request. Please try again.