diff --git a/atst/forms/task_order.py b/atst/forms/task_order.py index f1bf67c9..6714b5ad 100644 --- a/atst/forms/task_order.py +++ b/atst/forms/task_order.py @@ -12,7 +12,7 @@ from wtforms.fields.html5 import DateField, TelField from wtforms.widgets import ListWidget, CheckboxInput from wtforms.validators import Required, Length -from atst.forms.validators import IsNumber, PhoneNumber, RequiredIfNot +from atst.forms.validators import IsNumber, PhoneNumber, RequiredIf from .forms import CacheableForm from .data import ( @@ -117,7 +117,7 @@ class OversightForm(CacheableForm): ) ko_dod_id = StringField( translate("forms.task_order.oversight_dod_id_label"), - validators=[Required(), Length(min=10), IsNumber()], + validators=[RequiredIf("ko_invite"), Length(min=10), IsNumber()], ) am_cor = BooleanField(translate("forms.task_order.oversight_am_cor_label")) @@ -128,11 +128,11 @@ class OversightForm(CacheableForm): cor_email = StringField(translate("forms.task_order.oversight_email_label")) cor_phone_number = TelField( translate("forms.task_order.oversight_phone_label"), - validators=[RequiredIfNot("am_cor"), PhoneNumber()], + validators=[RequiredIf("am_cor", False), PhoneNumber()], ) cor_dod_id = StringField( translate("forms.task_order.oversight_dod_id_label"), - validators=[RequiredIfNot("am_cor"), Length(min=10), IsNumber()], + validators=[RequiredIf("am_cor", False), Length(min=10), IsNumber()], ) so_first_name = StringField( diff --git a/atst/forms/validators.py b/atst/forms/validators.py index d8b59d97..716225e7 100644 --- a/atst/forms/validators.py +++ b/atst/forms/validators.py @@ -80,26 +80,35 @@ def ListItemsUnique(message=translate("forms.validators.list_items_unique_messag return _list_items_unique -def RequiredIfNot(other_field_name, message=translate("forms.validators.is_required")): +def RequiredIf( + other_field_name, checked=True, message=translate("forms.validators.is_required") +): """ A validator which makes a field required only if another field - has a falsy value + has a truthy value Args: other_field_name (str): the name of the field we check before - determining if this field is required; if this other field is falsy, - the field will be required + determining if this field is required + checked (bool): the value of other_field_name that we want to check against; + if checked is True, we require the field if other_field_name's field value + is truthy; if checked is False, we require the field if other_field_name's + field value is falsy message (str): an optional message to display if the field is required but hasNone value """ - def _required_if_not(form, field): + def _required_if(form, field): other_field = form._fields.get(other_field_name) if other_field is None: raise Exception('no field named "%s" in form' % self.other_field_name) - if not bool(other_field.data): + field_required = ( + bool(other_field.data) if checked else not bool(other_field.data) + ) + + if field_required: if field.data is None: raise ValidationError(message) else: raise StopValidation() - return _required_if_not + return _required_if diff --git a/tests/forms/test_validators.py b/tests/forms/test_validators.py index d01ec7a8..267ddbc6 100644 --- a/tests/forms/test_validators.py +++ b/tests/forms/test_validators.py @@ -6,7 +6,7 @@ from atst.forms.validators import ( IsNumber, PhoneNumber, ListItemsUnique, - RequiredIfNot, + RequiredIf, ) @@ -81,29 +81,56 @@ class TestListItemsUnique: validator(dummy_form, dummy_field) -class TestRequiredIfNot: - def test_RequiredIfNot_requires_field_if_arg_is_falsy( +class TestRequiredIf: + def test_RequiredIf_requires_field_if_arg_is_truthy( self, dummy_form_with_field, dummy_field ): - form = dummy_form_with_field("arg", False) - validator = RequiredIfNot("arg") + form = dummy_form_with_field("arg", True) + validator = RequiredIf("arg") dummy_field.data = None with pytest.raises(ValidationError): validator(form, dummy_field) - def test_RequiredIfNot_does_not_require_field_if_arg_is_truthy( + def test_RequiredIf_does_not_require_field_if_arg_is_falsy( self, dummy_form_with_field, dummy_field ): - form = dummy_form_with_field("arg", True) - validator = RequiredIfNot("arg") + form = dummy_form_with_field("arg", False) + validator = RequiredIf("arg") dummy_field.data = None with pytest.raises(StopValidation): validator(form, dummy_field) - def test_RequiredIfNot_arg_is_None_raises_error(self, dummy_form, dummy_field): - validator = RequiredIfNot("arg") + def test_RequiredIf_arg_is_None_raises_error(self, dummy_form, dummy_field): + validator = RequiredIf("arg") + dummy_field.data = "some data" + + with pytest.raises(Exception): + validator(dummy_form, dummy_field) + + def test_not_RequiredIf_requires_field_if_arg_is_falsy( + self, dummy_form_with_field, dummy_field + ): + form = dummy_form_with_field("arg", False) + validator = RequiredIf("arg", False) + dummy_field.data = None + + with pytest.raises(ValidationError): + validator(form, dummy_field) + + def test_not_RequiredIf_does_not_require_field_if_arg_is_truthy( + self, dummy_form_with_field, dummy_field + ): + form = dummy_form_with_field("arg", True) + validator = RequiredIf("arg", False) + dummy_field.data = None + + with pytest.raises(StopValidation): + validator(form, dummy_field) + + def test_not_RequiredIf_arg_is_None_raises_error(self, dummy_form, dummy_field): + validator = RequiredIf("arg", False) dummy_field.data = "some data" with pytest.raises(Exception):