Merge pull request #3922 from netbox-community/3921-choices-tests

Closes #3921: Add tests for API _choices endpoints
This commit is contained in:
Jeremy Stretch 2020-01-14 16:42:28 -05:00 committed by GitHub
commit b538495a29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 232 additions and 15 deletions

View File

@ -6,7 +6,23 @@ from circuits.choices import *
from circuits.models import Circuit, CircuitTermination, CircuitType, Provider from circuits.models import Circuit, CircuitTermination, CircuitType, Provider
from dcim.models import Site from dcim.models import Site
from extras.models import Graph from extras.models import Graph
from utilities.testing import APITestCase from utilities.testing import APITestCase, choices_to_dict
class ChoicesTest(APITestCase):
def test_choices(self):
url = reverse('circuits-api:field-choice-list')
response = self.client.get(url, **self.header)
self.assertEqual(response.status_code, 200)
# Circuit
self.assertEqual(choices_to_dict(response.data.get('circuit:status')), CircuitStatusChoices.as_dict())
# CircuitTermination
self.assertEqual(choices_to_dict(response.data.get('circuit-termination:term_side')), CircuitTerminationSideChoices.as_dict())
class ProviderTest(APITestCase): class ProviderTest(APITestCase):

View File

@ -52,6 +52,7 @@ class DCIMFieldChoicesViewSet(FieldChoicesViewSet):
(FrontPortTemplate, ['type']), (FrontPortTemplate, ['type']),
(Interface, ['type', 'mode']), (Interface, ['type', 'mode']),
(InterfaceTemplate, ['type']), (InterfaceTemplate, ['type']),
(PowerFeed, ['phase', 'status', 'supply', 'type']),
(PowerOutlet, ['type', 'feed_leg']), (PowerOutlet, ['type', 'feed_leg']),
(PowerOutletTemplate, ['type', 'feed_leg']), (PowerOutletTemplate, ['type', 'feed_leg']),
(PowerPort, ['type', 'connection_status']), (PowerPort, ['type', 'connection_status']),

View File

@ -14,10 +14,86 @@ from dcim.models import (
) )
from ipam.models import IPAddress, VLAN from ipam.models import IPAddress, VLAN
from extras.models import Graph from extras.models import Graph
from utilities.testing import APITestCase from utilities.testing import APITestCase, choices_to_dict
from virtualization.models import Cluster, ClusterType from virtualization.models import Cluster, ClusterType
class ChoicesTest(APITestCase):
def test_choices(self):
url = reverse('dcim-api:field-choice-list')
response = self.client.get(url, **self.header)
self.assertEqual(response.status_code, 200)
# Cable
self.assertEqual(choices_to_dict(response.data.get('cable:length_unit')), CableLengthUnitChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('cable:status')), CableStatusChoices.as_dict())
content_types = ContentType.objects.filter(model__in=CABLE_TERMINATION_TYPES)
cable_termination_choices = {
"{}.{}".format(ct.app_label, ct.model): ct.name for ct in content_types
}
self.assertEqual(choices_to_dict(response.data.get('cable:termination_a_type')), cable_termination_choices)
self.assertEqual(choices_to_dict(response.data.get('cable:termination_b_type')), cable_termination_choices)
self.assertEqual(choices_to_dict(response.data.get('cable:type')), CableTypeChoices.as_dict())
# Console ports
self.assertEqual(choices_to_dict(response.data.get('console-port:type')), ConsolePortTypeChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('console-port:connection_status')), dict(CONNECTION_STATUS_CHOICES))
self.assertEqual(choices_to_dict(response.data.get('console-port-template:type')), ConsolePortTypeChoices.as_dict())
# Console server ports
self.assertEqual(choices_to_dict(response.data.get('console-server-port:type')), ConsolePortTypeChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('console-server-port-template:type')), ConsolePortTypeChoices.as_dict())
# Device
self.assertEqual(choices_to_dict(response.data.get('device:face')), DeviceFaceChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('device:status')), DeviceStatusChoices.as_dict())
# Device type
self.assertEqual(choices_to_dict(response.data.get('device-type:subdevice_role')), SubdeviceRoleChoices.as_dict())
# Front ports
self.assertEqual(choices_to_dict(response.data.get('front-port:type')), PortTypeChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('front-port-template:type')), PortTypeChoices.as_dict())
# Interfaces
self.assertEqual(choices_to_dict(response.data.get('interface:type')), InterfaceTypeChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('interface:mode')), InterfaceModeChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('interface-template:type')), InterfaceTypeChoices.as_dict())
# Power feed
self.assertEqual(choices_to_dict(response.data.get('power-feed:phase')), PowerFeedPhaseChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('power-feed:status')), PowerFeedStatusChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('power-feed:supply')), PowerFeedSupplyChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('power-feed:type')), PowerFeedTypeChoices.as_dict())
# Power outlets
self.assertEqual(choices_to_dict(response.data.get('power-outlet:type')), PowerOutletTypeChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('power-outlet:feed_leg')), PowerOutletFeedLegChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('power-outlet-template:type')), PowerOutletTypeChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('power-outlet-template:feed_leg')), PowerOutletFeedLegChoices.as_dict())
# Power ports
self.assertEqual(choices_to_dict(response.data.get('power-port:type')), PowerPortTypeChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('power-port:connection_status')), dict(CONNECTION_STATUS_CHOICES))
self.assertEqual(choices_to_dict(response.data.get('power-port-template:type')), PowerPortTypeChoices.as_dict())
# Rack
self.assertEqual(choices_to_dict(response.data.get('rack:type')), RackTypeChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('rack:width')), RackWidthChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('rack:status')), RackStatusChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('rack:outer_unit')), RackDimensionUnitChoices.as_dict())
# Rear ports
self.assertEqual(choices_to_dict(response.data.get('rear-port:type')), PortTypeChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('rear-port-template:type')), PortTypeChoices.as_dict())
# Site
self.assertEqual(choices_to_dict(response.data.get('site:status')), SiteStatusChoices.as_dict())
class RegionTest(APITestCase): class RegionTest(APITestCase):
def setUp(self): def setUp(self):

