diff --git a/src/servala/core/crd/forms.py b/src/servala/core/crd/forms.py index b022a5e..188ce3e 100644 --- a/src/servala/core/crd/forms.py +++ b/src/servala/core/crd/forms.py @@ -371,11 +371,13 @@ class CustomFormMixin(FormGeneratorMixin): validators = [] if min_val is not None: - validators.append(MinValueValidator(min_val)) - field.widget.attrs["min"] = min_val + with suppress(ValueError): + validators.append(MinValueValidator(int(min_val))) + field.widget.attrs["min"] = min_val if max_val is not None: - validators.append(MaxValueValidator(max_val)) - field.widget.attrs["max"] = max_val + with suppress(ValueError): + validators.append(MaxValueValidator(int(max_val))) + field.widget.attrs["max"] = max_val if validators: field.validators.extend(validators) diff --git a/src/tests/test_form_config.py b/src/tests/test_form_config.py index c93f3fb..25f1bf2 100644 --- a/src/tests/test_form_config.py +++ b/src/tests/test_form_config.py @@ -1055,6 +1055,59 @@ def test_empty_values_dont_override_default_configs(): assert name_field.required is False # Was overridden by explicit False +def test_number_field_validates_min_max_values(): + + class TestModel(models.Model): + name = models.CharField(max_length=100) + port = models.IntegerField() + + class Meta: + app_label = "test" + + form_config = { + "fieldsets": [ + { + "title": "General", + "fields": [ + { + "type": "text", + "label": "Name", + "controlplane_field_mapping": "name", + "required": True, + }, + { + "type": "number", + "label": "Port", + "controlplane_field_mapping": "port", + "required": True, + "min_value": "1", + "max_value": "65535", + }, + ], + } + ] + } + + form_class = generate_custom_form_class(form_config, TestModel) + + # Test value below minimum fails validation + form = form_class(data={"name": "test-service", "port": 0}) + form.fields["context"].required = False + assert not form.is_valid() + assert "port" in form.errors + + # Test value above maximum fails validation + form = form_class(data={"name": "test-service", "port": 65536}) + form.fields["context"].required = False + assert not form.is_valid() + assert "port" in form.errors + + # Test valid value passes validation + form = form_class(data={"name": "test-service", "port": 8080}) + form.fields["context"].required = False + assert form.is_valid(), f"Form should be valid but has errors: {form.errors}" + + def test_number_field_with_addon_text_roundtrip(): class TestModel(models.Model): name = models.CharField(max_length=100)