def test_login__form_submission__success(self, remember): from nuvavaalit.models import Voter from nuvavaalit.views.login import login session = DBSession() session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers')) session.flush() self.assertEquals( session.query(Voter).filter_by(username=u'buck.rogers').first().fullname(), u'Bück Rögers') remember.return_value = [('X-Login', 'buck.rogers')] request = testing.DummyRequest(statsd=False) token = request.session.new_csrf_token() request.POST = { 'form.submitted': u'1', 'username': u'buck.rogers', 'password': u'secret', 'csrf_token': token, } response = login(request) self.assertEquals(dict(response.headers), { 'Content-Length': '0', 'Content-Type': 'text/html; charset=UTF-8', 'Location': 'http://example.com/valitse', 'X-Login': '******'})
def test_candidates(self): from nuvavaalit.models import Candidate from nuvavaalit.views.public import browse_candidates session = DBSession() session.add(Candidate(2, u'Steven', u'Seagal', u'No pain, no game', u'')) session.add(Candidate(7, u'Jet', u'Li', u'Yin, yang', u'')) session.add(Candidate(11, u'Jean-Claude', u'van Damme', u'No engrish', u'')) session.flush() options = browse_candidates(testing.DummyRequest(statsd=False)) positions = options.pop('positions') self.assertEquals('0 1:3 2:3 0 1:3 2:3'.split(), [positions.next() for i in xrange(6)]) self.assertEquals(list(options.pop('candidates')), [ [{'image_url': 'http://example.com/static/images/candidates/2.jpg', 'name': u'Seagal, Steven', 'number': 2, 'slogan': u'No pain, no game'}, {'image_url': 'http://example.com/static/images/candidates/7.jpg', 'name': u'Li, Jet', 'number': 7, 'slogan': u'Yin, yang'}, {'image_url': 'http://example.com/static/images/candidates/11.jpg', 'name': u'van Damme, Jean-Claude', 'number': 11, 'slogan': u'No engrish'}]]) self.assertEquals(options, { 'columns': 3, 'page_name': 'browse'})
def test_login__form_submission__invalid_password(self): from nuvavaalit.models import Voter from nuvavaalit.views.login import login session = DBSession() session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers')) session.flush() self.assertEquals( session.query(Voter).filter_by(username=u'buck.rogers').first().fullname(), u'Bück Rögers') request = testing.DummyRequest(statsd=False) token = request.session.new_csrf_token() request.POST = { 'form.submitted': u'1', 'username': u'buck.rogers', 'password': u'thisiswrong', 'csrf_token': token, } options = login(request) self.assertEquals(options, { 'action_url': 'http://example.com/tunnistaudu', 'csrf_token': token, 'error': u'Tunnistautuminen epäonnistui. Kokeile tunnistautua uudelleen!'})
def test_no_votes(self): from nuvavaalit.models import Candidate from nuvavaalit.models import Voter from nuvavaalit.views.results import results session = DBSession() session.add(Voter(u"buck.rogers", u"secret", u"Bück", u"Rögers")) session.add(Candidate(2, u"Steven", u"Seagal", u"No pain, no game", u"")) session.add(Candidate(7, u"Jet", u"Li", u"Yin, yang", u"")) session.add(Candidate(11, u"Jean-Claude", u"van Damme", u"No engrish", u"")) session.flush() self.assertEquals( results(testing.DummyRequest(statsd=False)), { "others": [], "selected": [ {"name": u"Li, Jet", "number": 7, "percentage": "0.0", "votes": 0}, {"name": u"Seagal, Steven", "number": 2, "percentage": "0.0", "votes": 0}, {"name": u"van Damme, Jean-Claude", "number": 11, "percentage": "0.0", "votes": 0}, ], "threshold": 8, "total_votes": 0, "show_leftovers": False, "voting_percentage": "0.0", }, )
def test_encrypted_link_matches_selection(self): from nuvavaalit.models import Candidate from nuvavaalit.models import Voter session = DBSession() session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers')) session.add(Candidate(2, u'Steven', u'Seagal', u'No pain, no game', u'')) session.add(Candidate(7, u'Jet', u'Li', u'Yin, yang', u'')) session.add(Candidate(11, u'Jean-Claude', u'van Damme', u'No engrish', u'')) session.flush() response = self.testapp.get('/tunnistaudu') response.form['username'] = u'buck.rogers' response.form['password'] = u'secret' response = response.form.submit() self.assertEquals(response.status, '302 Found') self.assertEquals(response.location, 'http://localhost/valitse') response = response.follow() self.assertEquals(response.request.url, 'http://localhost/valitse') voting_links = response.html.findAll('a', attrs={'href': re.compile('^http://localhost/aanesta/')}) self.assertEquals(voting_links[1]['href'], voting_links[2]['href']) self.assertEquals(voting_links[2].text, u'Seagal, Steven, 2') # Click the voting link response = self.testapp.get(voting_links[2]['href']) # Assert that we get a matching candidate selection self.assertEquals(response.html.find('p', attrs={'class': 'candidate-name'}).text, u'2 Seagal, Steven')
def run(self): session = DBSession() session.bind.echo = False # Join the repoze.filesafe manager in the transaction so that files will # be written only when a transaction commits successfully. filesafe = FileSafeDataManager() transaction.get().join(filesafe) # Query the currently existing usernames to avoid UNIQUE violations. self.usernames.update(username for cols in session.query(Voter.username).all() for username in cols) fh_itella = filesafe.createFile(self.output, 'w') # Excel worksheet for Itella wb_itella = xlwt.Workbook(encoding='utf-8') ws_itella = wb_itella.add_sheet('Hexagon IT') text_formatting = xlwt.easyxf(num_format_str='@') for col, header in enumerate([u'Tunnus', u'Salasana', u'Nimi', u'Osoite', u'Postinumero', u'Postitoimipaikka']): ws_itella.write(0, col, header, text_formatting) rows_itella = count(1) voter_count = 0 self.header('Starting to process {}'.format(self.source_file)) src_sheet = xlrd.open_workbook(self.source_file).sheet_by_index(0) pbar = progressbar.ProgressBar(widgets=[progressbar.Percentage(), progressbar.Bar()], maxval=src_sheet.nrows).start() for row in xrange(1, src_sheet.nrows): token, lastname, names, address, zipcode, city = [c.value for c in src_sheet.row_slice(row, 0, 6)] names = names.split() firstname = names[0] username = self.genusername(names, lastname) password = self.genpasswd() # Create the voter instance. session.add(Voter(username, password, firstname, lastname, token)) # Write the Itella information row = rows_itella.next() for col, item in enumerate([username, password, u'{} {}'.format(u' '.join(names), lastname), address, zipcode, city]): ws_itella.write(row, col, item, text_formatting) voter_count += 1 pbar.update(voter_count) wb_itella.save(fh_itella) fh_itella.close() session.flush() transaction.commit() pbar.finish() self.header('Finished processing') print 'Processed', voter_count, 'voters.'
def test_voting_forbidden_authorized_after_election_period(self): from nuvavaalit.models import Voter session = DBSession() session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers')) session.flush() self.authenticate(u'buck.rogers') response = self.testapp.get('/aanesta/abcdefg', expect_errors=True) self.assertEquals(response.status, '403 Forbidden')
def test_stable_sorting_of_equals(self): """Test that in case of a tie we get a stable but random sorting of candidates.""" from nuvavaalit.models import Candidate from nuvavaalit.models import Vote from nuvavaalit.models import Voter from nuvavaalit.views.results import results session = DBSession() session.add(Voter(u"buck.rogers", u"secret", u"Bück", u"Rögers")) session.add(Candidate(2, u"Steven", u"Seagal", u"No pain, no game", u"")) session.add(Candidate(7, u"Jet", u"Li", u"Yin, yang", u"")) session.add(Candidate(11, u"Jean-Claude", u"van Damme", u"No engrish", u"")) session.flush() candidate_two = session.query(Candidate).filter_by(number=2).first() candidate_seven = session.query(Candidate).filter_by(number=7).first() session.add(Vote(candidate_two)) session.add(Vote(candidate_seven)) session.flush() self.assertEquals( results(testing.DummyRequest(statsd=False)), { "others": [], "selected": [ {"name": u"Li, Jet", "number": 7, "percentage": "50.0", "votes": 1}, {"name": u"Seagal, Steven", "number": 2, "percentage": "50.0", "votes": 1}, {"name": u"van Damme, Jean-Claude", "number": 11, "percentage": "0.0", "votes": 0}, ], "threshold": 8, "total_votes": 2, "show_leftovers": False, "voting_percentage": "200.0", }, ) # Rendering the results again will result in the same relative ordering # of the equal votes. self.assertEquals( results(testing.DummyRequest(statsd=False)), { "others": [], "selected": [ {"name": u"Li, Jet", "number": 7, "percentage": "50.0", "votes": 1}, {"name": u"Seagal, Steven", "number": 2, "percentage": "50.0", "votes": 1}, {"name": u"van Damme, Jean-Claude", "number": 11, "percentage": "0.0", "votes": 0}, ], "threshold": 8, "total_votes": 2, "show_leftovers": False, "voting_percentage": "200.0", }, )
def populate_test_users(): """Populates the database with test users.""" parser = argparse.ArgumentParser(description='Generates test users in the database.') parser.add_argument('config', help='Path to a Paste configuration file, e.g. development.ini.') parser.add_argument('quantity', nargs='?', default=10, type=int, help='Number of test users to generate.') args = parser.parse_args() env = bootstrap(relpath(args.config)) session = DBSession() session.bind.echo = False for i in xrange(1, args.quantity + 1): session.add(Voter(u'user{}'.format(i), u'testi', u'User #{}'.format(i), u'Fööbär')) session.flush() transaction.commit() print "Created {} test users".format(args.quantity) env['closer']()
def test_empty_votes_removed_from_results_listing(self): """Test that in case of a tie we get a stable but random sorting of candidates.""" from nuvavaalit.models import Candidate from nuvavaalit.models import Vote from nuvavaalit.models import Voter from nuvavaalit.views.results import results session = DBSession() session.add(Voter(u"buck.rogers", u"secret", u"Bück", u"Rögers")) session.add(Candidate(Candidate.EMPTY_CANDIDATE, u"empty", u"empty", u"empty", u"empty")) session.add(Candidate(2, u"Steven", u"Seagal", u"No pain, no game", u"")) session.add(Candidate(7, u"Jet", u"Li", u"Yin, yang", u"")) session.add(Candidate(11, u"Jean-Claude", u"van Damme", u"No engrish", u"")) session.flush() candidate_two = session.query(Candidate).filter_by(number=2).first() candidate_seven = session.query(Candidate).filter_by(number=7).first() candidate_empty = session.query(Candidate).filter_by(number=Candidate.EMPTY_CANDIDATE).first() session.add(Vote(candidate_two)) session.add(Vote(candidate_seven)) session.add(Vote(candidate_empty)) session.add(Vote(candidate_empty)) session.flush() # The empty votes do not show up in the results listing but do # affect the number of votes, percentages, etc. self.assertEquals( results(testing.DummyRequest(statsd=False)), { "others": [], "selected": [ {"name": u"Li, Jet", "number": 7, "percentage": "25.0", "votes": 1}, {"name": u"Seagal, Steven", "number": 2, "percentage": "25.0", "votes": 1}, {"name": u"van Damme, Jean-Claude", "number": 11, "percentage": "0.0", "votes": 0}, ], "threshold": 8, "total_votes": 4, "show_leftovers": False, "voting_percentage": "400.0", }, )
def test_already_voted_user_is_logged_out(self): from nuvavaalit.models import Voter from nuvavaalit.models import VotingLog session = DBSession() voter = Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers') session.add(voter) session.flush() session.add(VotingLog(voter)) session.flush() self.assertTrue(voter.has_voted()) self.authenticate(u'buck.rogers') response = self.testapp.get('/valitse') # An already voted user is redirected to the thank you page. self.assertEquals(response.status, '302 Found') self.assertEquals(response.location, 'http://localhost/kiitos') # Assert that we get cookies that log out the user. self.assertLogoutCookies(response)
def test_different_sessions_get_different_vote_links(self): from nuvavaalit.models import Candidate from nuvavaalit.models import Voter session = DBSession() session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers')) session.add(Candidate(2, u'Steven', u'Seagal', u'No pain, no game', u'')) session.add(Candidate(7, u'Jet', u'Li', u'Yin, yang', u'')) session.add(Candidate(11, u'Jean-Claude', u'van Damme', u'No engrish', u'')) session.flush() response = self.testapp.get('/tunnistaudu') response.form['username'] = u'buck.rogers' response.form['password'] = u'secret' response = response.form.submit() self.assertEquals(response.status, '302 Found') self.assertEquals(response.location, 'http://localhost/valitse') response = response.follow() self.assertEquals(response.request.url, 'http://localhost/valitse') # Get a list of voting links voting_links = [str(tag) for tag in response.html.findAll('a', attrs={'href': re.compile('^http://localhost/aanesta/')})] # Login again to the application, creating a new session response = self.testapp.get('/tunnistaudu') response.form['username'] = u'buck.rogers' response.form['password'] = u'secret' response = response.form.submit() self.assertEquals(response.status, '302 Found') self.assertEquals(response.location, 'http://localhost/valitse') response = response.follow() self.assertEquals(response.request.url, 'http://localhost/valitse') new_voting_links = [str(tag) for tag in response.html.findAll('a', attrs={'href': re.compile('^http://localhost/aanesta/')})] self.assertEquals(len(voting_links), len(new_voting_links)) self.assertNotEqual(voting_links, new_voting_links)
def populate_candidates(): """Populates the database with candidate information.""" parser = argparse.ArgumentParser(description='Generates candidates in the database.') parser.add_argument('config', help='Path to a Paste configuration file, e.g. development.ini.') parser.add_argument('candidates', nargs='?', help='Path to a CSV file containing the candidate information.') args = parser.parse_args() env = bootstrap(relpath(args.config)) session = DBSession() session.bind.echo = False # Create the candidate for empty votes. session.add(Candidate(Candidate.EMPTY_CANDIDATE, u'Tyhjä', u'', u'', u'')) csv_file = relpath(args.candidates) reader = csv.reader(open(csv_file)) print 'Reading candidates from', csv_file cnt = 0 reader.next() for row in reader: number, firstname, lastname, slogan = row[:4] try: number = int(number.strip()) except (TypeError, ValueError): print 'Invalid data: {}'.format(str(row)) continue session.add(Candidate(number, univalue(firstname), univalue(lastname), univalue(slogan), u'')) print 'Added {} {}, {}'.format(firstname, lastname, number) cnt += 1 session.flush() transaction.commit() print "Created {} candidates.".format(cnt) env['closer']()
def test_successful_voting_process(self): from nuvavaalit.models import Candidate from nuvavaalit.models import Vote from nuvavaalit.models import Voter from nuvavaalit.models import VotingLog # Create a user we will authenticate as. session = DBSession() session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers')) session.add(Candidate(2, u'Steven', u'Seägäl', u'No pain, no game', u'')) session.add(Candidate(7, u'Jët', u'Li', u'Yin, yang', u'')) session.add(Candidate(11, u'Jeän-Claüde', u'van Damme', u'No engrish', u'')) session.flush() self.assertEquals(0, session.query(Vote).count()) self.assertEquals(0, session.query(VotingLog).count()) self.authenticate(u'buck.rogers') # Accessing the system front page will redirect us to the login page # during the elections. response = self.testapp.get('/') self.assertEquals(response.status, '302 Found') self.assertEquals(response.location, 'http://localhost/tunnistaudu') response = response.follow() # Logging in the system successfully will bring us to the candidate # selection page. response.form['username'] = u'buck.rogers' response.form['password'] = u'secret' response = response.form.submit() self.assertEquals(response.status, '302 Found') self.assertEquals(response.location, 'http://localhost/valitse') response = response.follow() # Selecting a candidate brings us to the voting page. self.assertEquals(response.request.url, 'http://localhost/valitse') voting_links = response.html.findAll('a', attrs={'href': re.compile('^http://localhost/aanesta/')}) # Assert we have two links to the candidate. self.assertEquals(voting_links[1]['href'], voting_links[2]['href']) self.assertEquals(voting_links[2].text, u'Seägäl, Steven, 2') # Click the voting link response = self.testapp.get(voting_links[2]['href']) self.assertTrue(response.request.url.startswith('http://localhost/aanesta/')) # Assert that we get a matching candidate selection self.assertEquals(response.html.find('p', attrs={'class': 'candidate-name'}).text, u'2 Seägäl, Steven') # Attempting to vote a non-selected candidate gives us an error message. response.form['vote'] = u'69' response = response.form.submit() self.assertTrue(response.html.find('div', attrs={'class': 'error'}).text.startswith(u'Antamasi ehdokasnumero ei vastaa valintaasi')) self.assertTrue(response.request.url.startswith('http://localhost/aanesta/')) # Voting for the selected candidate stores the vote and logs out the user. response.form['vote'] = u'2' response = response.form.submit() self.assertEquals(response.status, '302 Found') self.assertEquals(response.location, 'http://localhost/kiitos') # Assert that we get cookies that log out the user. self.assertLogoutCookies(response) # Assert that the vote was recorded correctly. self.assertEquals(2, session.query(Vote).one().candidate.number) self.assertEquals(u'buck.rogers', session.query(VotingLog).one().voter.username) # Assert that subsequent attempts to login results in automatic logout. response = self.testapp.get('/tunnistaudu') response.form['username'] = u'buck.rogers' response.form['password'] = u'secret' response = response.form.submit() self.assertEquals(response.status, '302 Found') self.assertEquals(response.location, 'http://localhost/kiitos') # Assert that we get cookies that log out the user. self.assertLogoutCookies(response)