mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
5509 Add Test cases for Custom Fields (#12312)
* 5509 add content type data to model tests create and update * 5509 update use cf form data * 5509 update tests to use CustomFieldTypeChoices * 5509 update tests to check custom fields * Simplify custom fields used for testing * Move custom field data functions to testing.utils * Move validate_custom_field_data() into assertInstanceEqual() --------- Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
@ -10,10 +10,11 @@ from django.test import Client, TestCase as _TestCase
|
|||||||
from netaddr import IPNetwork
|
from netaddr import IPNetwork
|
||||||
from taggit.managers import TaggableManager
|
from taggit.managers import TaggableManager
|
||||||
|
|
||||||
|
from netbox.models.features import CustomFieldsMixin
|
||||||
from users.models import ObjectPermission
|
from users.models import ObjectPermission
|
||||||
from utilities.permissions import resolve_permission_ct
|
from utilities.permissions import resolve_permission_ct
|
||||||
from utilities.utils import content_type_identifier
|
from utilities.utils import content_type_identifier
|
||||||
from .utils import extract_form_failures
|
from .utils import DUMMY_CF_DATA, extract_form_failures
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'ModelTestCase',
|
'ModelTestCase',
|
||||||
@ -166,8 +167,12 @@ class ModelTestCase(TestCase):
|
|||||||
model_dict = self.model_to_dict(instance, fields=fields, api=api)
|
model_dict = self.model_to_dict(instance, fields=fields, api=api)
|
||||||
|
|
||||||
# Omit any dictionary keys which are not instance attributes or have been excluded
|
# Omit any dictionary keys which are not instance attributes or have been excluded
|
||||||
relevant_data = {
|
model_data = {
|
||||||
k: v for k, v in data.items() if hasattr(instance, k) and k not in exclude
|
k: v for k, v in data.items() if hasattr(instance, k) and k not in exclude
|
||||||
}
|
}
|
||||||
|
|
||||||
self.assertDictEqual(model_dict, relevant_data)
|
self.assertDictEqual(model_dict, model_data)
|
||||||
|
|
||||||
|
# Validate any custom field data, if present
|
||||||
|
if getattr(instance, 'custom_field_data', None):
|
||||||
|
self.assertDictEqual(instance.custom_field_data, DUMMY_CF_DATA)
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
|
|
||||||
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
|
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
|
||||||
from extras.models import Tag
|
from extras.choices import CustomFieldTypeChoices
|
||||||
|
from extras.models import CustomField, Tag
|
||||||
from virtualization.models import Cluster, ClusterType, VirtualMachine
|
from virtualization.models import Cluster, ClusterType, VirtualMachine
|
||||||
|
|
||||||
|
|
||||||
@ -102,3 +105,42 @@ def disable_warnings(logger_name):
|
|||||||
logger.setLevel(logging.ERROR)
|
logger.setLevel(logging.ERROR)
|
||||||
yield
|
yield
|
||||||
logger.setLevel(current_level)
|
logger.setLevel(current_level)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Custom field testing
|
||||||
|
#
|
||||||
|
|
||||||
|
DUMMY_CF_DATA = {
|
||||||
|
'text_field': 'foo123',
|
||||||
|
'integer_field': 456,
|
||||||
|
'decimal_field': 456.12,
|
||||||
|
'boolean_field': True,
|
||||||
|
'json_field': {'abc': 123},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def add_custom_field_data(form_data, model):
|
||||||
|
"""
|
||||||
|
Create some custom fields for the model and add a value for each to the form data.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
form_data: The dictionary of form data to be updated
|
||||||
|
model: The model of the object the form seeks to create or modify
|
||||||
|
"""
|
||||||
|
content_type = ContentType.objects.get_for_model(model)
|
||||||
|
custom_fields = (
|
||||||
|
CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='text_field', default='foo'),
|
||||||
|
CustomField(type=CustomFieldTypeChoices.TYPE_INTEGER, name='integer_field', default=123),
|
||||||
|
CustomField(type=CustomFieldTypeChoices.TYPE_DECIMAL, name='decimal_field', default=123.45),
|
||||||
|
CustomField(type=CustomFieldTypeChoices.TYPE_BOOLEAN, name='boolean_field', default=False),
|
||||||
|
CustomField(type=CustomFieldTypeChoices.TYPE_JSON, name='json_field', default='{"x": "y"}'),
|
||||||
|
)
|
||||||
|
CustomField.objects.bulk_create(custom_fields)
|
||||||
|
for cf in custom_fields:
|
||||||
|
cf.content_types.set([content_type])
|
||||||
|
|
||||||
|
form_data.update({
|
||||||
|
f'cf_{k}': v if type(v) is str else json.dumps(v)
|
||||||
|
for k, v in DUMMY_CF_DATA.items()
|
||||||
|
})
|
||||||
|
@ -10,11 +10,11 @@ from django.utils.translation import gettext as _
|
|||||||
|
|
||||||
from extras.choices import ObjectChangeActionChoices
|
from extras.choices import ObjectChangeActionChoices
|
||||||
from extras.models import ObjectChange
|
from extras.models import ObjectChange
|
||||||
from netbox.models.features import ChangeLoggingMixin
|
from netbox.models.features import ChangeLoggingMixin, CustomFieldsMixin
|
||||||
from users.models import ObjectPermission
|
from users.models import ObjectPermission
|
||||||
from utilities.choices import CSVDelimiterChoices, ImportFormatChoices
|
from utilities.choices import CSVDelimiterChoices, ImportFormatChoices
|
||||||
from .base import ModelTestCase
|
from .base import ModelTestCase
|
||||||
from .utils import disable_warnings, post_data
|
from .utils import add_custom_field_data, disable_warnings, post_data
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'ModelViewTestCase',
|
'ModelViewTestCase',
|
||||||
@ -26,7 +26,6 @@ __all__ = (
|
|||||||
# UI Tests
|
# UI Tests
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
class ModelViewTestCase(ModelTestCase):
|
class ModelViewTestCase(ModelTestCase):
|
||||||
"""
|
"""
|
||||||
Base TestCase for model views. Subclass to test individual views.
|
Base TestCase for model views. Subclass to test individual views.
|
||||||
@ -166,6 +165,10 @@ class ViewTestCases:
|
|||||||
# Try GET with model-level permission
|
# Try GET with model-level permission
|
||||||
self.assertHttpStatus(self.client.get(self._get_url('add')), 200)
|
self.assertHttpStatus(self.client.get(self._get_url('add')), 200)
|
||||||
|
|
||||||
|
# Add custom field data if the model supports it
|
||||||
|
if issubclass(self.model, CustomFieldsMixin):
|
||||||
|
add_custom_field_data(self.form_data, self.model)
|
||||||
|
|
||||||
# Try POST with model-level permission
|
# Try POST with model-level permission
|
||||||
initial_count = self._get_queryset().count()
|
initial_count = self._get_queryset().count()
|
||||||
request = {
|
request = {
|
||||||
@ -265,6 +268,10 @@ class ViewTestCases:
|
|||||||
# Try GET with model-level permission
|
# Try GET with model-level permission
|
||||||
self.assertHttpStatus(self.client.get(self._get_url('edit', instance)), 200)
|
self.assertHttpStatus(self.client.get(self._get_url('edit', instance)), 200)
|
||||||
|
|
||||||
|
# Add custom field data if the model supports it
|
||||||
|
if issubclass(self.model, CustomFieldsMixin):
|
||||||
|
add_custom_field_data(self.form_data, self.model)
|
||||||
|
|
||||||
# Try POST with model-level permission
|
# Try POST with model-level permission
|
||||||
request = {
|
request = {
|
||||||
'path': self._get_url('edit', instance),
|
'path': self._get_url('edit', instance),
|
||||||
|
Reference in New Issue
Block a user