import csv import io import random import json import pytz from django.conf import settings from django.contrib.auth.models import User from django.test import TestCase from django.urls import reverse from tracker import models from .util import today_noon, tomorrow_noon, long_ago_noon from .. import randgen class TestEvent(TestCase): def setUp(self): self.event = models.Event.objects.create(targetamount=1, datetime=today_noon) self.run = models.SpeedRun.objects.create( event=self.event, starttime=today_noon, order=0, run_time='00:01:00', setup_time='00:01:00', ) def test_update_first_run_if_event_time_changes(self): self.event.datetime = tomorrow_noon self.event.save() self.run.refresh_from_db() self.assertEqual(self.run.starttime, self.event.datetime) self.event.datetime = long_ago_noon self.event.save() self.run.refresh_from_db() self.assertEqual(self.run.starttime, self.event.datetime) class TestEventViews(TestCase): def setUp(self): self.event = models.Event.objects.create( targetamount=1, datetime=today_noon, short='short', name='Short' ) def test_main_index(self): # TODO: make this more than just a smoke test response = self.client.get(reverse('tracker:index_all')) self.assertContains(response, 'All Events') def test_json_with_no_donations(self): response = self.client.get( reverse('tracker:index', args=(self.event.id,)), data={'json': ''} ) self.assertEqual( json.loads(response.content), { 'count': {'bids': 0, 'donors': 0, 'prizes': 0, 'runs': 0}, 'agg': { 'amount': 0.0, 'avg': 0.0, 'count': 0, 'max': 0.0, 'target': 1.0, }, }, ) def test_json_with_only_pending_donations(self): models.Donation.objects.create(event=self.event, amount=5, domainId='123456') response = self.client.get( reverse('tracker:index', args=(self.event.id,)), data={'json': ''} ) self.assertEqual( json.loads(response.content), { 'count': {'bids': 0, 'donors': 0, 'prizes': 0, 'runs': 0}, 'agg': { 'amount': 0.0, 'avg': 0.0, 'count': 0, 'max': 0.0, 'target': 1.0, }, }, ) def test_json_with_cleared_donations(self): models.Donation.objects.create( event=self.event, amount=5, domainId='123456', transactionstate='COMPLETED' ) models.Donation.objects.create( event=self.event, amount=10, domainId='123457', transactionstate='COMPLETED' ) response = self.client.get( reverse('tracker:index', args=(self.event.id,)), data={'json': ''} ) self.assertEqual( json.loads(response.content), { 'count': {'bids': 0, 'donors': 0, 'prizes': 0, 'runs': 0}, 'agg': { 'amount': 15.0, 'avg': 7.5, 'count': 2, 'max': 10.0, 'target': 1.0, }, }, ) class TestEventAdmin(TestCase): def setUp(self): self.super_user = User.objects.create_superuser( 'admin', 'admin@example.com', 'password' ) timezone = pytz.timezone(settings.TIME_ZONE) self.event = models.Event.objects.create( targetamount=5, datetime=today_noon, timezone=timezone, name='test event', short='test', ) self.rand = random.Random(None) self.client.force_login(self.super_user) def test_event_admin(self): response = self.client.get(reverse('admin:tracker_event_changelist')) self.assertEqual(response.status_code, 200) response = self.client.get(reverse('admin:tracker_event_add')) self.assertEqual(response.status_code, 200) response = self.client.get( reverse('admin:tracker_event_change', args=(self.event.id,)) ) self.assertEqual(response.status_code, 200) def test_event_donor_report(self): donor1 = randgen.generate_donor(self.rand, visibility='ANON') donor1.save() donation1 = randgen.generate_donation(self.rand, donor=donor1, event=self.event) donation1.save() donor2 = randgen.generate_donor(self.rand, visibility='ANON') donor2.save() donation2 = randgen.generate_donation(self.rand, donor=donor2, event=self.event) donation2.save() donor3 = randgen.generate_donor(self.rand, visibility='FULL') donor3.save() donation3 = randgen.generate_donation(self.rand, donor=donor3, event=self.event) donation3.save() donation4 = randgen.generate_donation(self.rand, donor=donor3, event=self.event) donation4.transactionstate = 'PENDING' donation4.save() resp = self.client.post( reverse('admin:tracker_event_changelist'), {'action': 'donor_report', '_selected_action': [self.event.id]}, ) self.assertEqual(resp.status_code, 200) lines = [line for line in csv.reader(io.StringIO(resp.content.decode('utf-8')))] self.assertEqual(len(lines), 3) self.assertEqual( lines[1], ['All Anonymous Donations', str(donation1.amount + donation2.amount), '2'], ) self.assertEqual(lines[2], [donor3.visible_name(), str(donation3.amount), '1']) def test_event_run_report(self): runs = randgen.generate_runs(self.rand, self.event, 2, scheduled=True) randgen.generate_runs(self.rand, self.event, 2, scheduled=False) runs[0].runners.add(*randgen.generate_runners(self.rand, 2)) runs[1].runners.add(*randgen.generate_runners(self.rand, 1)) resp = self.client.post( reverse('admin:tracker_event_changelist'), {'action': 'run_report', '_selected_action': [self.event.id]}, ) self.assertEqual(resp.status_code, 200) lines = [line for line in csv.reader(io.StringIO(resp.content.decode('utf-8')))] self.assertEqual(len(lines), 3) def line_for(run): return [ str(run), run.event.short, run.starttime.astimezone(run.event.timezone).isoformat(), run.endtime.astimezone(run.event.timezone).isoformat(), ','.join(str(r) for r in run.runners.all()), ','.join(r.twitter for r in run.runners.all() if r.twitter), ] self.assertEqual(lines[1], line_for(runs[0])) self.assertEqual(lines[2], line_for(runs[1])) def test_event_donation_report(self): randgen.generate_runs(self.rand, self.event, 5, scheduled=True) randgen.generate_donors(self.rand, 5) donations = randgen.generate_donations(self.rand, self.event, 10) randgen.generate_donations( self.rand, self.event, 10, transactionstate='PENDING', domain='PAYPAL' ) resp = self.client.post( reverse('admin:tracker_event_changelist'), {'action': 'donation_report', '_selected_action': [self.event.id]}, ) self.assertEqual(resp.status_code, 200) lines = [line for line in csv.reader(io.StringIO(resp.content.decode('utf-8')))] self.assertEqual(len(lines), 11) def line_for(donation): return [ donation.donor.visible_name(), donation.event.short, str(donation.amount), donation.timereceived.astimezone(donation.event.timezone).isoformat(), ] expected = [ line_for(d) for d in sorted(donations, key=lambda d: d.timereceived, reverse=True) ] for csv_line, expected_line in zip(lines[1:], expected): self.assertEqual(csv_line, expected_line) def test_event_bid_report(self): runs = randgen.generate_runs(self.rand, self.event, 2, scheduled=True) closed_goal = randgen.generate_bid( self.rand, allow_children=False, run=runs[0], state='CLOSED', add_goal=True )[0] closed_goal.save() opened_bid, children = randgen.generate_bid( self.rand, allow_children=True, min_children=5, max_children=5, max_depth=1, run=runs[1], state='OPENED', add_goal=False, ) randgen.chain_insert_bid(opened_bid, children) opened_bid.save() hidden_goal = randgen.generate_bid( self.rand, allow_children=False, event=self.event, state='HIDDEN', add_goal=True, )[0] hidden_goal.save() randgen.generate_donations( self.rand, self.event, 50, bid_targets_list=[closed_goal] + list(opened_bid.get_children()), ) closed_goal.refresh_from_db() opened_bid.refresh_from_db() resp = self.client.post( reverse('admin:tracker_event_changelist'), {'action': 'bid_report', '_selected_action': [self.event.id]}, ) self.assertEqual(resp.status_code, 200) lines = [line for line in csv.reader(io.StringIO(resp.content.decode('utf-8')))] self.assertEqual(len(lines), 8) def line_for(bid): return [ str(bid.id), str(bid), bid.event.short, str(bid.istarget), str(bid.goal) if bid.goal else '', str(bid.total), str(bid.count), ] self.assertEqual(lines[1], line_for(closed_goal)) self.assertEqual(lines[2], line_for(opened_bid)) expected_children = [ line_for(bid) for bid in sorted( opened_bid.get_children(), key=lambda c: c.total, reverse=True ) ] for csv_line, expected_line in zip(lines[3:], expected_children): self.assertEqual(csv_line, expected_line) def test_event_donationbid_report(self): randgen.generate_runs(self.rand, self.event, 2, scheduled=True) closed_goal = randgen.generate_bid( self.rand, allow_children=False, event=self.event, state='CLOSED', add_goal=True, )[0] closed_goal.save() open_goal = randgen.generate_bid( self.rand, allow_children=False, event=self.event, state='OPENED', add_goal=True, )[0] open_goal.save() hidden_goal = randgen.generate_bid( self.rand, allow_children=False, event=self.event, state='HIDDEN', add_goal=True, )[0] hidden_goal.save() randgen.generate_donations( self.rand, self.event, 10, bid_targets_list=[closed_goal], transactionstate='COMPLETED', ) randgen.generate_donations( self.rand, self.event, 10, bid_targets_list=[closed_goal], transactionstate='PENDING', domain='PAYPAL', ) randgen.generate_donations( self.rand, self.event, 10, bid_targets_list=[open_goal], transactionstate='COMPLETED', ) randgen.generate_donations( self.rand, self.event, 10, bid_targets_list=[hidden_goal], transactionstate='COMPLETED', ) resp = self.client.post( reverse('admin:tracker_event_changelist'), {'action': 'donationbid_report', '_selected_action': [self.event.id]}, ) self.assertEqual(resp.status_code, 200) lines = [line for line in csv.reader(io.StringIO(resp.content.decode('utf-8')))] self.assertEqual(len(lines), 21) def line_for(dbid): return [str(dbid.bid_id), str(dbid.amount), str(dbid.donation.timereceived)] expected = [ line_for(dbid) for dbid in models.DonationBid.objects.filter( bid__state__in=['CLOSED', 'OPENED'], donation__transactionstate='COMPLETED', ).order_by('donation__timereceived') ] for csv_line, expected_line in zip(lines[1:], expected): self.assertEqual(csv_line, expected_line) def test_event_prize_report(self): runs = randgen.generate_runs(self.rand, self.event, 2, scheduled=True) prize = randgen.generate_prize( self.rand, event=self.event, start_run=runs[0], end_run=runs[0], sum_donations=False, min_amount=5, max_amount=5, ) prize.save() donors = randgen.generate_donors(self.rand, 3) randgen.generate_donation( self.rand, donor=donors[0], event=self.event, min_time=runs[0].starttime, max_time=runs[0].endtime, min_amount=prize.minimumbid + 5, transactionstate='COMPLETED', ).save() randgen.generate_donation( self.rand, donor=donors[1], event=self.event, min_time=runs[0].starttime, max_time=runs[0].endtime, min_amount=prize.minimumbid, max_amount=prize.minimumbid, transactionstate='COMPLETED', ).save() grandPrize = randgen.generate_prize( self.rand, event=self.event, sum_donations=True, min_amount=50, max_amount=50, ) grandPrize.save() # generate 2 for summation randgen.generate_donation( self.rand, donor=donors[0], event=self.event, min_time=runs[1].starttime, max_time=runs[1].endtime, min_amount=grandPrize.minimumbid // 2, max_amount=grandPrize.minimumbid // 2, transactionstate='COMPLETED', ).save() randgen.generate_donation( self.rand, donor=donors[0], event=self.event, min_time=runs[1].starttime, max_time=runs[1].endtime, min_amount=grandPrize.minimumbid * 3 // 4, max_amount=grandPrize.minimumbid * 3 // 4, transactionstate='COMPLETED', ).save() # also has another donation in randgen.generate_donation( self.rand, donor=donors[1], event=self.event, min_time=runs[1].starttime, max_time=runs[1].endtime, min_amount=grandPrize.minimumbid, max_amount=grandPrize.minimumbid, transactionstate='COMPLETED', ).save() # only has donation for grand prize randgen.generate_donation( self.rand, donor=donors[2], event=self.event, min_time=runs[1].starttime, max_time=runs[1].endtime, min_amount=grandPrize.minimumbid, max_amount=grandPrize.minimumbid, transactionstate='COMPLETED', ).save() resp = self.client.post( reverse('admin:tracker_event_changelist'), {'action': 'prize_report', '_selected_action': [self.event.id]}, ) self.assertEqual(resp.status_code, 200) lines = [line for line in csv.reader(io.StringIO(resp.content.decode('utf-8')))] self.assertEqual(len(lines), 3) self.assertEqual(lines[1], ['test', grandPrize.name, '3', '1', '', '']) self.assertEqual( lines[2], [ 'test', prize.name, '2', '1', str(runs[0].starttime.astimezone(pytz.utc)), str(runs[0].endtime.astimezone(pytz.utc)), ], ) def test_event_email_report(self): randgen.generate_runs(self.rand, self.event, 2, scheduled=True) donors = randgen.generate_donors(self.rand, 4) donors[1].solicitemail = 'OPTIN' donors[1].lastname = '' donors[1].save() donors[2].solicitemail = 'OPTIN' donors[2].firstname = '' donors[2].lastname = '' donors[2].save() donors[3].solicitemail = 'OPTIN' donors[3].save() randgen.generate_donations(self.rand, self.event, 50) resp = self.client.post( reverse('admin:tracker_event_changelist'), {'action': 'email_report', '_selected_action': [self.event.id]}, ) self.assertEqual(resp.status_code, 200) lines = [line for line in csv.reader(io.StringIO(resp.content.decode('utf-8')))] self.assertEqual(len(lines), 4) def line_for(d): if d.firstname: if d.lastname: name = u'%s, %s' % (d.lastname, d.firstname) else: name = d.firstname else: name = '(No Name Supplied)' return [ d.email, name, str(d.visibility == 'ANON'), str(d.donation_total), str(d.addresscountry or ''), ] expected = [ line_for(d) for d in models.DonorCache.objects.filter( event=self.event, donor__solicitemail='OPTIN', ).select_related('donor') ] for csv_line, expected_line in zip(lines[1:], expected): self.assertEqual(csv_line, expected_line) def test_run_admin(self): self.run = models.SpeedRun.objects.create(event=self.event) response = self.client.get(reverse('admin:tracker_speedrun_changelist')) self.assertEqual(response.status_code, 200) response = self.client.get(reverse('admin:tracker_speedrun_add')) self.assertEqual(response.status_code, 200) response = self.client.get( reverse('admin:tracker_speedrun_change', args=(self.run.id,)) ) self.assertEqual(response.status_code, 200) def test_runner_admin(self): self.runner = models.Runner.objects.create() response = self.client.get(reverse('admin:tracker_runner_changelist')) self.assertEqual(response.status_code, 200) response = self.client.get(reverse('admin:tracker_runner_add')) self.assertEqual(response.status_code, 200) response = self.client.get( reverse('admin:tracker_runner_change', args=(self.runner.id,)) ) self.assertEqual(response.status_code, 200) def test_postbackurl_admin(self): self.postbackurl = models.PostbackURL.objects.create(event=self.event) response = self.client.get(reverse('admin:tracker_postbackurl_changelist')) self.assertEqual(response.status_code, 200) response = self.client.get(reverse('admin:tracker_postbackurl_add')) self.assertEqual(response.status_code, 200) response = self.client.get( reverse('admin:tracker_postbackurl_change', args=(self.postbackurl.id,)) ) self.assertEqual(response.status_code, 200)