fedora_elections/__init__.py | 8 +
fedora_elections/default_config.py | 11 ++
fedora_elections/elections.py | 45 ++++++++++
fedora_elections/forms.py | 15 +++
fedora_elections/models.py | 2
tests/test_candidate.py | 22 +++++
tests/test_election.py | 32 ++++++-
tests/test_flask.py | 10 +-
tests/test_flask_irc.py | 157 +++++++++++++++++++++++++++++++++++++
tests/test_vote.py | 12 ++
10 files changed, 303 insertions(+), 11 deletions(-)
New commits:
commit 6ff26d188985174fedadcf76538c9d2e7a386cf1
Merge: b1396a3 398d7d3
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 17:10:55 2014 +0200
Merge pull request #35 from fedora-infra/permanent_session
Permanent session
commit 398d7d3f4f1449f84189472e3718e75b92c3155d
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 16:46:57 2014 +0200
Add header and a default time-out period for the session in the default configuration
file
diff --git a/fedora_elections/default_config.py b/fedora_elections/default_config.py
index 9a37e23..979dd9d 100644
--- a/fedora_elections/default_config.py
+++ b/fedora_elections/default_config.py
@@ -1,3 +1,14 @@
+# -*- coding: utf-8 -*-
+
+'''
+Fedora elections default configuration.
+'''
+
+from datetime import timedelta
+
+# Set the time after which the session expires
+PERMANENT_SESSION_LIFETIME = timedelta(hours=1)
+
FEDORA_ELECTIONS_ADMIN_GROUP = 'elections'
# url to the database server:
commit 32788ff1f7219ec341ea0421e3672debe51d094e
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 16:46:35 2014 +0200
Activate the permanent session so that session time-out as specified in the
configuration file
diff --git a/fedora_elections/__init__.py b/fedora_elections/__init__.py
index 2fd1222..131f320 100644
--- a/fedora_elections/__init__.py
+++ b/fedora_elections/__init__.py
@@ -152,6 +152,7 @@ def inject_variables():
return dict(is_admin=is_admin(user),
version=__version__)
+
@APP.template_filter('rjust')
def rjust_filter(text, length):
""" Run a rjust command on the text for the given length
@@ -159,6 +160,13 @@ def rjust_filter(text, length):
return str(text).rjust(length)
+# pylint: disable=W0613
+(a)APP.before_request
+def set_session():
+ """ Set the flask session as permanent. """
+ flask.session.permanent = True
+
+
# LIST VIEWS #############################################
@APP.route('/')
commit b1396a3567540aa03aaccabe8903fa97c805fa83
Merge: 1f21208 8a42ce6
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 16:34:51 2014 +0200
Merge pull request #34 from fedora-infra/for_abstain_against_vote
For abstain against vote
commit 8a42ce62abbefb172d0cf8c575b5f843d987b0e6
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 16:32:42 2014 +0200
One more forAbstainAgainst to change
diff --git a/tests/test_election.py b/tests/test_election.py
index 583ce13..b33bf86 100644
--- a/tests/test_election.py
+++ b/tests/test_election.py
@@ -172,7 +172,7 @@ class Electiontests(Modeltests):
self.session.add(obj)
self.session.commit()
self.assertNotEqual(obj, None)
- # Election - forAbstainAgainst voting - Open
+ # Election - IRC voting - Open
obj = models.Election( # id:7
shortdesc='test election 7 shortdesc',
alias='test_election7',
commit 8ffd821696d0409ebd03413b380434e1e091babb
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 16:30:17 2014 +0200
Adjust test function names and docstrings for the change in the type
diff --git a/tests/test_flask_irc.py b/tests/test_flask_irc.py
index 44d467d..9c45fa4 100644
--- a/tests/test_flask_irc.py
+++ b/tests/test_flask_irc.py
@@ -44,8 +44,8 @@ from tests import ModelFlasktests, Modeltests, TODAY, FakeUser,
user_set
class FlaskIrcElectionstests(ModelFlasktests):
""" Flask application tests irc voting. """
- def test_vote_for_abstain_against(self):
- """ Test the vote_for_abstain_against function - the preview part.
"""
+ def test_vote_irc(self):
+ """ Test the vote_irc function - the preview part.
"""
output = self.app.get(
'/vote/test_election', follow_redirects=True)
self.assertEqual(output.status_code, 200)
@@ -105,8 +105,8 @@ class FlaskIrcElectionstests(ModelFlasktests):
'<li class="message">Please confirm your
vote!</li>'
in output.data)
- def test_vote_for_abstain_against_process(self):
- """ Test the vote_for_abstain_against function - the voting part.
"""
+ def test_vote_irc_process(self):
+ """ Test the vote_irc function - the voting part.
"""
output = self.app.get(
'/vote/test_election', follow_redirects=True)
self.assertEqual(output.status_code, 200)
commit 64c3628ffa812ad5e642e3fd28932d63a1e1bacc
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 16:27:59 2014 +0200
Change ``for_abstain_against`` voting to ``irc`` voting
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index bfff1cd..2ad0e1e 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -117,8 +117,8 @@ def vote(election_alias):
return vote_simple(election)
elif election.voting_type == 'select':
return vote_select(election)
- elif election.voting_type == 'for_abstain_against':
- return vote_for_abstain_against(election)
+ elif election.voting_type == 'irc':
+ return vote_irc(election)
else: # pragma: no cover
flask.flash(
'Unknown election voting type: %s' % election.voting_type)
@@ -303,7 +303,7 @@ def vote_simple(election):
nextaction=next_action)
-def vote_for_abstain_against(election):
+def vote_irc(election):
votes = models.Vote.of_user_on_election(
SESSION, flask.g.fas_user.username, election.id, count=True)
@@ -314,7 +314,7 @@ def vote_for_abstain_against(election):
num_candidates = election.candidates.count()
next_action = 'confirm'
- form=forms.get_for_abstain_against_voting_form(
+ form=forms.get_irc_voting_form(
candidates=election.candidates,
fasusers=election.candidates_are_fasusers)
if form.validate_on_submit():
diff --git a/fedora_elections/forms.py b/fedora_elections/forms.py
index 50f676b..7150564 100644
--- a/fedora_elections/forms.py
+++ b/fedora_elections/forms.py
@@ -37,7 +37,7 @@ class ElectionForm(wtf.Form):
('range_3', 'Simplified Range Voting (max is set below)'),
('select', 'Select Voting (checkboxes for each candidate, '
'maximum number of votes set below)'),
- ('for_abstain_against', '+1/0/-1 voting'),
+ ('irc', '+1/0/-1 voting'),
],
default='range')
@@ -160,8 +160,8 @@ def get_simple_voting_form(candidates, fasusers):
return SimpleVoting()
-def get_for_abstain_against_voting_form(candidates, fasusers):
- class ForAbstainAgainstVoting(wtf.Form):
+def get_irc_voting_form(candidates, fasusers):
+ class IrcVoting(wtf.Form):
action = wtforms.HiddenField()
for candidate in candidates:
@@ -169,9 +169,9 @@ def get_for_abstain_against_voting_form(candidates, fasusers):
candidate.name,
choices=[('0',0),('1',1),('-1',-1)]
)
- setattr(ForAbstainAgainstVoting, candidate.name, field)
+ setattr(IrcVoting, candidate.name, field)
- return ForAbstainAgainstVoting()
+ return IrcVoting()
def get_select_voting_form(candidates, max_selection):
diff --git a/fedora_elections/models.py b/fedora_elections/models.py
index 1ff263f..74af82d 100644
--- a/fedora_elections/models.py
+++ b/fedora_elections/models.py
@@ -420,7 +420,7 @@ class Vote(BASE):
stats['max_vote'] = election.max_votes
elif election.voting_type == 'simple':
stats['max_vote'] = 1
- elif election.voting_type == 'for_abstain_against':
+ elif election.voting_type == 'irc':
stats['max_vote'] = 1
return stats
diff --git a/tests/test_election.py b/tests/test_election.py
index fe1e17e..583ce13 100644
--- a/tests/test_election.py
+++ b/tests/test_election.py
@@ -182,7 +182,7 @@ class Electiontests(Modeltests):
end_date=TODAY + timedelta(days=3),
seats_elected=1,
embargoed=1,
- voting_type='for_abstain_against',
+ voting_type='irc',
candidates_are_fasusers=0,
max_votes=1,
fas_user='nerdsville',
diff --git a/tests/test_flask_for_abstain_against_voting.py
b/tests/test_flask_for_abstain_against_voting.py
deleted file mode 100644
index 243159d..0000000
--- a/tests/test_flask_for_abstain_against_voting.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-"""
- (c) 2014 - Copyright Joshua Santos
- Author: Joshua Santos <nerdsville(a)nerdsville.net>
-
-# This copyrighted material is made available to anyone wishing to use, modify,
-# copy, or redistribute it subject to the terms and conditions of the GNU
-# General Public License v.2, or (at your option) any later version. This
-# program is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY expressed or implied, including the implied warranties of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-# Public License for more details. You should have received a copy of the GNU
-# General Public License along with this program; if not, write to the Free
-# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the source
-# code or documentation are not subject to the GNU General Public License and
-# may only be used or replicated with the express permission of Red Hat, Inc.
-
- fedora_elections.elections test script
-"""
-__requires__ = ['SQLAlchemy >= 0.7', 'jinja2 >= 2.4']
-import pkg_resources
-
-import logging
-import unittest
-import sys
-import os
-
-from datetime import time
-from datetime import timedelta
-
-import flask
-
-sys.path.insert(0, os.path.join(os.path.dirname(
- os.path.abspath(__file__)), '..'))
-
-import fedora_elections
-from tests import ModelFlasktests, Modeltests, TODAY, FakeUser, user_set
-
-
-# pylint: disable=R0904
-class FlaskSimpleElectionstests(ModelFlasktests):
- """ Flask application tests range voting. """
-
- def test_vote_for_abstain_against(self):
- """ Test the vote_for_abstain_against function - the preview part.
"""
- output = self.app.get(
- '/vote/test_election', follow_redirects=True)
- self.assertEqual(output.status_code, 200)
- self.assertTrue(
- '<title>OpenID transaction in progress</title>' in
output.data
- or 'discoveryfailure' in output.data)
-
- self.setup_db()
-
- user = FakeUser(['packager'], username='toshio')
- with user_set(fedora_elections.APP, user):
- output = self.app.get(
- '/vote/test_election7', follow_redirects=True)
- self.assertTrue(
- 'class="message">You have already voted in the
election!</'
- in output.data)
-
- user = FakeUser(['packager'], username='nerdsville')
- with user_set(fedora_elections.APP, user):
- output = self.app.get(
- '/vote/test_election7')
- self.assertTrue(
- '<h2>test election 7 shortdesc</h2>' in output.data)
- self.assertTrue(
- '<input type="hidden" name="action"
value="preview" />'
- in output.data)
-
- csrf_token = output.data.split(
- 'name="csrf_token" type="hidden"
value="')[1].split('">')[0]
-
- # Invalid vote: No candidate
- data = {
- 'action': 'preview',
- }
-
- output = self.app.post('/vote/test_election7', data=data)
- self.assertEqual(output.status_code, 200)
- self.assertTrue(
- '<h2>test election 7 shortdesc</h2>' in output.data)
-
- # Valid input
- data = {
- 'Kevin': -1,
- 'Toshio': '0',
- 'action': 'preview',
- 'csrf_token': csrf_token,
- }
-
- output = self.app.post('/vote/test_election7', data=data)
- self.assertEqual(output.status_code, 200)
- self.assertTrue(
- '<h2>test election 7 shortdesc</h2>' in output.data)
- self.assertTrue(
- '<input type="hidden" name="action"
value="submit" />'
- in output.data)
- self.assertTrue(
- '<li class="message">Please confirm your
vote!</li>'
- in output.data)
-
- def test_vote_for_abstain_against_process(self):
- """ Test the vote_for_abstain_against function - the voting part.
"""
- output = self.app.get(
- '/vote/test_election', follow_redirects=True)
- self.assertEqual(output.status_code, 200)
- self.assertTrue(
- '<title>OpenID transaction in progress</title>' in
output.data
- or 'discoveryfailure' in output.data)
-
- self.setup_db()
-
- user = FakeUser(['packager'], username='pingou')
- with user_set(fedora_elections.APP, user):
- # Invalid candidate id - no csrf
- data = {
- 'candidate': 1,
- 'action': 'submit',
- }
-
- output = self.app.post(
- '/vote/test_election7', data=data,
- follow_redirects=True)
- self.assertEqual(output.status_code, 200)
-
- csrf_token = output.data.split(
- 'name="csrf_token" type="hidden"
value="')[1].split('">')[0]
-
- # Valid input
- data = {
- 'Toshio': '0',
- 'Kevin': '1',
- 'action': 'submit',
- 'csrf_token': csrf_token,
- }
-
- output = self.app.post(
- '/vote/test_election7', data=data,
- follow_redirects=True)
- self.assertEqual(output.status_code, 200)
- self.assertTrue(
- 'class="message">Your vote has been recorded. Thank
you!</'
- in output.data)
- self.assertTrue('<h3>Current elections</h3>' in
output.data)
- self.assertTrue('<h3>Next 1 elections</h3>' in
output.data)
- self.assertTrue('<h3>Last 2 elections</h3>' in
output.data)
-
-
-if __name__ == '__main__':
- SUITE = unittest.TestLoader().loadTestsFromTestCase(FlaskSimpleElectionstests)
- unittest.TextTestRunner(verbosity=2).run(SUITE)
diff --git a/tests/test_flask_irc.py b/tests/test_flask_irc.py
new file mode 100644
index 0000000..44d467d
--- /dev/null
+++ b/tests/test_flask_irc.py
@@ -0,0 +1,157 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+ (c) 2014 - Copyright Joshua Santos
+ Author: Joshua Santos <nerdsville(a)nerdsville.net>
+
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2, or (at your option) any later version. This
+# program is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the GNU
+# General Public License along with this program; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the source
+# code or documentation are not subject to the GNU General Public License and
+# may only be used or replicated with the express permission of Red Hat, Inc.
+
+ fedora_elections.elections test script
+"""
+__requires__ = ['SQLAlchemy >= 0.7', 'jinja2 >= 2.4']
+import pkg_resources
+
+import logging
+import unittest
+import sys
+import os
+
+from datetime import time
+from datetime import timedelta
+
+import flask
+
+sys.path.insert(0, os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), '..'))
+
+import fedora_elections
+from tests import ModelFlasktests, Modeltests, TODAY, FakeUser, user_set
+
+
+# pylint: disable=R0904
+class FlaskIrcElectionstests(ModelFlasktests):
+ """ Flask application tests irc voting. """
+
+ def test_vote_for_abstain_against(self):
+ """ Test the vote_for_abstain_against function - the preview part.
"""
+ output = self.app.get(
+ '/vote/test_election', follow_redirects=True)
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ '<title>OpenID transaction in progress</title>' in
output.data
+ or 'discoveryfailure' in output.data)
+
+ self.setup_db()
+
+ user = FakeUser(['packager'], username='toshio')
+ with user_set(fedora_elections.APP, user):
+ output = self.app.get(
+ '/vote/test_election7', follow_redirects=True)
+ self.assertTrue(
+ 'class="message">You have already voted in the
election!</'
+ in output.data)
+
+ user = FakeUser(['packager'], username='nerdsville')
+ with user_set(fedora_elections.APP, user):
+ output = self.app.get(
+ '/vote/test_election7')
+ self.assertTrue(
+ '<h2>test election 7 shortdesc</h2>' in output.data)
+ self.assertTrue(
+ '<input type="hidden" name="action"
value="preview" />'
+ in output.data)
+
+ csrf_token = output.data.split(
+ 'name="csrf_token" type="hidden"
value="')[1].split('">')[0]
+
+ # Invalid vote: No candidate
+ data = {
+ 'action': 'preview',
+ }
+
+ output = self.app.post('/vote/test_election7', data=data)
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ '<h2>test election 7 shortdesc</h2>' in output.data)
+
+ # Valid input
+ data = {
+ 'Kevin': -1,
+ 'Toshio': '0',
+ 'action': 'preview',
+ 'csrf_token': csrf_token,
+ }
+
+ output = self.app.post('/vote/test_election7', data=data)
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ '<h2>test election 7 shortdesc</h2>' in output.data)
+ self.assertTrue(
+ '<input type="hidden" name="action"
value="submit" />'
+ in output.data)
+ self.assertTrue(
+ '<li class="message">Please confirm your
vote!</li>'
+ in output.data)
+
+ def test_vote_for_abstain_against_process(self):
+ """ Test the vote_for_abstain_against function - the voting part.
"""
+ output = self.app.get(
+ '/vote/test_election', follow_redirects=True)
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ '<title>OpenID transaction in progress</title>' in
output.data
+ or 'discoveryfailure' in output.data)
+
+ self.setup_db()
+
+ user = FakeUser(['packager'], username='pingou')
+ with user_set(fedora_elections.APP, user):
+ # Invalid candidate id - no csrf
+ data = {
+ 'candidate': 1,
+ 'action': 'submit',
+ }
+
+ output = self.app.post(
+ '/vote/test_election7', data=data,
+ follow_redirects=True)
+ self.assertEqual(output.status_code, 200)
+
+ csrf_token = output.data.split(
+ 'name="csrf_token" type="hidden"
value="')[1].split('">')[0]
+
+ # Valid input
+ data = {
+ 'Toshio': '0',
+ 'Kevin': '1',
+ 'action': 'submit',
+ 'csrf_token': csrf_token,
+ }
+
+ output = self.app.post(
+ '/vote/test_election7', data=data,
+ follow_redirects=True)
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ 'class="message">Your vote has been recorded. Thank
you!</'
+ in output.data)
+ self.assertTrue('<h3>Current elections</h3>' in
output.data)
+ self.assertTrue('<h3>Next 1 elections</h3>' in
output.data)
+ self.assertTrue('<h3>Last 2 elections</h3>' in
output.data)
+
+
+if __name__ == '__main__':
+ SUITE = unittest.TestLoader().loadTestsFromTestCase(FlaskIrcElectionstests)
+ unittest.TextTestRunner(verbosity=2).run(SUITE)
commit 22e5cffc30c89dea14819fb4ac2201c3914f72b2
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 16:18:40 2014 +0200
Name the `for_abstain_against` election type `+1/0/-1 voting` in the UI
diff --git a/fedora_elections/forms.py b/fedora_elections/forms.py
index dda16b3..50f676b 100644
--- a/fedora_elections/forms.py
+++ b/fedora_elections/forms.py
@@ -37,7 +37,7 @@ class ElectionForm(wtf.Form):
('range_3', 'Simplified Range Voting (max is set below)'),
('select', 'Select Voting (checkboxes for each candidate, '
'maximum number of votes set below)'),
- ('for_abstain_against', 'For - Abstain - Against (+1, neutral,
-1)'),
+ ('for_abstain_against', '+1/0/-1 voting'),
],
default='range')
commit d6ddf33bf2e83ca91386197ebf2adae9ed92f19c
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 15:00:57 2014 +0200
Adjust the unit-tests to handle the pro_abstain_against vote
diff --git a/tests/test_flask_for_abstain_against_voting.py
b/tests/test_flask_for_abstain_against_voting.py
index 2c5e99c..243159d 100644
--- a/tests/test_flask_for_abstain_against_voting.py
+++ b/tests/test_flask_for_abstain_against_voting.py
@@ -85,9 +85,11 @@ class FlaskSimpleElectionstests(ModelFlasktests):
self.assertEqual(output.status_code, 200)
self.assertTrue(
'<h2>test election 7 shortdesc</h2>' in output.data)
+
# Valid input
data = {
'Kevin': -1,
+ 'Toshio': '0',
'action': 'preview',
'csrf_token': csrf_token,
}
@@ -132,7 +134,8 @@ class FlaskSimpleElectionstests(ModelFlasktests):
# Valid input
data = {
- 'Toshio': True,
+ 'Toshio': '0',
+ 'Kevin': '1',
'action': 'submit',
'csrf_token': csrf_token,
}
commit a58e7ea1c654edd9f74b04eb2532dc32f69e94c9
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 14:58:52 2014 +0200
Adjust again the form logic for vote_for_abstain_against
The name of the field will be the name of the candidate and adjust the
logic to handle it as such
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index 7ba405d..bfff1cd 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -307,6 +307,10 @@ def vote_for_abstain_against(election):
votes = models.Vote.of_user_on_election(
SESSION, flask.g.fas_user.username, election.id, count=True)
+ cand_name = {}
+ for candidate in election.candidates:
+ cand_name[candidate.name] = candidate.id
+
num_candidates = election.candidates.count()
next_action = 'confirm'
@@ -318,12 +322,11 @@ def vote_for_abstain_against(election):
for candidate in form:
if candidate.short_name in ['csrf_token', 'action']:
continue
- cand_id = candidate.short_name.replace('candidate_', '')
new_vote = models.Vote(
election_id=election.id,
voter=flask.g.fas_user.username,
timestamp=datetime.now(),
- candidate_id=cand_id,
+ candidate_id=cand_name[candidate.short_name],
value=candidate.data,
)
SESSION.add(new_vote)
diff --git a/fedora_elections/forms.py b/fedora_elections/forms.py
index fc82721..dda16b3 100644
--- a/fedora_elections/forms.py
+++ b/fedora_elections/forms.py
@@ -164,15 +164,12 @@ def get_for_abstain_against_voting_form(candidates, fasusers):
class ForAbstainAgainstVoting(wtf.Form):
action = wtforms.HiddenField()
- fields = []
for candidate in candidates:
- fields.append(wtforms.SelectField(
+ field = wtforms.SelectField(
candidate.name,
choices=[('0',0),('1',1),('-1',-1)]
- ))
-
- for i,field in enumerate(fields):
- setattr(ForAbstainAgainstVoting,'candidate_'+str(i),field)
+ )
+ setattr(ForAbstainAgainstVoting, candidate.name, field)
return ForAbstainAgainstVoting()
commit bfa0f558f1f30fdb4daf43bc20ea346109ffc1d9
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 14:46:38 2014 +0200
Add some candidates to the election #7
diff --git a/tests/test_candidate.py b/tests/test_candidate.py
index aa87e95..90bdc08 100644
--- a/tests/test_candidate.py
+++ b/tests/test_candidate.py
@@ -187,6 +187,28 @@ class Candidatetests(Modeltests):
self.session.commit()
self.assertNotEqual(obj, None)
+ #
+ # Election #7
+ #
+
+ obj = models.Candidate( # id:14
+ election_id=7,
+ name='Toshio',
+
url='https://fedoraproject.org/wiki/User:Toshio';,
+ )
+ self.session.add(obj)
+ self.session.commit()
+ self.assertNotEqual(obj, None)
+
+ obj = models.Candidate( # id:15
+ election_id=7,
+ name='Kevin',
+
url='https://fedoraproject.org/wiki/User:Kevin';,
+ )
+ self.session.add(obj)
+ self.session.commit()
+ self.assertNotEqual(obj, None)
+
def test_to_json(self):
""" Test the Candidate.to_json function. """
self.test_init_candidate()
commit 7c282c7622c248b1e2df0ed63c7e1b20a44a2a45
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 14:38:46 2014 +0200
Fix get_election_stats for the `for_abstain_against` elections
diff --git a/fedora_elections/models.py b/fedora_elections/models.py
index 1cc51f4..1ff263f 100644
--- a/fedora_elections/models.py
+++ b/fedora_elections/models.py
@@ -420,6 +420,8 @@ class Vote(BASE):
stats['max_vote'] = election.max_votes
elif election.voting_type == 'simple':
stats['max_vote'] = 1
+ elif election.voting_type == 'for_abstain_against':
+ stats['max_vote'] = 1
return stats
commit df53ac4639dddfb6d149de0664c1fb70e3827536
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 14:38:20 2014 +0200
Simplify retrieving the candidate id submitted via the form
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index b50951a..7ba405d 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -315,18 +315,17 @@ def vote_for_abstain_against(election):
fasusers=election.candidates_are_fasusers)
if form.validate_on_submit():
if form.action.data == 'submit':
- i=0
for candidate in form:
if candidate.short_name in ['csrf_token', 'action']:
continue
+ cand_id = candidate.short_name.replace('candidate_', '')
new_vote = models.Vote(
election_id=election.id,
voter=flask.g.fas_user.username,
timestamp=datetime.now(),
- candidate_id=form.candidate_ids[i-1],
+ candidate_id=cand_id,
value=candidate.data,
)
- i += 1
SESSION.add(new_vote)
SESSION.commit()
flask.flash("Your vote has been recorded. Thank you!")
commit 27037ebd30c58d5e8d380b840f569bbb68ace74d
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Aug 26 14:38:01 2014 +0200
Simplify the form for get_for_abstain_against_voting_form
diff --git a/fedora_elections/forms.py b/fedora_elections/forms.py
index 68cbed3..fc82721 100644
--- a/fedora_elections/forms.py
+++ b/fedora_elections/forms.py
@@ -163,32 +163,17 @@ def get_simple_voting_form(candidates, fasusers):
def get_for_abstain_against_voting_form(candidates, fasusers):
class ForAbstainAgainstVoting(wtf.Form):
action = wtforms.HiddenField()
- titles = []
- candidate_ids = []
+
fields = []
for candidate in candidates:
- title = candidate.name
- if fasusers: # pragma: no cover
- # We can't cover FAS integration
- try:
- title = \
- FAS2.person_by_username(candidate.name)['human_name']
- except (KeyError, AuthError), err:
- APP.logger.debug(err)
- if candidate.url:
- title = '%s <a href="%s">[Info]</a>' % (title,
candidate.url)
- ForAbstainAgainstVoting.titles.append((str(candidate.id), title))
- ForAbstainAgainstVoting.candidate_ids.append(str(candidate.id))
fields.append(wtforms.SelectField(
candidate.name,
choices=[('0',0),('1',1),('-1',-1)]
))
- def validate_field(form, field):
- if field.data != '1' and field.data != '-1' and field.data !=
'0':
- raise wtforms.ValidationError(
- 'Not a valid integer value for vote.')
+
for i,field in enumerate(fields):
- setattr(ForAbstainAgainstVoting,'candidate'+str(i),field)
+ setattr(ForAbstainAgainstVoting,'candidate_'+str(i),field)
+
return ForAbstainAgainstVoting()
commit 59097d23b275b43240419ba927d96a2effd89257
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Mon Aug 25 07:54:08 2014 -0700
Adding unit tests
diff --git a/tests/test_election.py b/tests/test_election.py
index 2370716..fe1e17e 100644
--- a/tests/test_election.py
+++ b/tests/test_election.py
@@ -172,6 +172,24 @@ class Electiontests(Modeltests):
self.session.add(obj)
self.session.commit()
self.assertNotEqual(obj, None)
+ # Election - forAbstainAgainst voting - Open
+ obj = models.Election( # id:7
+ shortdesc='test election 7 shortdesc',
+ alias='test_election7',
+ description='test election 7 description',
+ url='https://fedoraproject.org',
+ start_date=TODAY - timedelta(days=1),
+ end_date=TODAY + timedelta(days=3),
+ seats_elected=1,
+ embargoed=1,
+ voting_type='for_abstain_against',
+ candidates_are_fasusers=0,
+ max_votes=1,
+ fas_user='nerdsville',
+ )
+ self.session.add(obj)
+ self.session.commit()
+ self.assertNotEqual(obj, None)
def test_get_election(self):
""" Test the Election.get function. """
@@ -246,13 +264,14 @@ class Electiontests(Modeltests):
obj = models.Election.search(self.session)
self.assertNotEqual(obj, None)
self.assertNotEqual(obj, [])
- self.assertEqual(len(obj), 6)
+ self.assertEqual(len(obj), 7)
self.assertEqual(obj[0].description, 'test election 4 description')
self.assertEqual(obj[1].description, 'test election 5 description')
self.assertEqual(obj[2].description, 'test election 6 description')
- self.assertEqual(obj[3].description, 'test election 3 description')
- self.assertEqual(obj[4].description, 'test election 2 description')
- self.assertEqual(obj[5].description, 'test election description')
+ self.assertEqual(obj[3].description, 'test election 7 description')
+ self.assertEqual(obj[4].description, 'test election 3 description')
+ self.assertEqual(obj[5].description, 'test election 2 description')
+ self.assertEqual(obj[6].description, 'test election description')
def test_get_older_election(self):
""" Test the Election.get_older_election function.
"""
@@ -270,10 +289,11 @@ class Electiontests(Modeltests):
obj = models.Election.get_open_election(self.session, limit=TODAY)
self.assertNotEqual(obj, None)
self.assertNotEqual(obj, [])
- self.assertEqual(len(obj), 3)
+ self.assertEqual(len(obj), 4)
self.assertEqual(obj[0].shortdesc, 'test election 5 shortdesc')
self.assertEqual(obj[1].shortdesc, 'test election 6 shortdesc')
- self.assertEqual(obj[2].shortdesc, 'test election 3 shortdesc')
+ self.assertEqual(obj[2].shortdesc, 'test election 7 shortdesc')
+ self.assertEqual(obj[3].shortdesc, 'test election 3 shortdesc')
def test_get_next_election(self):
""" Test the Election.get_next_election function.
"""
diff --git a/tests/test_flask.py b/tests/test_flask.py
index b9da2cd..9e7efbe 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -99,7 +99,7 @@ class Flasktests(ModelFlasktests):
self.assertTrue('<a href="/vote/' in output.data)
self.assertTrue(
'<span class="text">logged in as </span>'
in output.data)
- self.assertEqual(output.data.count('Vote now!'), 3)
+ self.assertEqual(output.data.count('Vote now!'), 4)
user = FakeUser([], username='toshio')
with user_set(fedora_elections.APP, user):
@@ -296,7 +296,7 @@ class Flasktests(ModelFlasktests):
output = self.app.get('/open')
self.assertEqual(output.status_code, 200)
self.assertTrue('<title>Fedora elections</title>' in
output.data)
- self.assertTrue('<h3>Next 3 elections</h3>' in output.data)
+ self.assertTrue('<h3>Next 4 elections</h3>' in output.data)
self.assertTrue('<td>test election 3 shortdesc</td>' in
output.data)
self.assertTrue('<a href="/vote/' in output.data)
self.assertTrue('<a href="/login">login</a>' in
output.data)
@@ -306,18 +306,18 @@ class Flasktests(ModelFlasktests):
output = self.app.get('/open')
self.assertEqual(output.status_code, 200)
self.assertTrue('<title>Fedora elections</title>' in
output.data)
- self.assertTrue('<h3>Next 3 elections</h3>' in
output.data)
+ self.assertTrue('<h3>Next 4 elections</h3>' in
output.data)
self.assertTrue('<a href="/vote/' in output.data)
self.assertTrue(
'<span class="text">logged in as </span>'
in output.data)
- self.assertEqual(output.data.count('Vote now!'), 3)
+ self.assertEqual(output.data.count('Vote now!'), 4)
user = FakeUser([], username='toshio')
with user_set(fedora_elections.APP, user):
output = self.app.get('/open')
self.assertEqual(output.status_code, 200)
self.assertTrue('<title>Fedora elections</title>' in
output.data)
- self.assertTrue('<h3>Next 3 elections</h3>' in
output.data)
+ self.assertTrue('<h3>Next 4 elections</h3>' in
output.data)
self.assertTrue(
'<span class="text">logged in as </span>'
in output.data)
self.assertEqual(output.data.count('Vote now!'), 0)
diff --git a/tests/test_flask_for_abstain_against_voting.py
b/tests/test_flask_for_abstain_against_voting.py
new file mode 100644
index 0000000..2c5e99c
--- /dev/null
+++ b/tests/test_flask_for_abstain_against_voting.py
@@ -0,0 +1,154 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+ (c) 2014 - Copyright Joshua Santos
+ Author: Joshua Santos <nerdsville(a)nerdsville.net>
+
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2, or (at your option) any later version. This
+# program is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the GNU
+# General Public License along with this program; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the source
+# code or documentation are not subject to the GNU General Public License and
+# may only be used or replicated with the express permission of Red Hat, Inc.
+
+ fedora_elections.elections test script
+"""
+__requires__ = ['SQLAlchemy >= 0.7', 'jinja2 >= 2.4']
+import pkg_resources
+
+import logging
+import unittest
+import sys
+import os
+
+from datetime import time
+from datetime import timedelta
+
+import flask
+
+sys.path.insert(0, os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), '..'))
+
+import fedora_elections
+from tests import ModelFlasktests, Modeltests, TODAY, FakeUser, user_set
+
+
+# pylint: disable=R0904
+class FlaskSimpleElectionstests(ModelFlasktests):
+ """ Flask application tests range voting. """
+
+ def test_vote_for_abstain_against(self):
+ """ Test the vote_for_abstain_against function - the preview part.
"""
+ output = self.app.get(
+ '/vote/test_election', follow_redirects=True)
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ '<title>OpenID transaction in progress</title>' in
output.data
+ or 'discoveryfailure' in output.data)
+
+ self.setup_db()
+
+ user = FakeUser(['packager'], username='toshio')
+ with user_set(fedora_elections.APP, user):
+ output = self.app.get(
+ '/vote/test_election7', follow_redirects=True)
+ self.assertTrue(
+ 'class="message">You have already voted in the
election!</'
+ in output.data)
+
+ user = FakeUser(['packager'], username='nerdsville')
+ with user_set(fedora_elections.APP, user):
+ output = self.app.get(
+ '/vote/test_election7')
+ self.assertTrue(
+ '<h2>test election 7 shortdesc</h2>' in output.data)
+ self.assertTrue(
+ '<input type="hidden" name="action"
value="preview" />'
+ in output.data)
+
+ csrf_token = output.data.split(
+ 'name="csrf_token" type="hidden"
value="')[1].split('">')[0]
+
+ # Invalid vote: No candidate
+ data = {
+ 'action': 'preview',
+ }
+
+ output = self.app.post('/vote/test_election7', data=data)
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ '<h2>test election 7 shortdesc</h2>' in output.data)
+ # Valid input
+ data = {
+ 'Kevin': -1,
+ 'action': 'preview',
+ 'csrf_token': csrf_token,
+ }
+
+ output = self.app.post('/vote/test_election7', data=data)
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ '<h2>test election 7 shortdesc</h2>' in output.data)
+ self.assertTrue(
+ '<input type="hidden" name="action"
value="submit" />'
+ in output.data)
+ self.assertTrue(
+ '<li class="message">Please confirm your
vote!</li>'
+ in output.data)
+
+ def test_vote_for_abstain_against_process(self):
+ """ Test the vote_for_abstain_against function - the voting part.
"""
+ output = self.app.get(
+ '/vote/test_election', follow_redirects=True)
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ '<title>OpenID transaction in progress</title>' in
output.data
+ or 'discoveryfailure' in output.data)
+
+ self.setup_db()
+
+ user = FakeUser(['packager'], username='pingou')
+ with user_set(fedora_elections.APP, user):
+ # Invalid candidate id - no csrf
+ data = {
+ 'candidate': 1,
+ 'action': 'submit',
+ }
+
+ output = self.app.post(
+ '/vote/test_election7', data=data,
+ follow_redirects=True)
+ self.assertEqual(output.status_code, 200)
+
+ csrf_token = output.data.split(
+ 'name="csrf_token" type="hidden"
value="')[1].split('">')[0]
+
+ # Valid input
+ data = {
+ 'Toshio': True,
+ 'action': 'submit',
+ 'csrf_token': csrf_token,
+ }
+
+ output = self.app.post(
+ '/vote/test_election7', data=data,
+ follow_redirects=True)
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ 'class="message">Your vote has been recorded. Thank
you!</'
+ in output.data)
+ self.assertTrue('<h3>Current elections</h3>' in
output.data)
+ self.assertTrue('<h3>Next 1 elections</h3>' in
output.data)
+ self.assertTrue('<h3>Last 2 elections</h3>' in
output.data)
+
+
+if __name__ == '__main__':
+ SUITE = unittest.TestLoader().loadTestsFromTestCase(FlaskSimpleElectionstests)
+ unittest.TextTestRunner(verbosity=2).run(SUITE)
diff --git a/tests/test_vote.py b/tests/test_vote.py
index c3d81e5..8d15279 100644
--- a/tests/test_vote.py
+++ b/tests/test_vote.py
@@ -176,6 +176,18 @@ class Votetests(Modeltests):
self.session.commit()
self.assertNotEqual(obj, None)
+ # Election 7
+
+ obj = models.Vote( #id:1
+ election_id=7,
+ voter='toshio',
+ candidate_id=12,
+ value='1',
+ )
+ self.session.add(obj)
+ self.session.commit()
+ self.assertNotEqual(obj, None)
+
def test_vote_count_with_votes(self):
""" Test the Candidate.vote_count function with votes in.
"""
self.test_init_vote()
commit 96c803a6ddf46e31f140e0b194e21929dafb1abd
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Mon Aug 4 16:53:41 2014 -0700
Adding for abstain against feature
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index 4abfbdc..b50951a 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -117,6 +117,8 @@ def vote(election_alias):
return vote_simple(election)
elif election.voting_type == 'select':
return vote_select(election)
+ elif election.voting_type == 'for_abstain_against':
+ return vote_for_abstain_against(election)
else: # pragma: no cover
flask.flash(
'Unknown election voting type: %s' % election.voting_type)
@@ -301,6 +303,47 @@ def vote_simple(election):
nextaction=next_action)
+def vote_for_abstain_against(election):
+ votes = models.Vote.of_user_on_election(
+ SESSION, flask.g.fas_user.username, election.id, count=True)
+
+ num_candidates = election.candidates.count()
+
+ next_action = 'confirm'
+ form=forms.get_for_abstain_against_voting_form(
+ candidates=election.candidates,
+ fasusers=election.candidates_are_fasusers)
+ if form.validate_on_submit():
+ if form.action.data == 'submit':
+ i=0
+ for candidate in form:
+ if candidate.short_name in ['csrf_token', 'action']:
+ continue
+ new_vote = models.Vote(
+ election_id=election.id,
+ voter=flask.g.fas_user.username,
+ timestamp=datetime.now(),
+ candidate_id=form.candidate_ids[i-1],
+ value=candidate.data,
+ )
+ i += 1
+ SESSION.add(new_vote)
+ SESSION.commit()
+ flask.flash("Your vote has been recorded. Thank you!")
+ return safe_redirect_back()
+
+ if form.action.data == 'preview':
+ flask.flash("Please confirm your vote!")
+ next_action = 'vote'
+
+ return flask.render_template(
+ 'vote_simple.html',
+ election=election,
+ form=form,
+ num_candidates=num_candidates,
+ nextaction=next_action)
+
+
@APP.route('/results/<election_alias>')
def election_results(election_alias):
election = get_valid_election(election_alias, ended=True)
diff --git a/fedora_elections/forms.py b/fedora_elections/forms.py
index 46c14ee..68cbed3 100644
--- a/fedora_elections/forms.py
+++ b/fedora_elections/forms.py
@@ -37,6 +37,7 @@ class ElectionForm(wtf.Form):
('range_3', 'Simplified Range Voting (max is set below)'),
('select', 'Select Voting (checkboxes for each candidate, '
'maximum number of votes set below)'),
+ ('for_abstain_against', 'For - Abstain - Against (+1, neutral,
-1)'),
],
default='range')
@@ -159,6 +160,38 @@ def get_simple_voting_form(candidates, fasusers):
return SimpleVoting()
+def get_for_abstain_against_voting_form(candidates, fasusers):
+ class ForAbstainAgainstVoting(wtf.Form):
+ action = wtforms.HiddenField()
+ titles = []
+ candidate_ids = []
+ fields = []
+ for candidate in candidates:
+ title = candidate.name
+ if fasusers: # pragma: no cover
+ # We can't cover FAS integration
+ try:
+ title = \
+ FAS2.person_by_username(candidate.name)['human_name']
+ except (KeyError, AuthError), err:
+ APP.logger.debug(err)
+ if candidate.url:
+ title = '%s <a href="%s">[Info]</a>' % (title,
candidate.url)
+ ForAbstainAgainstVoting.titles.append((str(candidate.id), title))
+ ForAbstainAgainstVoting.candidate_ids.append(str(candidate.id))
+ fields.append(wtforms.SelectField(
+ candidate.name,
+ choices=[('0',0),('1',1),('-1',-1)]
+ ))
+ def validate_field(form, field):
+ if field.data != '1' and field.data != '-1' and field.data !=
'0':
+ raise wtforms.ValidationError(
+ 'Not a valid integer value for vote.')
+ for i,field in enumerate(fields):
+ setattr(ForAbstainAgainstVoting,'candidate'+str(i),field)
+ return ForAbstainAgainstVoting()
+
+
def get_select_voting_form(candidates, max_selection):
class SelectVoting(wtf.Form):
action = wtforms.HiddenField()