diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index 50cd022b5..4bab22823 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -3,6 +3,7 @@ from django.core.exceptions import ObjectDoesNotExist from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import extend_schema_field from rest_framework import serializers +from rest_framework.fields import ListField from core.api.nested_serializers import NestedDataSourceSerializer, NestedDataFileSerializer, NestedJobSerializer from core.api.serializers import JobSerializer @@ -171,6 +172,7 @@ class CustomFieldChoiceSetSerializer(ValidatedModelSerializer): choices=CustomFieldChoiceSetBaseChoices, required=False ) + extra_choices = serializers.ListField(child=serializers.ListField(min_length=2)) class Meta: model = CustomFieldChoiceSet @@ -383,8 +385,7 @@ class JournalEntrySerializer(NetBoxModelSerializer): @extend_schema_field(serializers.JSONField(allow_null=True)) def get_assigned_object(self, instance): - serializer = get_serializer_for_model(instance.assigned_object_type.model_class(), - prefix=NESTED_SERIALIZER_PREFIX) + serializer = get_serializer_for_model(instance.assigned_object_type.model_class(), prefix=NESTED_SERIALIZER_PREFIX) context = {'request': self.context['request']} return serializer(instance.assigned_object, context=context).data diff --git a/netbox/extras/tests/test_api.py b/netbox/extras/tests/test_api.py index fd9f5bafa..d3c899351 100644 --- a/netbox/extras/tests/test_api.py +++ b/netbox/extras/tests/test_api.py @@ -4,7 +4,7 @@ from django.contrib.auth import get_user_model from django.contrib.contenttypes.models import ContentType from django.urls import reverse from django.utils.timezone import make_aware -from rest_framework import status +from rest_framework import status, test from core.choices import ManagedFileRootPathChoices from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Rack, Location, RackRole, Site @@ -12,14 +12,17 @@ from extras.choices import * from extras.models import * from extras.reports import Report from extras.scripts import BooleanVar, IntegerVar, Script, StringVar +from users.models import Token from utilities.testing import APITestCase, APIViewTestCases + User = get_user_model() class AppTest(APITestCase): def test_root(self): + url = reverse('extras-api:api-root') response = self.client.get('{}?format=api'.format(url), **self.header) @@ -50,6 +53,7 @@ class WebhookTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): + webhooks = ( Webhook( name='Webhook 1', @@ -502,6 +506,7 @@ class TagTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): + tags = ( Tag(name='Tag 1', slug='tag-1'), Tag(name='Tag 2', slug='tag-2'), @@ -628,6 +633,7 @@ class ConfigContextTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): + config_contexts = ( ConfigContext(name='Config Context 1', weight=100, data={'foo': 123}), ConfigContext(name='Config Context 2', weight=200, data={'bar': 456}), @@ -726,6 +732,7 @@ class ConfigTemplateTest(APIViewTestCases.APIViewTestCase): class ReportTest(APITestCase): + class TestReport(Report): def test_foo(self): @@ -756,7 +763,9 @@ class ReportTest(APITestCase): class ScriptTest(APITestCase): + class TestScript(Script): + class Meta: name = "Test script" @@ -765,6 +774,7 @@ class ScriptTest(APITestCase): var3 = BooleanVar() def run(self, data, commit=True): + self.log_info(data['var1']) self.log_success(data['var2']) self.log_failure(data['var3']) @@ -789,6 +799,7 @@ class ScriptTest(APITestCase): ScriptViewSet._get_script = self.get_test_script def test_get_script(self): + url = reverse('extras-api:script-detail', kwargs={'pk': None}) response = self.client.get(url, **self.header) @@ -886,3 +897,56 @@ class ContentTypeTest(APITestCase): url = reverse('extras-api:contenttype-detail', kwargs={'pk': contenttype.pk}) self.assertHttpStatus(self.client.get(url, **self.header), status.HTTP_200_OK) + + +class CustomFieldChoiceSetsEndpointTest(test.APITestCase): + + def setUp(self): + self.super_user = User.objects.create_user(username='testuser', is_staff=True, is_superuser=True) + self.token = Token.objects.create(user=self.super_user) + self.header = {'HTTP_AUTHORIZATION': f'Token {self.token.key}'} + self.url = '/api/extras/custom-field-choice-sets/' + + def test_extra_choices_only_one_choice_element_return_400(self): + payload = { + "name": "test", + "extra_choices": [["choice1"]] + } + + response = self.client.post(self.url, payload, format='json', **self.header) + + self.assertEqual(response.status_code, 400) + + def test_extra_choices_two_wrong_choice_elements_return_400(self): + payload = { + "name": "test", + "extra_choices": [["choice1"], ["choice2"]] + } + + response = self.client.post(self.url, payload, format='json', **self.header) + + self.assertEqual(response.status_code, 400) + + def test_extra_choices_one_is_wrong_other_correct_choice_elements_return_400(self): + payload = { + "name": "test", + "extra_choices": [["1A", "choice1"], ["choice2"]] + } + + response = self.client.post(self.url, payload, format='json', **self.header) + + self.assertEqual(response.status_code, 400) + + def test_extra_choices_correct_choices_return_201(self): + payload = { + 'name': 'Choice Set', + 'extra_choices': [ + ['4A', 'Choice 1'], + ['4B', 'Choice 2'], + ['4C', 'Choice 3'], + ], + } + + response = self.client.post(self.url, payload, format='json', **self.header) + + self.assertEqual(response.status_code, 201) diff --git a/netbox/extras/tests/test_custom_field_choice_sets_endpoint.py b/netbox/extras/tests/test_custom_field_choice_sets_endpoint.py deleted file mode 100644 index 5c9cb53b6..000000000 --- a/netbox/extras/tests/test_custom_field_choice_sets_endpoint.py +++ /dev/null @@ -1,59 +0,0 @@ -from django.contrib.auth import get_user_model -from rest_framework.test import APITestCase - -from users.models import Token - -User = get_user_model() - - -class CustomFieldChoiceSetsEndpointTest(APITestCase): - - def setUp(self): - self.super_user = User.objects.create_user(username='testuser', is_staff=True, is_superuser=True) - self.token = Token.objects.create(user=self.super_user) - self.header = {'HTTP_AUTHORIZATION': f'Token {self.token.key}'} - self.url = '/api/extras/custom-field-choice-sets/' - - def test_extra_choices_only_one_choice_element_return_400(self): - payload = { - "name": "test", - "extra_choices": [["choice1"]] - } - - response = self.client.post(self.url, payload, format='json', **self.header) - - self.assertEqual(response.status_code, 400) - - def test_extra_choices_two_wrong_choice_elements_return_400(self): - payload = { - "name": "test", - "extra_choices": [["choice1"], ["choice2"]] - } - - response = self.client.post(self.url, payload, format='json', **self.header) - - self.assertEqual(response.status_code, 400) - - def test_extra_choices_one_is_wrong_other_correct_choice_elements_return_400(self): - payload = { - "name": "test", - "extra_choices": [["1A", "choice1"], ["choice2"]] - } - - response = self.client.post(self.url, payload, format='json', **self.header) - - self.assertEqual(response.status_code, 400) - - def test_extra_choices_correct_choices_return_201(self): - payload = { - 'name': 'Choice Set', - 'extra_choices': [ - ['4A', 'Choice 1'], - ['4B', 'Choice 2'], - ['4C', 'Choice 3'], - ], - } - - response = self.client.post(self.url, payload, format='json', **self.header) - - self.assertEqual(response.status_code, 201)