Skip to content

Commit f047b46

Browse files
authored
fix: accept multiple_objects custom field, add tests (#113)
1 parent 5b13798 commit f047b46

File tree

2 files changed

+124
-4
lines changed

2 files changed

+124
-4
lines changed

netbox_diode_plugin/api/transformer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ def _prepare_custom_fields(object_type: str, custom_fields: dict) -> tuple[dict,
608608
keyname = key
609609
try:
610610
value_type, value = _pop_custom_field_type_and_value(value)
611-
if value_type in ("text", "longText", "decimal", "boolean", "datetime", "selection", "url", "multipleSelection"):
611+
if value_type in ("text", "long_text", "decimal", "boolean", "datetime", "selection", "url", "multiple_selection"):
612612
out[key] = value
613613
elif value_type == "date":
614614
# truncate to YYYY-MM-DD
@@ -629,11 +629,11 @@ def _prepare_custom_fields(object_type: str, custom_fields: dict) -> tuple[dict,
629629
object_type=ref['_object_type'],
630630
uuid=ref['_uuid'],
631631
)
632-
elif value_type == "multipleObjects":
632+
elif value_type == "multiple_objects":
633633
vals = []
634634
for i, item in enumerate(value):
635635
keyname = f"{key}[{i}]"
636-
nested = _prepare_custom_ref(value)
636+
nested = _prepare_custom_ref(item)
637637
ref = nested[0]
638638
refs.add(ref['_uuid'])
639639
nodes += nested

netbox_diode_plugin/tests/test_api_diff_and_apply.py

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from core.models import ObjectType
1616
from dcim.models import Device, Interface, ModuleBay, Site
1717
from extras.models import CustomField
18-
from extras.models.customfields import CustomFieldTypeChoices
18+
from extras.models.customfields import CustomFieldChoiceSet, CustomFieldChoiceSetBaseChoices, CustomFieldTypeChoices
1919
from ipam.models import IPAddress, VLANGroup
2020
from rest_framework import status
2121
from utilities.testing import APITestCase
@@ -98,6 +98,59 @@ def setUp(self):
9898
self.decimal_field.object_types.set([self.object_type])
9999
self.decimal_field.save()
100100

101+
self.long_text_field = CustomField.objects.create(
102+
name='my_long_text',
103+
type=CustomFieldTypeChoices.TYPE_LONGTEXT,
104+
required=False,
105+
unique=False,
106+
)
107+
self.long_text_field.object_types.set([self.object_type])
108+
self.long_text_field.save()
109+
110+
choices = CustomFieldChoiceSet.objects.create(
111+
name='my_choices',
112+
base_choices=CustomFieldChoiceSetBaseChoices.IATA,
113+
)
114+
self.selection_field = CustomField.objects.create(
115+
name='my_selection',
116+
type=CustomFieldTypeChoices.TYPE_SELECT,
117+
required=False,
118+
unique=False,
119+
choice_set=choices,
120+
)
121+
self.selection_field.object_types.set([self.object_type])
122+
self.selection_field.save()
123+
124+
self.multiple_selection_field = CustomField.objects.create(
125+
name='my_multiple_selection',
126+
type=CustomFieldTypeChoices.TYPE_MULTISELECT,
127+
required=False,
128+
unique=False,
129+
choice_set=choices,
130+
)
131+
self.multiple_selection_field.object_types.set([self.object_type])
132+
self.multiple_selection_field.save()
133+
134+
self.object_field = CustomField.objects.create(
135+
name='my_object',
136+
type=CustomFieldTypeChoices.TYPE_OBJECT,
137+
required=False,
138+
unique=False,
139+
related_object_type=self.object_type,
140+
)
141+
self.object_field.object_types.set([self.object_type])
142+
self.object_field.save()
143+
144+
self.multiple_objects_field = CustomField.objects.create(
145+
name='my_multiple_objects',
146+
type=CustomFieldTypeChoices.TYPE_MULTIOBJECT,
147+
required=False,
148+
unique=False,
149+
related_object_type=self.object_type,
150+
)
151+
self.multiple_objects_field.object_types.set([self.object_type])
152+
self.multiple_objects_field.save()
153+
101154
def tearDown(self):
102155
"""Clean up after tests."""
103156
self.introspect_patcher.stop()
@@ -539,6 +592,36 @@ def test_generate_diff_and_apply_create_and_update_site_with_custom_field(self):
539592
"some_json": {
540593
"json": '{"some_key": 9876543210}',
541594
},
595+
"my_long_text": {
596+
"long_text": "This is a long text",
597+
},
598+
"my_selection": {
599+
"selection": "LAX",
600+
},
601+
"my_multiple_selection": {
602+
"multiple_selection": ["JFK", "LAX"],
603+
},
604+
"my_object": {
605+
"object": {
606+
"site": {
607+
"name": "Custom Object Site Ref 1",
608+
}
609+
},
610+
},
611+
"my_multiple_objects": {
612+
"multiple_objects": [
613+
{
614+
"site": {
615+
"name": "Custom Object Site Ref 2",
616+
}
617+
},
618+
{
619+
"site": {
620+
"name": "Custom Object Site Ref 3",
621+
}
622+
},
623+
],
624+
},
542625
},
543626
},
544627
}
@@ -549,6 +632,19 @@ def test_generate_diff_and_apply_create_and_update_site_with_custom_field(self):
549632
self.assertEqual(new_site.custom_field_data[self.uuid_field.name], site_uuid)
550633
self.assertEqual(new_site.custom_field_data[self.json_field.name], {"some_key": 9876543210})
551634
self.assertEqual(new_site.custom_field_data[self.decimal_field.name], 1234.567)
635+
self.assertEqual(new_site.custom_field_data[self.long_text_field.name], "This is a long text")
636+
self.assertEqual(new_site.custom_field_data[self.selection_field.name], "LAX")
637+
self.assertEqual(new_site.custom_field_data[self.multiple_selection_field.name], ["JFK", "LAX"])
638+
639+
siteRef1 = Site.objects.get(name="Custom Object Site Ref 1")
640+
self.assertIsNotNone(siteRef1)
641+
self.assertEqual(new_site.custom_field_data[self.object_field.name], siteRef1.pk)
642+
siteRef2 = Site.objects.get(name="Custom Object Site Ref 2")
643+
self.assertIsNotNone(siteRef2)
644+
self.assertEqual(new_site.custom_field_data[self.multiple_objects_field.name][0], siteRef2.pk)
645+
siteRef3 = Site.objects.get(name="Custom Object Site Ref 3")
646+
self.assertIsNotNone(siteRef3)
647+
self.assertEqual(new_site.custom_field_data[self.multiple_objects_field.name][1], siteRef3.pk)
552648

