Fixes #19041: Call super().clean() in FrontPortCreateForm (#19051)

* fix(forms): Call super().clean() in clean methods

Adds a call to super().clean() in the clean methods of object creation
forms. This ensures base class validation logic is executed properly
before custom logic is applied.

Fixes #19041

* test(forms): Add tests for front port form validation

Introduces unit tests for validating FrontPortCreateForm behavior.
Tests include scenarios for matching and mismatched name-label pairs
to ensure proper form validation logic.

Fixes #19041

* Omit errant print statement

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
Martin Hauser 2025-04-02 14:29:21 +02:00 committed by GitHub
parent bad820001d
commit f17bbe610e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 54 additions and 1 deletions

View File

@ -153,6 +153,7 @@ class FrontPortTemplateCreateForm(ComponentCreateForm, model_forms.FrontPortTemp
self.fields['rear_port'].choices = choices self.fields['rear_port'].choices = choices
def clean(self): def clean(self):
super().clean()
# Check that the number of FrontPortTemplates to be created matches the selected number of RearPortTemplate # Check that the number of FrontPortTemplates to be created matches the selected number of RearPortTemplate
# positions # positions
@ -302,6 +303,7 @@ class FrontPortCreateForm(ComponentCreateForm, model_forms.FrontPortForm):
self.fields['rear_port'].choices = choices self.fields['rear_port'].choices = choices
def clean(self): def clean(self):
super().clean()
# Check that the number of FrontPorts to be created matches the selected number of RearPort positions # Check that the number of FrontPorts to be created matches the selected number of RearPort positions
frontport_count = len(self.cleaned_data['name']) frontport_count = len(self.cleaned_data['name'])

View File

@ -1,6 +1,12 @@
from django.test import TestCase from django.test import TestCase
from dcim.choices import DeviceFaceChoices, DeviceStatusChoices, InterfaceTypeChoices, InterfaceModeChoices from dcim.choices import (
DeviceFaceChoices,
DeviceStatusChoices,
InterfaceModeChoices,
InterfaceTypeChoices,
PortTypeChoices,
)
from dcim.forms import * from dcim.forms import *
from dcim.models import * from dcim.models import *
from ipam.models import VLAN from ipam.models import VLAN
@ -118,6 +124,51 @@ class DeviceTestCase(TestCase):
self.assertIn('position', form.errors) self.assertIn('position', form.errors)
class FrontPortTestCase(TestCase):
@classmethod
def setUpTestData(cls):
cls.device = create_test_device('Panel Device 1')
cls.rear_ports = (
RearPort(name='RearPort1', device=cls.device, type=PortTypeChoices.TYPE_8P8C),
RearPort(name='RearPort2', device=cls.device, type=PortTypeChoices.TYPE_8P8C),
RearPort(name='RearPort3', device=cls.device, type=PortTypeChoices.TYPE_8P8C),
RearPort(name='RearPort4', device=cls.device, type=PortTypeChoices.TYPE_8P8C),
)
RearPort.objects.bulk_create(cls.rear_ports)
def test_front_port_label_count_valid(self):
"""
Test that generating an equal number of names and labels passes form validation.
"""
front_port_data = {
'device': self.device.pk,
'name': 'FrontPort[1-4]',
'label': 'Port[1-4]',
'type': PortTypeChoices.TYPE_8P8C,
'rear_port': [f'{rear_port.pk}:1' for rear_port in self.rear_ports],
}
form = FrontPortCreateForm(front_port_data)
self.assertTrue(form.is_valid())
def test_front_port_label_count_mismatch(self):
"""
Check that attempting to generate a differing number of names and labels results in a validation error.
"""
bad_front_port_data = {
'device': self.device.pk,
'name': 'FrontPort[1-4]',
'label': 'Port[1-2]',
'type': PortTypeChoices.TYPE_8P8C,
'rear_port': [f'{rear_port.pk}:1' for rear_port in self.rear_ports],
}
form = FrontPortCreateForm(bad_front_port_data)
self.assertFalse(form.is_valid())
self.assertIn('label', form.errors)
class InterfaceTestCase(TestCase): class InterfaceTestCase(TestCase):
@classmethod @classmethod