View File

@ -7,10 +7,37 @@ from rest_framework import status
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Platform, Rack, RackGroup, RackRole, Region, Site from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Platform, Rack, RackGroup, RackRole, Region, Site
from extras.api.views import ScriptViewSet from extras.api.views import ScriptViewSet
from extras.choices import *
from extras.constants import GRAPH_MODELS
from extras.models import ConfigContext, Graph, ExportTemplate, Tag from extras.models import ConfigContext, Graph, ExportTemplate, Tag
from extras.scripts import BooleanVar, IntegerVar, Script, StringVar from extras.scripts import BooleanVar, IntegerVar, Script, StringVar
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
from utilities.testing import APITestCase from utilities.testing import APITestCase, choices_to_dict
from utilities.utils import model_names_to_filter_dict
class ChoicesTest(APITestCase):
def test_choices(self):
url = reverse('extras-api:field-choice-list')
response = self.client.get(url, **self.header)
self.assertEqual(response.status_code, 200)
# ExportTemplate
self.assertEqual(choices_to_dict(response.data.get('export-template:template_language')), ExportTemplateLanguageChoices.as_dict())
# Graph
content_types = ContentType.objects.filter(**model_names_to_filter_dict(GRAPH_MODELS))
graph_type_choices = {
"{}.{}".format(ct.app_label, ct.model): ct.name for ct in content_types
}
self.assertEqual(choices_to_dict(response.data.get('graph:type')), graph_type_choices)
self.assertEqual(choices_to_dict(response.data.get('graph:template_language')), ExportTemplateLanguageChoices.as_dict())
# ObjectChange
self.assertEqual(choices_to_dict(response.data.get('object-change:action')), ObjectChangeActionChoices.as_dict())
class GraphTest(APITestCase): class GraphTest(APITestCase):

View File

@ -111,7 +111,7 @@ class VLANStatusChoices(ChoiceSet):
# #
# VLANs # Services
# #
class ServiceProtocolChoices(ChoiceSet): class ServiceProtocolChoices(ChoiceSet):

View File

@ -5,9 +5,37 @@ from netaddr import IPNetwork
from rest_framework import status from rest_framework import status
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
from ipam.choices import ServiceProtocolChoices from ipam.choices import *
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
from utilities.testing import APITestCase from utilities.testing import APITestCase, choices_to_dict
class ChoicesTest(APITestCase):
def test_choices(self):
url = reverse('ipam-api:field-choice-list')
response = self.client.get(url, **self.header)
self.assertEqual(response.status_code, 200)
# Aggregate
# self.assertEqual(choices_to_dict(response.data.get('aggregate:family')), )
# Prefix
# self.assertEqual(choices_to_dict(response.data.get('prefix:family')), )
self.assertEqual(choices_to_dict(response.data.get('prefix:status')), PrefixStatusChoices.as_dict())
# IPAddress
# self.assertEqual(choices_to_dict(response.data.get('ip-address:family')), )
self.assertEqual(choices_to_dict(response.data.get('ip-address:role')), IPAddressRoleChoices.as_dict())
self.assertEqual(choices_to_dict(response.data.get('ip-address:status')), IPAddressStatusChoices.as_dict())
# VLAN
self.assertEqual(choices_to_dict(response.data.get('vlan:status')), VLANStatusChoices.as_dict())
# Service
self.assertEqual(choices_to_dict(response.data.get('service:protocol')), ServiceProtocolChoices.as_dict())
class VRFTest(APITestCase): class VRFTest(APITestCase):