553649
payload = {
554650
"timestamp": 1,
@@ -596,6 +692,21 @@ def test_generate_diff_and_apply_create_and_update_site_with_custom_field(self):
596692
"mydate": {
597693
"date": "2026-01-02T00:00:00Z",
598694
},
695+
"my_multiple_objects": {
696+
"multiple_objects": [
697+
{
698+
"site": {
699+
"name": "Custom Object Site Ref 2",
700+
}
701+
},
702+
{
703+
"site": {
704+
"name": "Custom Object Site Ref 4",
705+
}
706+
},
707+
],
708+
},
709+
599710
},
600711
},
601712
}
@@ -608,6 +719,15 @@ def test_generate_diff_and_apply_create_and_update_site_with_custom_field(self):
608719
self.assertEqual(new_site.cf[self.datetime_field.name], datetime.datetime(2026, 1, 1, 10, 0, 0, tzinfo=datetime.timezone.utc))
609720
self.assertEqual(new_site.cf[self.date_field.name], datetime.date(2026, 1, 2))
610721

722+
self.assertEqual(len(new_site.custom_field_data[self.multiple_objects_field.name]), 2)
723+
siteRef2 = Site.objects.get(name="Custom Object Site Ref 2")
724+
self.assertIsNotNone(siteRef2)
725+
self.assertEqual(new_site.custom_field_data[self.multiple_objects_field.name][0], siteRef2.pk)
726+
siteRef4 = Site.objects.get(name="Custom Object Site Ref 4")
727+
self.assertIsNotNone(siteRef3)
728+
self.assertEqual(new_site.custom_field_data[self.multiple_objects_field.name][1], siteRef4.pk)
729+
730+
611731
payload = {
612732
"timestamp": 1,
613733
"object_type": "dcim.site",

0 commit comments

Comments
 (0)