from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.test import TestCase from django.utils import timezone import eav from eav.models import Attribute, EnumGroup, EnumValue, Value from test_project.models import Patient class DataValidation(TestCase): def setUp(self): eav.register(Patient) Attribute.objects.create(name="Age", datatype=Attribute.TYPE_INT) Attribute.objects.create(name="DoB", datatype=Attribute.TYPE_DATE) Attribute.objects.create(name="Height", datatype=Attribute.TYPE_FLOAT) Attribute.objects.create(name="City", datatype=Attribute.TYPE_TEXT) Attribute.objects.create(name="Pregnant", datatype=Attribute.TYPE_BOOLEAN) Attribute.objects.create(name="User", datatype=Attribute.TYPE_OBJECT) Attribute.objects.create(name="Extra", datatype=Attribute.TYPE_JSON) Attribute.objects.create(name="Multi", datatype=Attribute.TYPE_CSV) def tearDown(self): eav.unregister(Patient) def test_required_field(self): p = Patient(name="Bob") p.eav.age = 5 p.save() Attribute.objects.create( name="Weight", datatype=Attribute.TYPE_INT, required=True, ) p.eav.age = 6 self.assertRaises(ValidationError, p.save) p = Patient.objects.get(name="Bob") self.assertEqual(p.eav.age, 5) p.eav.weight = 23 p.save() p = Patient.objects.get(name="Bob") self.assertEqual(p.eav.weight, 23) def test_create_required_field(self): Attribute.objects.create( name="Weight", datatype=Attribute.TYPE_INT, required=True, ) self.assertRaises( ValidationError, Patient.objects.create, name="Joe", eav__age=5, ) self.assertEqual(Patient.objects.count(), 0) self.assertEqual(Value.objects.count(), 0) Patient.objects.create(name="Joe", eav__weight=2, eav__age=5) self.assertEqual(Patient.objects.count(), 1) self.assertEqual(Value.objects.count(), 2) def test_validation_error_create(self): self.assertRaises( ValidationError, Patient.objects.create, name="Joe", eav__age="df", ) self.assertEqual(Patient.objects.count(), 0) self.assertEqual(Value.objects.count(), 0) def test_changing_datatypes(self): a = Attribute.objects.create(name="Color", datatype=Attribute.TYPE_INT) a.datatype = Attribute.TYPE_TEXT a.save() Patient.objects.create(name="Bob", eav__color="brown") a.datatype = Attribute.TYPE_INT self.assertRaises(ValidationError, a.save) def test_int_validation(self): p = Patient.objects.create(name="Joe") p.eav.age = "bad" self.assertRaises(ValidationError, p.save) p.eav.age = 15 p.save() self.assertEqual(Patient.objects.get(pk=p.pk).eav.age, 15) def test_date_validation(self): p = Patient.objects.create(name="Joe") p.eav.dob = "12" self.assertRaises(ValidationError, lambda: p.save()) p.eav.dob = 15 self.assertRaises(ValidationError, lambda: p.save()) now = timezone.now() p.eav.dob = now p.save() self.assertEqual(Patient.objects.get(pk=p.pk).eav.dob, now) today = timezone.now().date() p.eav.dob = today p.save() self.assertEqual(Patient.objects.get(pk=p.pk).eav.dob.date(), today) def test_float_validation(self): p = Patient.objects.create(name="Joe") p.eav.height = "bad" self.assertRaises(ValidationError, p.save) p.eav.height = 15 p.save() self.assertEqual(Patient.objects.get(pk=p.pk).eav.height, 15) p.eav.height = "2.3" p.save() self.assertEqual(Patient.objects.get(pk=p.pk).eav.height, 2.3) def test_text_validation(self): p = Patient.objects.create(name="Joe") p.eav.city = 5 self.assertRaises(ValidationError, p.save) p.eav.city = "El Dorado" p.save() self.assertEqual(Patient.objects.get(pk=p.pk).eav.city, "El Dorado") def test_bool_validation(self): p = Patient.objects.create(name="Joe") p.eav.pregnant = 5 self.assertRaises(ValidationError, p.save) p.eav.pregnant = True p.save() self.assertEqual(Patient.objects.get(pk=p.pk).eav.pregnant, True) def test_object_validation(self): p = Patient.objects.create(name="Joe") p.eav.user = 5 self.assertRaises(ValidationError, p.save) p.eav.user = object self.assertRaises(ValidationError, p.save) p.eav.user = User(username="joe") self.assertRaises(ValidationError, p.save) u = User.objects.create(username="joe") p.eav.user = u p.save() self.assertEqual(Patient.objects.get(pk=p.pk).eav.user, u) def test_enum_validation(self): yes = EnumValue.objects.create(value="yes") no = EnumValue.objects.create(value="no") unkown = EnumValue.objects.create(value="unkown") green = EnumValue.objects.create(value="green") ynu = EnumGroup.objects.create(name="Yes / No / Unknown") ynu.values.add(yes) ynu.values.add(no) ynu.values.add(unkown) Attribute.objects.create( name="Fever", datatype=Attribute.TYPE_ENUM, enum_group=ynu, ) p = Patient.objects.create(name="Joe") p.eav.fever = 5 self.assertRaises(ValidationError, p.save) p.eav.fever = object self.assertRaises(ValidationError, p.save) p.eav.fever = green self.assertRaises(ValidationError, p.save) p.eav.fever = EnumValue(value="yes") self.assertRaises(ValidationError, p.save) p.eav.fever = no p.save() self.assertEqual(Patient.objects.get(pk=p.pk).eav.fever, no) def test_enum_datatype_without_enum_group(self): a = Attribute(name="Age Bracket", datatype=Attribute.TYPE_ENUM) self.assertRaises(ValidationError, a.save) yes = EnumValue.objects.create(value="yes") no = EnumValue.objects.create(value="no") unkown = EnumValue.objects.create(value="unkown") ynu = EnumGroup.objects.create(name="Yes / No / Unknown") ynu.values.add(yes) ynu.values.add(no) ynu.values.add(unkown) a = Attribute(name="Age Bracket", datatype=Attribute.TYPE_ENUM, enum_group=ynu) a.save() def test_enum_group_on_other_datatype(self): yes = EnumValue.objects.create(value="yes") no = EnumValue.objects.create(value="no") unkown = EnumValue.objects.create(value="unkown") ynu = EnumGroup.objects.create(name="Yes / No / Unknown") ynu.values.add(yes) ynu.values.add(no) ynu.values.add(unkown) a = Attribute(name="color", datatype=Attribute.TYPE_TEXT, enum_group=ynu) self.assertRaises(ValidationError, a.save) def test_json_validation(self): p = Patient.objects.create(name="Joe") p.eav.extra = 5 self.assertRaises(ValidationError, p.save) p.eav.extra = {"eyes": "blue", "hair": "brown"} p.save() self.assertEqual(Patient.objects.get(pk=p.pk).eav.extra.get("eyes", ""), "blue") def test_csv_validation(self): yes = EnumValue.objects.create(value="yes") p = Patient.objects.create(name="Mike") p.eav.multi = yes self.assertRaises(ValidationError, p.save) p.eav.multi = "one;two;three" p.save() self.assertEqual( Patient.objects.get(pk=p.pk).eav.multi, ["one", "two", "three"], )