View File

@ -9,6 +9,16 @@ from utilities.testing import APITestCase
from .constants import PRIVATE_KEY, PUBLIC_KEY from .constants import PRIVATE_KEY, PUBLIC_KEY
class ChoicesTest(APITestCase):
def test_choices(self):
url = reverse('secrets-api:field-choice-list')
response = self.client.get(url, **self.header)
self.assertEqual(response.status_code, 200)
class SecretRoleTest(APITestCase): class SecretRoleTest(APITestCase):
def setUp(self): def setUp(self):

View File

@ -5,6 +5,16 @@ from tenancy.models import Tenant, TenantGroup
from utilities.testing import APITestCase from utilities.testing import APITestCase
class ChoicesTest(APITestCase):
def test_choices(self):
url = reverse('tenancy-api:field-choice-list')
response = self.client.get(url, **self.header)
self.assertEqual(response.status_code, 200)
class TenantGroupTest(APITestCase): class TenantGroupTest(APITestCase):
def setUp(self): def setUp(self):

View File

@ -1,3 +1,6 @@
from utilities.forms import unpack_grouped_choices
class ChoiceSetMeta(type): class ChoiceSetMeta(type):
""" """
Metaclass for ChoiceSet Metaclass for ChoiceSet
@ -20,6 +23,11 @@ class ChoiceSet(metaclass=ChoiceSetMeta):
def values(cls): def values(cls):
return [c[0] for c in cls.CHOICES] return [c[0] for c in cls.CHOICES]
@classmethod
def as_dict(cls):
# Unpack grouped choices before casting as a dict
return dict(unpack_grouped_choices(cls.CHOICES))
@classmethod @classmethod
def slug_to_id(cls, slug): def slug_to_id(cls, slug):
""" """

View File

@ -35,3 +35,30 @@ def create_test_user(username='testuser', permissions=list()):
user.user_permissions.add(perm) user.user_permissions.add(perm)
return user return user
def choices_to_dict(choices_list):
"""
Convert a list of field choices to a dictionary suitable for direct comparison with a ChoiceSet. For example:
[
{
"value": "choice-1",
"label": "First Choice"
},
{
"value": "choice-2",
"label": "Second Choice"
}
]
Becomes:
{
"choice-1": "First Choice",
"choice-2": "Second Choice
}
"""
return {
choice['value']: choice['label'] for choice in choices_list
}

View File

@ -30,14 +30,6 @@ class Migration(migrations.Migration):
name='tenant', name='tenant',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='clusters', to='tenancy.Tenant'), field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='clusters', to='tenancy.Tenant'),
), ),
migrations.AlterField(
model_name='virtualmachine',
name='status',
field=models.CharField(default='active', max_length=50),
),
migrations.RunPython(
code=virtualmachine_status_to_slug,
),
migrations.AlterField( migrations.AlterField(
model_name='virtualmachine', model_name='virtualmachine',
name='name', name='name',
@ -47,4 +39,12 @@ class Migration(migrations.Migration):
name='virtualmachine', name='virtualmachine',
unique_together={('cluster', 'tenant', 'name')}, unique_together={('cluster', 'tenant', 'name')},
), ),
migrations.AlterField(
model_name='virtualmachine',
name='status',
field=models.CharField(default='active', max_length=50),
),
migrations.RunPython(
code=virtualmachine_status_to_slug,
),
] ]

View File

@ -5,10 +5,24 @@ from rest_framework import status
from dcim.choices import InterfaceModeChoices, InterfaceTypeChoices from dcim.choices import InterfaceModeChoices, InterfaceTypeChoices
from dcim.models import Interface from dcim.models import Interface
from ipam.models import IPAddress, VLAN from ipam.models import IPAddress, VLAN
from utilities.testing import APITestCase from utilities.testing import APITestCase, choices_to_dict
from virtualization.choices import *
from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine
class ChoicesTest(APITestCase):
def test_choices(self):
url = reverse('virtualization-api:field-choice-list')
response = self.client.get(url, **self.header)
self.assertEqual(response.status_code, 200)
# VirtualMachine
self.assertEqual(choices_to_dict(response.data.get('virtual-machine:status')), VirtualMachineStatusChoices.as_dict())
class ClusterTypeTest(APITestCase): class ClusterTypeTest(APITestCase):
def setUp(self): def setUp(self):