Refactor core form tests for better organization and coverage

This commit is contained in:
Christopher C. Wells 2020-01-29 14:04:19 -08:00 committed by Christopher Charbonneau Wells
parent 39b0df534b
commit 1d492e4163
1 changed files with 415 additions and 194 deletions

View File

@ -4,16 +4,17 @@ from django.core.management import call_command
from django.test import TestCase from django.test import TestCase
from django.test import Client as HttpClient from django.test import Client as HttpClient
from django.utils import timezone from django.utils import timezone
from django.utils.formats import get_format
from faker import Factory from faker import Factory
from core import models from core import models
class FormsTestCase(TestCase): class FormsTestCaseBase(TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
super(FormsTestCase, cls).setUpClass() super(FormsTestCaseBase, cls).setUpClass()
fake = Factory.create() fake = Factory.create()
call_command('migrate', verbosity=0) call_command('migrate', verbosity=0)
call_command('fake', verbosity=0) call_command('fake', verbosity=0)
@ -30,241 +31,461 @@ class FormsTestCase(TestCase):
cls.c.login(**cls.credentials) cls.c.login(**cls.credentials)
def test_child_forms(self): @staticmethod
params = { def localdate_string(datetime=None):
'first_name': 'Child', """ Converts an object to a local date string for form input. """
'last_name': 'One', date_format = get_format('DATE_INPUT_FORMATS')[0]
'birth_date': '2000-01-01' return timezone.localdate(datetime).strftime(date_format)
}
entry = models.Child.objects.first() @staticmethod
page = self.c.post('/children/{}/edit/'.format(entry.slug), params) def localtime_string(datetime=None):
self.assertEqual(page.status_code, 302) """ Converts an object to a local time string for form input. """
entry.refresh_from_db() datetime_format = get_format('DATETIME_INPUT_FORMATS')[0]
return timezone.localtime(datetime).strftime(datetime_format)
params = {'confirm_name': 'Incorrect'}
page = self.c.post('/children/{}/delete/'.format(entry.slug), params)
self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', 'confirm_name',
'Name does not match child name.')
params['confirm_name'] = str(entry)
page = self.c.post('/children/{}/delete/'.format(entry.slug), params)
self.assertEqual(page.status_code, 302)
def test_diaperchange_forms(self):
params = {
'child': 1,
'time': '2000-01-01 1:01',
'wet': 1,
'solid': 1,
'color': 'black',
'amount': 0.45
}
entry = models.DiaperChange.objects.first()
page = self.c.post('/changes/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 302)
del params['solid']
del params['wet']
del params['color']
page = self.c.post('/changes/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None,
'Wet and/or solid is required.')
def test_feeding_forms(self):
entry = models.Feeding.objects.first()
params = {
'child': 1,
'start': '2000-01-01 1:01',
'end': '2000-01-01 1:31',
'type': 'formula',
'method': 'bottle',
'amount': 0
}
timer = models.Timer.objects.create(user=self.user)
timer.save()
page = self.c.post('/feedings/add/?timer={}'.format(timer.id), params)
self.assertEqual(page.status_code, 302)
# Change start and end to prevent intersection validation errors.
params['start'] = '2000-01-01 2:01'
params['end'] = '2000-01-01 2:31'
page = self.c.post('/feedings/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 302)
params['method'] = 'left breast'
page = self.c.post('/feedings/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200)
self.assertFormError(
page, 'form', 'method',
'Only "Bottle" method is allowed with "Formula" type.')
def test_sleep_forms(self):
params = {
'child': 1,
'start': '2000-01-01 1:01',
'end': '2000-01-01 3:01',
}
timer = models.Timer.objects.create(user=self.user)
timer.save()
page = self.c.post('/sleep/add/?timer={}'.format(timer.id), params)
self.assertEqual(page.status_code, 302)
# Change start and end to prevent intersection validation errors.
params['start'] = '2000-01-01 4:01'
params['end'] = '2000-01-01 6:01'
entry = models.Sleep.objects.first()
page = self.c.post('/sleep/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 302)
def test_temperature_forms(self):
params = {
'child': 1,
'temperature': '98.6',
'time': '2000-01-01 2:21'
}
entry = models.Temperature.objects.first()
page = self.c.post('/temperature/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 302)
def test_timer_forms(self):
start_time = timezone.localtime()
timer = models.Timer.objects.create(user=self.user, start=start_time)
timer.save()
params = {
'name': 'New',
'start': start_time.strftime('%Y-%m-%d %H:%M:%S')
}
page = self.c.post('/timer/{}/edit/'.format(timer.id), params)
self.assertEqual(page.status_code, 302)
timer.refresh_from_db()
self.assertEqual(timer.name, params['name'])
# Test changing the timer start time.
start_time = timer.start - timezone.timedelta(hours=1)
params['start'] = timezone.localtime(start_time).strftime(
'%Y-%m-%d %H:%M:%S')
page = self.c.post('/timer/{}/edit/'.format(timer.id), params)
self.assertEqual(page.status_code, 302)
timer.refresh_from_db()
self.assertEqual(timer.start, start_time)
# Test changing a stopped timer
timer.end = timer.start + timezone.timedelta(hours=1)
timer.save()
params['name'] = 'New timer name'
page = self.c.post('/timer/{}/edit/'.format(timer.id), params)
self.assertEqual(page.status_code, 302)
def test_tummytime_forms(self):
params = {
'child': 1,
'start': '2000-01-01 1:01',
'end': '2000-01-01 1:11',
'milestone': ''
}
timer = models.Timer.objects.create(user=self.user)
timer.save()
page = self.c.post(
'/tummy-time/add/?timer={}'.format(timer.id), params)
self.assertEqual(page.status_code, 302)
# Change start and end to prevent intersection validation errors.
params['start'] = '2000-01-01 2:01'
params['end'] = '2000-01-01 2:11'
entry = models.TummyTime.objects.first()
page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 302)
def test_weight_forms(self):
params = {
'child': 1,
'weight': '8.5',
'date': '2000-01-01'
}
entry = models.Weight.objects.first()
page = self.c.post('/weight/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 302)
class FormValidationTestCase(FormsTestCaseBase):
def test_validate_date(self): def test_validate_date(self):
future = (timezone.localdate() + timezone.timedelta(days=1)) future = timezone.localtime() + timezone.timedelta(days=1)
params = { params = {
'child': 1, 'child': 1,
'weight': '8.5', 'weight': '8.5',
'date': future.strftime('%Y-%m-%d') 'date': self.localdate_string(future)
} }
entry = models.Weight.objects.first() entry = models.Weight.objects.first()
page = self.c.post('/weight/{}/'.format(entry.id), params) page = self.c.post('/weight/{}/'.format(entry.id), params, follow=True)
self.assertEqual(page.status_code, 200) self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', 'date', self.assertFormError(page, 'form', 'date',
'Date can not be in the future.') 'Date can not be in the future.')
def test_validate_duration(self): def test_validate_duration(self):
child = models.Child.objects.first()
end = timezone.localtime() - timezone.timedelta(minutes=10)
start = end + timezone.timedelta(minutes=5)
params = { params = {
'child': 1, 'child': child.id,
'start': '2001-01-01 1:01', 'start': self.localtime_string(start),
'end': '2000-01-01 1:11', 'end': self.localtime_string(end),
'milestone': '' 'milestone': ''
} }
entry = models.TummyTime.objects.first()
page = self.c.post('/tummy-time/{}/'.format(entry.id), params) page = self.c.post('/tummy-time/add/', params, follow=True)
self.assertEqual(page.status_code, 200) self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None, self.assertFormError(page, 'form', None,
'Start time must come before end time.') 'Start time must come before end time.')
params['start'] = '1999-01-01 1:11' start = end - timezone.timedelta(weeks=53)
page = self.c.post('/tummy-time/{}/'.format(entry.id), params) params['start'] = self.localtime_string(start)
page = self.c.post('/tummy-time/add/', params, follow=True)
self.assertEqual(page.status_code, 200) self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None, 'Duration too long.') self.assertFormError(page, 'form', None, 'Duration too long.')
def test_validate_time(self): def test_validate_time(self):
future = (timezone.localtime() + timezone.timedelta(hours=1)) child = models.Child.objects.first()
future = timezone.localtime() + timezone.timedelta(hours=1)
params = { params = {
'child': 1, 'child': child.id,
'start': timezone.localtime().strftime('%Y-%m-%d %H:%M:%S'), 'start': self.localtime_string(),
'end': future.strftime('%Y-%m-%d %H:%M:%S'), 'end': self.localtime_string(future),
'milestone': '' 'milestone': ''
} }
entry = models.TummyTime.objects.first()
page = self.c.post('/tummy-time/{}/'.format(entry.id), params) page = self.c.post('/tummy-time/add/', params, follow=True)
self.assertEqual(page.status_code, 200) self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', 'end', self.assertFormError(page, 'form', 'end',
'Date/time can not be in the future.') 'Date/time can not be in the future.')
def test_validate_unique_period(self): def test_validate_unique_period(self):
entry = models.TummyTime.objects.first() entry = models.TummyTime.objects.first()
base_time = timezone.localtime() start = entry.start - timezone.timedelta(minutes=2)
new_entry = models.TummyTime.objects.create( end = entry.end + timezone.timedelta(minutes=2)
child=entry.child,
start=base_time - timezone.timedelta(minutes=45),
end=base_time - timezone.timedelta(minutes=15),
)
new_entry.save()
params = { params = {
'child': 1, 'child': entry.child.id,
'start': (base_time - timezone.timedelta(minutes=35)).strftime( 'start': self.localtime_string(start),
'%Y-%m-%d %H:%M'), 'end': self.localtime_string(end),
'end': (base_time - timezone.timedelta(minutes=5)).strftime(
'%Y-%m-%d %H:%M'),
'milestone': '' 'milestone': ''
} }
page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
page = self.c.post('/tummy-time/add/', params, follow=True)
self.assertEqual(page.status_code, 200) self.assertEqual(page.status_code, 200)
self.assertFormError( self.assertFormError(
page, page,
'form', 'form',
None, None,
'Another entry intersects the specified time period.') 'Another entry intersects the specified time period.')
class ChildFormsTestCaseBase(FormsTestCaseBase):
@classmethod
def setUpClass(cls):
super(ChildFormsTestCaseBase, cls).setUpClass()
cls.child = models.Child.objects.first()
def test_add(self):
params = {
'first_name': 'Child',
'last_name': 'One',
'birth_date': timezone.localdate()
}
page = self.c.post('/children/add/', params, follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(page, 'Child entry added')
def test_edit(self):
params = {
'first_name': 'Name',
'last_name': 'Changed',
'birth_date': self.child.birth_date
}
page = self.c.post('/children/{}/edit/'.format(self.child.slug),
params, follow=True)
self.assertEqual(page.status_code, 200)
self.child.refresh_from_db()
self.assertEqual(self.child.last_name, params['last_name'])
self.assertContains(page, 'Child entry updated')
def test_delete(self):
params = {'confirm_name': 'Incorrect'}
page = self.c.post('/children/{}/delete/'.format(self.child.slug),
params, follow=True)
self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', 'confirm_name',
'Name does not match child name.')
params['confirm_name'] = str(self.child)
page = self.c.post('/children/{}/delete/'.format(self.child.slug),
params, follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(page, 'Child entry deleted')
class DiaperChangeFormsTestCaseBase(FormsTestCaseBase):
@classmethod
def setUpClass(cls):
super(DiaperChangeFormsTestCaseBase, cls).setUpClass()
cls.change = models.DiaperChange.objects.first()
def test_add(self):
child = models.Child.objects.first()
params = {
'child': child.id,
'time': self.localtime_string(),
'color': 'black',
'amount': 0.45
}
page = self.c.post('/changes/add/', params)
self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None,
'Wet and/or solid is required.')
params.update({'wet': 1, 'solid': 1, 'color': 'black'})
page = self.c.post('/changes/add/', params, follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(
page,
'Diaper Change entry for {} added'.format(str(child))
)
def test_edit(self):
params = {
'child': self.change.child.id,
'time': self.localtime_string(),
'wet': self.change.wet,
'solid': self.change.solid,
'color': self.change.color,
'amount': 1.23
}
page = self.c.post('/changes/{}/'.format(self.change.id),
params, follow=True)
self.assertEqual(page.status_code, 200)
self.change.refresh_from_db()
self.assertEqual(self.change.amount, params['amount'])
self.assertContains(
page,
'Diaper Change entry for {} updated'.format(str(self.change.child))
)
def test_delete(self):
page = self.c.post('/changes/{}/delete/'.format(self.change.id),
follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(page, 'Diaper Change entry deleted')
class FeedingFormsTestCaseBase(FormsTestCaseBase):
@classmethod
def setUpClass(cls):
super(FeedingFormsTestCaseBase, cls).setUpClass()
cls.feeding = models.Feeding.objects.first()
def test_add(self):
child = models.Child.objects.first()
end = timezone.localtime()
start = end - timezone.timedelta(minutes=30)
params = {
'child': child.id,
'start': self.localtime_string(start),
'end': self.localtime_string(end),
'type': 'formula',
'method': 'left breast',
'amount': 0
}
page = self.c.post('/feedings/add/', params)
self.assertEqual(page.status_code, 200)
self.assertFormError(
page, 'form', 'method',
'Only "Bottle" method is allowed with "Formula" type.')
params.update({'method': 'bottle'})
page = self.c.post('/feedings/add/', params, follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(
page,
'Feeding entry for {} added'.format(str(child))
)
def test_edit(self):
end = timezone.localtime()
start = end - timezone.timedelta(minutes=30)
params = {
'child': self.feeding.child.id,
'start': self.localtime_string(start),
'end': self.localtime_string(end),
'type': self.feeding.type,
'method': self.feeding.method,
'amount': 100
}
page = self.c.post('/feedings/{}/'.format(self.feeding.id),
params, follow=True)
self.assertEqual(page.status_code, 200)
self.feeding.refresh_from_db()
self.assertEqual(self.feeding.amount, params['amount'])
self.assertContains(
page,
'Feeding entry for {} updated'.format(str(self.feeding.child))
)
def test_delete(self):
page = self.c.post('/feedings/{}/delete/'.format(self.feeding.id),
follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(page, 'Feeding entry deleted')
class SleepFormsTestCaseBase(FormsTestCaseBase):
@classmethod
def setUpClass(cls):
super(SleepFormsTestCaseBase, cls).setUpClass()
cls.sleep = models.Sleep.objects.first()
def test_add(self):
child = models.Child.objects.first()
end = timezone.localtime()
start = end - timezone.timedelta(minutes=2)
params = {
'child': child.id,
'start': self.localtime_string(start),
'end': self.localtime_string(end),
}
page = self.c.post('/sleep/add/', params, follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(
page,
'Sleep entry for {} added'.format(str(child))
)
def test_edit(self):
end = timezone.localtime()
start = end - timezone.timedelta(minutes=2)
params = {
'child': self.sleep.child.id,
'start': self.localtime_string(start),
'end': self.localtime_string(end),
}
page = self.c.post('/sleep/{}/'.format(self.sleep.id),
params, follow=True)
self.assertEqual(page.status_code, 200)
self.sleep.refresh_from_db()
self.assertEqual(
self.localtime_string(self.sleep.end),
params['end']
)
self.assertContains(
page,
'Sleep entry for {} updated'.format(str(self.sleep.child))
)
def test_delete(self):
page = self.c.post('/sleep/{}/delete/'.format(self.sleep.id),
follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(page, 'Sleep entry deleted')
class TemperatureFormsTestCaseBase(FormsTestCaseBase):
@classmethod
def setUpClass(cls):
super(TemperatureFormsTestCaseBase, cls).setUpClass()
cls.temp = models.Temperature.objects.first()
def test_add(self):
child = models.Child.objects.first()
params = {
'child': child.id,
'temperature': '98.6',
'time': self.localtime_string()
}
page = self.c.post('/temperature/add/', params, follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(
page,
'Temperature entry for {} added'.format(str(child))
)
def test_edit(self):
params = {
'child': self.temp.child.id,
'temperature': self.temp.temperature + 2,
'time': self.localtime_string()
}
page = self.c.post('/temperature/{}/'.format(self.temp.id),
params, follow=True)
self.assertEqual(page.status_code, 200)
self.temp.refresh_from_db()
self.assertEqual(self.temp.temperature, params['temperature'])
self.assertContains(
page,
'Temperature entry for {} updated'.format(str(self.temp.child))
)
def test_delete(self):
page = self.c.post('/temperature/{}/delete/'.format(self.temp.id),
follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(page, 'Temperature entry deleted')
class TummyTimeFormsTestCaseBase(FormsTestCaseBase):
@classmethod
def setUpClass(cls):
super(TummyTimeFormsTestCaseBase, cls).setUpClass()
cls.tt = models.TummyTime.objects.first()
def test_add(self):
child = models.Child.objects.first()
end = timezone.localtime()
start = end - timezone.timedelta(minutes=2)
params = {
'child': child.id,
'start': self.localtime_string(start),
'end': self.localtime_string(end),
'milestone': ''
}
page = self.c.post('/tummy-time/add/', params, follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(
page,
'Tummy Time entry for {} added'.format(str(child))
)
def test_edit(self):
end = timezone.localtime()
start = end - timezone.timedelta(minutes=1, seconds=32)
params = {
'child': self.tt.child.id,
'start': self.localtime_string(start),
'end': self.localtime_string(end),
'milestone': 'Moved head!'
}
page = self.c.post('/tummy-time/{}/'.format(self.tt.id),
params, follow=True)
self.assertEqual(page.status_code, 200)
self.tt.refresh_from_db()
self.assertEqual(self.tt.milestone, params['milestone'])
self.assertContains(
page,
'Tummy Time entry for {} updated'.format(str(self.tt.child))
)
def test_delete(self):
page = self.c.post('/tummy-time/{}/delete/'.format(self.tt.id),
follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(page, 'Tummy Time entry deleted')
class TimerFormsTestCaseBase(FormsTestCaseBase):
def test_add(self):
child = models.Child.objects.first()
params = {
'child': child.id,
'name': 'Test Timer',
'start': self.localtime_string()
}
page = self.c.post('/timer/add/', params, follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(page, params['name'])
self.assertContains(page, params['child'])
def test_edit(self):
timer = models.Timer.objects.create(user=self.user)
start_time = timer.start - timezone.timedelta(hours=1)
params = {
'name': 'New Timer Name',
'start': self.localtime_string(start_time)
}
page = self.c.post('/timer/{}/edit/'.format(timer.id), params,
follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(page, params['name'])
timer.refresh_from_db()
self.assertEqual(self.localtime_string(timer.start), params['start'])
class WeightFormsTest(FormsTestCaseBase):
@classmethod
def setUpClass(cls):
super(WeightFormsTest, cls).setUpClass()
cls.weight = models.Weight.objects.first()
def test_add(self):
child = models.Child.objects.first()
params = {
'child': child.id,
'weight': 8.5,
'date': self.localdate_string()
}
page = self.c.post('/weight/add/', params, follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(
page,
'Weight entry for {} added'.format(str(child))
)
def test_edit(self):
params = {
'child': self.weight.child.id,
'weight': self.weight.weight + 1,
'date': self.localdate_string()
}
page = self.c.post('/weight/{}/'.format(self.weight.id),
params, follow=True)
self.assertEqual(page.status_code, 200)
self.weight.refresh_from_db()
self.assertEqual(self.weight.weight, params['weight'])
self.assertContains(
page,
'Weight entry for {} updated'.format(str(self.weight.child))
)
def test_delete(self):
page = self.c.post('/weight/{}/delete/'.format(self.weight.id),
follow=True)
self.assertEqual(page.status_code, 200)
self.assertContains(page, 'Weight entry deleted')