diff --git a/netbox/circuits/tests/test_api.py b/netbox/circuits/tests/test_api.py index b5f8758e7..71db7234d 100644 --- a/netbox/circuits/tests/test_api.py +++ b/netbox/circuits/tests/test_api.py @@ -1,443 +1,188 @@ from django.contrib.contenttypes.models import ContentType from django.urls import reverse -from rest_framework import status from circuits.choices import * from circuits.models import Circuit, CircuitTermination, CircuitType, Provider from dcim.models import Site from extras.models import Graph -from utilities.testing import APITestCase +from utilities.testing import APITestCase, APIViewTestCases class AppTest(APITestCase): def test_root(self): - url = reverse('circuits-api:api-root') response = self.client.get('{}?format=api'.format(url), **self.header) self.assertEqual(response.status_code, 200) -class ProviderTest(APITestCase): +class ProviderTest(APIViewTestCases.APIViewTestCase): + model = Provider + brief_fields = ['circuit_count', 'id', 'name', 'slug', 'url'] + create_data = [ + { + 'name': 'Provider 4', + 'slug': 'provider-4', + }, + { + 'name': 'Provider 5', + 'slug': 'provider-5', + }, + { + 'name': 'Provider 6', + 'slug': 'provider-6', + }, + ] - def setUp(self): + @classmethod + def setUpTestData(cls): - super().setUp() - - self.provider1 = Provider.objects.create(name='Test Provider 1', slug='test-provider-1') - self.provider2 = Provider.objects.create(name='Test Provider 2', slug='test-provider-2') - self.provider3 = Provider.objects.create(name='Test Provider 3', slug='test-provider-3') - - def test_get_provider(self): - - url = reverse('circuits-api:provider-detail', kwargs={'pk': self.provider1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.provider1.name) + providers = ( + Provider(name='Provider 1', slug='provider-1'), + Provider(name='Provider 2', slug='provider-2'), + Provider(name='Provider 3', slug='provider-3'), + ) + Provider.objects.bulk_create(providers) def test_get_provider_graphs(self): + """ + Test retrieval of Graphs assigned to Providers. + """ + provider = self.model.objects.first() + ct = ContentType.objects.get(app_label='circuits', model='provider') + graphs = ( + Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=1'), + Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=2'), + Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=3'), + ) + Graph.objects.bulk_create(graphs) - provider_ct = ContentType.objects.get(app_label='circuits', model='provider') - self.graph1 = Graph.objects.create( - type=provider_ct, - name='Test Graph 1', - source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=1' - ) - self.graph2 = Graph.objects.create( - type=provider_ct, - name='Test Graph 2', - source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=2' - ) - self.graph3 = Graph.objects.create( - type=provider_ct, - name='Test Graph 3', - source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=3' - ) - - url = reverse('circuits-api:provider-graphs', kwargs={'pk': self.provider1.pk}) + url = reverse('circuits-api:provider-graphs', kwargs={'pk': provider.pk}) response = self.client.get(url, **self.header) self.assertEqual(len(response.data), 3) - self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?provider=test-provider-1&foo=1') + self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?provider=provider-1&foo=1') - def test_list_providers(self): - url = reverse('circuits-api:provider-list') - response = self.client.get(url, **self.header) +class CircuitTypeTest(APIViewTestCases.APIViewTestCase): + model = CircuitType + brief_fields = ['circuit_count', 'id', 'name', 'slug', 'url'] + create_data = ( + { + 'name': 'Circuit Type 4', + 'slug': 'circuit-type-4', + }, + { + 'name': 'Circuit Type 5', + 'slug': 'circuit-type-5', + }, + { + 'name': 'Circuit Type 6', + 'slug': 'circuit-type-6', + }, + ) - self.assertEqual(response.data['count'], 3) + @classmethod + def setUpTestData(cls): - def test_list_providers_brief(self): - - url = reverse('circuits-api:provider-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['circuit_count', 'id', 'name', 'slug', 'url'] + circuit_types = ( + CircuitType(name='Circuit Type 1', slug='circuit-type-1'), + CircuitType(name='Circuit Type 2', slug='circuit-type-2'), + CircuitType(name='Circuit Type 3', slug='circuit-type-3'), ) + CircuitType.objects.bulk_create(circuit_types) - def test_create_provider(self): - data = { - 'name': 'Test Provider 4', - 'slug': 'test-provider-4', - } +class CircuitTest(APIViewTestCases.APIViewTestCase): + model = Circuit + brief_fields = ['cid', 'id', 'url'] - url = reverse('circuits-api:provider-list') - response = self.client.post(url, data, format='json', **self.header) + @classmethod + def setUpTestData(cls): - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Provider.objects.count(), 4) - provider4 = Provider.objects.get(pk=response.data['id']) - self.assertEqual(provider4.name, data['name']) - self.assertEqual(provider4.slug, data['slug']) + providers = ( + Provider(name='Provider 1', slug='provider-1'), + Provider(name='Provider 2', slug='provider-2'), + ) + Provider.objects.bulk_create(providers) - def test_create_provider_bulk(self): + circuit_types = ( + CircuitType(name='Circuit Type 1', slug='circuit-type-1'), + CircuitType(name='Circuit Type 2', slug='circuit-type-2'), + ) + CircuitType.objects.bulk_create(circuit_types) - data = [ + circuits = ( + Circuit(cid='Circuit 1', provider=providers[0], type=circuit_types[0]), + Circuit(cid='Circuit 2', provider=providers[0], type=circuit_types[0]), + Circuit(cid='Circuit 3', provider=providers[0], type=circuit_types[0]), + ) + Circuit.objects.bulk_create(circuits) + + cls.create_data = [ { - 'name': 'Test Provider 4', - 'slug': 'test-provider-4', + 'cid': 'Circuit 4', + 'provider': providers[1].pk, + 'type': circuit_types[1].pk, }, { - 'name': 'Test Provider 5', - 'slug': 'test-provider-5', + 'cid': 'Circuit 5', + 'provider': providers[1].pk, + 'type': circuit_types[1].pk, }, { - 'name': 'Test Provider 6', - 'slug': 'test-provider-6', + 'cid': 'Circuit 6', + 'provider': providers[1].pk, + 'type': circuit_types[1].pk, }, ] - url = reverse('circuits-api:provider-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Provider.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) +class CircuitTerminationTest(APIViewTestCases.APIViewTestCase): + model = CircuitTermination + brief_fields = ['circuit', 'id', 'term_side', 'url'] - def test_update_provider(self): + @classmethod + def setUpTestData(cls): + SIDE_A = CircuitTerminationSideChoices.SIDE_A + SIDE_Z = CircuitTerminationSideChoices.SIDE_Z - data = { - 'name': 'Test Provider X', - 'slug': 'test-provider-x', - } - - url = reverse('circuits-api:provider-detail', kwargs={'pk': self.provider1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Provider.objects.count(), 3) - provider1 = Provider.objects.get(pk=response.data['id']) - self.assertEqual(provider1.name, data['name']) - self.assertEqual(provider1.slug, data['slug']) - - def test_delete_provider(self): - - url = reverse('circuits-api:provider-detail', kwargs={'pk': self.provider1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Provider.objects.count(), 2) - - -class CircuitTypeTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.circuittype1 = CircuitType.objects.create(name='Test Circuit Type 1', slug='test-circuit-type-1') - self.circuittype2 = CircuitType.objects.create(name='Test Circuit Type 2', slug='test-circuit-type-2') - self.circuittype3 = CircuitType.objects.create(name='Test Circuit Type 3', slug='test-circuit-type-3') - - def test_get_circuittype(self): - - url = reverse('circuits-api:circuittype-detail', kwargs={'pk': self.circuittype1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.circuittype1.name) - - def test_list_circuittypes(self): - - url = reverse('circuits-api:circuittype-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_circuittypes_brief(self): - - url = reverse('circuits-api:circuittype-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['circuit_count', 'id', 'name', 'slug', 'url'] + sites = ( + Site(name='Site 1', slug='site-1'), + Site(name='Site 2', slug='site-2'), ) + Site.objects.bulk_create(sites) - def test_create_circuittype(self): + provider = Provider.objects.create(name='Provider 1', slug='provider-1') + circuit_type = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1') - data = { - 'name': 'Test Circuit Type 4', - 'slug': 'test-circuit-type-4', - } - - url = reverse('circuits-api:circuittype-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(CircuitType.objects.count(), 4) - circuittype4 = CircuitType.objects.get(pk=response.data['id']) - self.assertEqual(circuittype4.name, data['name']) - self.assertEqual(circuittype4.slug, data['slug']) - - def test_update_circuittype(self): - - data = { - 'name': 'Test Circuit Type X', - 'slug': 'test-circuit-type-x', - } - - url = reverse('circuits-api:circuittype-detail', kwargs={'pk': self.circuittype1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(CircuitType.objects.count(), 3) - circuittype1 = CircuitType.objects.get(pk=response.data['id']) - self.assertEqual(circuittype1.name, data['name']) - self.assertEqual(circuittype1.slug, data['slug']) - - def test_delete_circuittype(self): - - url = reverse('circuits-api:circuittype-detail', kwargs={'pk': self.circuittype1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(CircuitType.objects.count(), 2) - - -class CircuitTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.provider1 = Provider.objects.create(name='Test Provider 1', slug='test-provider-1') - self.provider2 = Provider.objects.create(name='Test Provider 2', slug='test-provider-2') - self.circuittype1 = CircuitType.objects.create(name='Test Circuit Type 1', slug='test-circuit-type-1') - self.circuittype2 = CircuitType.objects.create(name='Test Circuit Type 2', slug='test-circuit-type-2') - self.circuit1 = Circuit.objects.create(cid='TEST0001', provider=self.provider1, type=self.circuittype1) - self.circuit2 = Circuit.objects.create(cid='TEST0002', provider=self.provider1, type=self.circuittype1) - self.circuit3 = Circuit.objects.create(cid='TEST0003', provider=self.provider1, type=self.circuittype1) - - def test_get_circuit(self): - - url = reverse('circuits-api:circuit-detail', kwargs={'pk': self.circuit1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['cid'], self.circuit1.cid) - - def test_list_circuits(self): - - url = reverse('circuits-api:circuit-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_circuits_brief(self): - - url = reverse('circuits-api:circuit-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['cid', 'id', 'url'] + circuits = ( + Circuit(cid='Circuit 1', provider=provider, type=circuit_type), + Circuit(cid='Circuit 2', provider=provider, type=circuit_type), + Circuit(cid='Circuit 3', provider=provider, type=circuit_type), ) + Circuit.objects.bulk_create(circuits) - def test_create_circuit(self): + circuit_terminations = ( + CircuitTermination(circuit=circuits[0], site=sites[0], port_speed=100000, term_side=SIDE_A), + CircuitTermination(circuit=circuits[0], site=sites[1], port_speed=100000, term_side=SIDE_Z), + CircuitTermination(circuit=circuits[1], site=sites[0], port_speed=100000, term_side=SIDE_A), + CircuitTermination(circuit=circuits[1], site=sites[1], port_speed=100000, term_side=SIDE_Z), + ) + CircuitTermination.objects.bulk_create(circuit_terminations) - data = { - 'cid': 'TEST0004', - 'provider': self.provider1.pk, - 'type': self.circuittype1.pk, - 'status': CircuitStatusChoices.STATUS_ACTIVE, - } - - url = reverse('circuits-api:circuit-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Circuit.objects.count(), 4) - circuit4 = Circuit.objects.get(pk=response.data['id']) - self.assertEqual(circuit4.cid, data['cid']) - self.assertEqual(circuit4.provider_id, data['provider']) - self.assertEqual(circuit4.type_id, data['type']) - - def test_create_circuit_bulk(self): - - data = [ + cls.create_data = [ { - 'cid': 'TEST0004', - 'provider': self.provider1.pk, - 'type': self.circuittype1.pk, - 'status': CircuitStatusChoices.STATUS_ACTIVE, + 'circuit': circuits[2].pk, + 'term_side': SIDE_A, + 'site': sites[1].pk, + 'port_speed': 200000, }, { - 'cid': 'TEST0005', - 'provider': self.provider1.pk, - 'type': self.circuittype1.pk, - 'status': CircuitStatusChoices.STATUS_ACTIVE, - }, - { - 'cid': 'TEST0006', - 'provider': self.provider1.pk, - 'type': self.circuittype1.pk, - 'status': CircuitStatusChoices.STATUS_ACTIVE, + 'circuit': circuits[2].pk, + 'term_side': SIDE_Z, + 'site': sites[1].pk, + 'port_speed': 200000, }, ] - - url = reverse('circuits-api:circuit-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Circuit.objects.count(), 6) - self.assertEqual(response.data[0]['cid'], data[0]['cid']) - self.assertEqual(response.data[1]['cid'], data[1]['cid']) - self.assertEqual(response.data[2]['cid'], data[2]['cid']) - - def test_update_circuit(self): - - data = { - 'cid': 'TEST000X', - 'provider': self.provider2.pk, - 'type': self.circuittype2.pk, - } - - url = reverse('circuits-api:circuit-detail', kwargs={'pk': self.circuit1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Circuit.objects.count(), 3) - circuit1 = Circuit.objects.get(pk=response.data['id']) - self.assertEqual(circuit1.cid, data['cid']) - self.assertEqual(circuit1.provider_id, data['provider']) - self.assertEqual(circuit1.type_id, data['type']) - - def test_delete_circuit(self): - - url = reverse('circuits-api:circuit-detail', kwargs={'pk': self.circuit1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Circuit.objects.count(), 2) - - -class CircuitTerminationTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.site2 = Site.objects.create(name='Test Site 2', slug='test-site-2') - provider = Provider.objects.create(name='Test Provider', slug='test-provider') - circuittype = CircuitType.objects.create(name='Test Circuit Type', slug='test-circuit-type') - self.circuit1 = Circuit.objects.create(cid='TEST0001', provider=provider, type=circuittype) - self.circuit2 = Circuit.objects.create(cid='TEST0002', provider=provider, type=circuittype) - self.circuit3 = Circuit.objects.create(cid='TEST0003', provider=provider, type=circuittype) - self.circuittermination1 = CircuitTermination.objects.create( - circuit=self.circuit1, - term_side=CircuitTerminationSideChoices.SIDE_A, - site=self.site1, - port_speed=1000000 - ) - self.circuittermination2 = CircuitTermination.objects.create( - circuit=self.circuit1, - term_side=CircuitTerminationSideChoices.SIDE_Z, - site=self.site2, - port_speed=1000000 - ) - self.circuittermination3 = CircuitTermination.objects.create( - circuit=self.circuit2, - term_side=CircuitTerminationSideChoices.SIDE_A, - site=self.site1, - port_speed=1000000 - ) - self.circuittermination4 = CircuitTermination.objects.create( - circuit=self.circuit2, - term_side=CircuitTerminationSideChoices.SIDE_Z, - site=self.site2, - port_speed=1000000 - ) - - def test_get_circuittermination(self): - - url = reverse('circuits-api:circuittermination-detail', kwargs={'pk': self.circuittermination1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['id'], self.circuittermination1.pk) - - def test_list_circuitterminations(self): - - url = reverse('circuits-api:circuittermination-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 4) - - def test_create_circuittermination(self): - - data = { - 'circuit': self.circuit3.pk, - 'term_side': CircuitTerminationSideChoices.SIDE_A, - 'site': self.site1.pk, - 'port_speed': 1000000, - } - - url = reverse('circuits-api:circuittermination-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(CircuitTermination.objects.count(), 5) - circuittermination4 = CircuitTermination.objects.get(pk=response.data['id']) - self.assertEqual(circuittermination4.circuit_id, data['circuit']) - self.assertEqual(circuittermination4.term_side, data['term_side']) - self.assertEqual(circuittermination4.site_id, data['site']) - self.assertEqual(circuittermination4.port_speed, data['port_speed']) - - def test_update_circuittermination(self): - - circuittermination5 = CircuitTermination.objects.create( - circuit=self.circuit3, - term_side=CircuitTerminationSideChoices.SIDE_A, - site=self.site1, - port_speed=1000000 - ) - - data = { - 'circuit': self.circuit3.pk, - 'term_side': CircuitTerminationSideChoices.SIDE_Z, - 'site': self.site2.pk, - 'port_speed': 1000000, - } - - url = reverse('circuits-api:circuittermination-detail', kwargs={'pk': circuittermination5.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(CircuitTermination.objects.count(), 5) - circuittermination1 = CircuitTermination.objects.get(pk=response.data['id']) - self.assertEqual(circuittermination1.term_side, data['term_side']) - self.assertEqual(circuittermination1.site_id, data['site']) - self.assertEqual(circuittermination1.port_speed, data['port_speed']) - - def test_delete_circuittermination(self): - - url = reverse('circuits-api:circuittermination-detail', kwargs={'pk': self.circuittermination1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(CircuitTermination.objects.count(), 3) diff --git a/netbox/dcim/api/nested_serializers.py b/netbox/dcim/api/nested_serializers.py index a8d413d37..83fcd7a2a 100644 --- a/netbox/dcim/api/nested_serializers.py +++ b/netbox/dcim/api/nested_serializers.py @@ -302,6 +302,7 @@ class NestedDeviceBaySerializer(WritableNestedSerializer): class NestedInventoryItemSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitem-detail') + device = NestedDeviceSerializer(read_only=True) class Meta: model = models.InventoryItem diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py index d45d972f8..6c6b75c7f 100644 --- a/netbox/dcim/tests/test_api.py +++ b/netbox/dcim/tests/test_api.py @@ -1,6 +1,6 @@ +from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.urls import reverse -from netaddr import IPNetwork from rest_framework import status from circuits.models import Circuit, CircuitTermination, CircuitType, Provider @@ -12,9 +12,9 @@ from dcim.models import ( InventoryItem, Platform, PowerFeed, PowerPort, PowerPortTemplate, PowerOutlet, PowerOutletTemplate, PowerPanel, Rack, RackGroup, RackReservation, RackRole, RearPort, Region, Site, VirtualChassis, ) -from ipam.models import IPAddress, VLAN +from ipam.models import VLAN from extras.models import Graph -from utilities.testing import APITestCase +from utilities.testing import APITestCase, APIViewTestCases from virtualization.models import Cluster, ClusterType @@ -28,2007 +28,796 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class RegionTest(APITestCase): +class RegionTest(APIViewTestCases.APIViewTestCase): + model = Region + brief_fields = ['id', 'name', 'site_count', 'slug', 'url'] + create_data = [ + { + 'name': 'Region 4', + 'slug': 'region-4', + }, + { + 'name': 'Region 5', + 'slug': 'region-5', + }, + { + 'name': 'Region 6', + 'slug': 'region-6', + }, + ] - def setUp(self): + @classmethod + def setUpTestData(cls): - super().setUp() + Region.objects.create(name='Region 1', slug='region-1') + Region.objects.create(name='Region 2', slug='region-2') + Region.objects.create(name='Region 3', slug='region-3') - self.region1 = Region.objects.create(name='Test Region 1', slug='test-region-1') - self.region2 = Region.objects.create(name='Test Region 2', slug='test-region-2') - self.region3 = Region.objects.create(name='Test Region 3', slug='test-region-3') - def test_get_region(self): +class SiteTest(APIViewTestCases.APIViewTestCase): + model = Site + brief_fields = ['id', 'name', 'slug', 'url'] - url = reverse('dcim-api:region-detail', kwargs={'pk': self.region1.pk}) - response = self.client.get(url, **self.header) + @classmethod + def setUpTestData(cls): - self.assertEqual(response.data['name'], self.region1.name) - - def test_list_regions(self): - - url = reverse('dcim-api:region-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_regions_brief(self): - - url = reverse('dcim-api:region-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'site_count', 'slug', 'url'] + regions = ( + Region.objects.create(name='Test Region 1', slug='test-region-1'), + Region.objects.create(name='Test Region 2', slug='test-region-2'), ) - def test_create_region(self): + sites = ( + Site(region=regions[0], name='Site 1', slug='site-1'), + Site(region=regions[0], name='Site 2', slug='site-2'), + Site(region=regions[0], name='Site 3', slug='site-3'), + ) + Site.objects.bulk_create(sites) - data = { - 'name': 'Test Region 4', - 'slug': 'test-region-4', - } - - url = reverse('dcim-api:region-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Region.objects.count(), 4) - region4 = Region.objects.get(pk=response.data['id']) - self.assertEqual(region4.name, data['name']) - self.assertEqual(region4.slug, data['slug']) - - def test_create_region_bulk(self): - - data = [ + cls.create_data = [ { - 'name': 'Test Region 4', - 'slug': 'test-region-4', + 'name': 'Site 4', + 'slug': 'site-4', + 'region': regions[1].pk, + 'status': SiteStatusChoices.STATUS_ACTIVE, }, { - 'name': 'Test Region 5', - 'slug': 'test-region-5', + 'name': 'Site 5', + 'slug': 'site-5', + 'region': regions[1].pk, + 'status': SiteStatusChoices.STATUS_ACTIVE, }, { - 'name': 'Test Region 6', - 'slug': 'test-region-6', + 'name': 'Site 6', + 'slug': 'site-6', + 'region': regions[1].pk, + 'status': SiteStatusChoices.STATUS_ACTIVE, }, ] - url = reverse('dcim-api:region-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Region.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_region(self): - - data = { - 'name': 'Test Region X', - 'slug': 'test-region-x', - } - - url = reverse('dcim-api:region-detail', kwargs={'pk': self.region1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Region.objects.count(), 3) - region1 = Region.objects.get(pk=response.data['id']) - self.assertEqual(region1.name, data['name']) - self.assertEqual(region1.slug, data['slug']) - - def test_delete_region(self): - - url = reverse('dcim-api:region-detail', kwargs={'pk': self.region1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Region.objects.count(), 2) - - -class SiteTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.region1 = Region.objects.create(name='Test Region 1', slug='test-region-1') - self.region2 = Region.objects.create(name='Test Region 2', slug='test-region-2') - self.site1 = Site.objects.create(region=self.region1, name='Test Site 1', slug='test-site-1') - self.site2 = Site.objects.create(region=self.region1, name='Test Site 2', slug='test-site-2') - self.site3 = Site.objects.create(region=self.region1, name='Test Site 3', slug='test-site-3') - - def test_get_site(self): - - url = reverse('dcim-api:site-detail', kwargs={'pk': self.site1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.site1.name) - def test_get_site_graphs(self): + """ + Test retrieval of Graphs assigned to Sites. + """ + ct = ContentType.objects.get_for_model(Site) + graphs = ( + Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?site={{ obj.slug }}&foo=1'), + Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?site={{ obj.slug }}&foo=2'), + Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?site={{ obj.slug }}&foo=3'), + ) + Graph.objects.bulk_create(graphs) - site_ct = ContentType.objects.get_for_model(Site) - self.graph1 = Graph.objects.create( - type=site_ct, - name='Test Graph 1', - source='http://example.com/graphs.py?site={{ obj.slug }}&foo=1' - ) - self.graph2 = Graph.objects.create( - type=site_ct, - name='Test Graph 2', - source='http://example.com/graphs.py?site={{ obj.slug }}&foo=2' - ) - self.graph3 = Graph.objects.create( - type=site_ct, - name='Test Graph 3', - source='http://example.com/graphs.py?site={{ obj.slug }}&foo=3' - ) - - url = reverse('dcim-api:site-graphs', kwargs={'pk': self.site1.pk}) + url = reverse('dcim-api:site-graphs', kwargs={'pk': Site.objects.first().pk}) response = self.client.get(url, **self.header) self.assertEqual(len(response.data), 3) - self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?site=test-site-1&foo=1') + self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?site=site-1&foo=1') - def test_list_sites(self): - url = reverse('dcim-api:site-list') - response = self.client.get(url, **self.header) +class RackGroupTest(APIViewTestCases.APIViewTestCase): + model = RackGroup + brief_fields = ['id', 'name', 'rack_count', 'slug', 'url'] - self.assertEqual(response.data['count'], 3) + @classmethod + def setUpTestData(cls): - def test_list_sites_brief(self): + sites = ( + Site(name='Site 1', slug='site-1'), + Site(name='Site 2', slug='site-2'), + ) + Site.objects.bulk_create(sites) - url = reverse('dcim-api:site-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'slug', 'url'] + parent_rack_groups = ( + RackGroup.objects.create(site=sites[0], name='Parent Rack Group 1', slug='parent-rack-group-1'), + RackGroup.objects.create(site=sites[1], name='Parent Rack Group 2', slug='parent-rack-group-2'), ) - def test_create_site(self): + RackGroup.objects.create(site=sites[0], name='Rack Group 1', slug='rack-group-1', parent=parent_rack_groups[0]) + RackGroup.objects.create(site=sites[0], name='Rack Group 2', slug='rack-group-2', parent=parent_rack_groups[0]) + RackGroup.objects.create(site=sites[0], name='Rack Group 3', slug='rack-group-3', parent=parent_rack_groups[0]) - data = { - 'name': 'Test Site 4', - 'slug': 'test-site-4', - 'region': self.region1.pk, - 'status': SiteStatusChoices.STATUS_ACTIVE, - } - - url = reverse('dcim-api:site-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Site.objects.count(), 4) - site4 = Site.objects.get(pk=response.data['id']) - self.assertEqual(site4.name, data['name']) - self.assertEqual(site4.slug, data['slug']) - self.assertEqual(site4.region_id, data['region']) - - def test_create_site_bulk(self): - - data = [ - { - 'name': 'Test Site 4', - 'slug': 'test-site-4', - 'region': self.region1.pk, - 'status': SiteStatusChoices.STATUS_ACTIVE, - }, - { - 'name': 'Test Site 5', - 'slug': 'test-site-5', - 'region': self.region1.pk, - 'status': SiteStatusChoices.STATUS_ACTIVE, - }, - { - 'name': 'Test Site 6', - 'slug': 'test-site-6', - 'region': self.region1.pk, - 'status': SiteStatusChoices.STATUS_ACTIVE, - }, - ] - - url = reverse('dcim-api:site-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Site.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_site(self): - - data = { - 'name': 'Test Site X', - 'slug': 'test-site-x', - 'region': self.region2.pk, - } - - url = reverse('dcim-api:site-detail', kwargs={'pk': self.site1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Site.objects.count(), 3) - site1 = Site.objects.get(pk=response.data['id']) - self.assertEqual(site1.name, data['name']) - self.assertEqual(site1.slug, data['slug']) - self.assertEqual(site1.region_id, data['region']) - - def test_delete_site(self): - - url = reverse('dcim-api:site-detail', kwargs={'pk': self.site1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Site.objects.count(), 2) - - -class RackGroupTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.site2 = Site.objects.create(name='Test Site 2', slug='test-site-2') - self.parent_rackgroup1 = RackGroup.objects.create(site=self.site1, name='Parent Rack Group 1', slug='parent-rack-group-1') - self.parent_rackgroup2 = RackGroup.objects.create(site=self.site2, name='Parent Rack Group 2', slug='parent-rack-group-2') - self.rackgroup1 = RackGroup.objects.create(site=self.site1, name='Rack Group 1', slug='rack-group-1', parent=self.parent_rackgroup1) - self.rackgroup2 = RackGroup.objects.create(site=self.site1, name='Rack Group 2', slug='rack-group-2', parent=self.parent_rackgroup1) - self.rackgroup3 = RackGroup.objects.create(site=self.site1, name='Rack Group 3', slug='rack-group-3', parent=self.parent_rackgroup1) - - def test_get_rackgroup(self): - - url = reverse('dcim-api:rackgroup-detail', kwargs={'pk': self.rackgroup1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.rackgroup1.name) - - def test_list_rackgroups(self): - - url = reverse('dcim-api:rackgroup-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 5) - - def test_list_rackgroups_brief(self): - - url = reverse('dcim-api:rackgroup-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'rack_count', 'slug', 'url'] - ) - - def test_create_rackgroup(self): - - data = { - 'name': 'Rack Group 4', - 'slug': 'rack-group-4', - 'site': self.site1.pk, - 'parent': self.parent_rackgroup1.pk, - } - - url = reverse('dcim-api:rackgroup-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(RackGroup.objects.count(), 6) - rackgroup4 = RackGroup.objects.get(pk=response.data['id']) - self.assertEqual(rackgroup4.name, data['name']) - self.assertEqual(rackgroup4.slug, data['slug']) - self.assertEqual(rackgroup4.site_id, data['site']) - self.assertEqual(rackgroup4.parent_id, data['parent']) - - def test_create_rackgroup_bulk(self): - - data = [ + cls.create_data = [ { 'name': 'Test Rack Group 4', 'slug': 'test-rack-group-4', - 'site': self.site1.pk, - 'parent': self.parent_rackgroup1.pk, + 'site': sites[1].pk, + 'parent': parent_rack_groups[1].pk, }, { 'name': 'Test Rack Group 5', 'slug': 'test-rack-group-5', - 'site': self.site1.pk, - 'parent': self.parent_rackgroup1.pk, + 'site': sites[1].pk, + 'parent': parent_rack_groups[1].pk, }, { 'name': 'Test Rack Group 6', 'slug': 'test-rack-group-6', - 'site': self.site1.pk, - 'parent': self.parent_rackgroup1.pk, + 'site': sites[1].pk, + 'parent': parent_rack_groups[1].pk, }, ] - url = reverse('dcim-api:rackgroup-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(RackGroup.objects.count(), 8) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) +class RackRoleTest(APIViewTestCases.APIViewTestCase): + model = RackRole + brief_fields = ['id', 'name', 'rack_count', 'slug', 'url'] + create_data = [ + { + 'name': 'Rack Role 4', + 'slug': 'rack-role-4', + 'color': 'ffff00', + }, + { + 'name': 'Rack Role 5', + 'slug': 'rack-role-5', + 'color': 'ffff00', + }, + { + 'name': 'Rack Role 6', + 'slug': 'rack-role-6', + 'color': 'ffff00', + }, + ] - def test_update_rackgroup(self): + @classmethod + def setUpTestData(cls): - data = { - 'name': 'Test Rack Group X', - 'slug': 'test-rack-group-x', - 'site': self.site2.pk, - 'parent': self.parent_rackgroup2.pk, - } - - url = reverse('dcim-api:rackgroup-detail', kwargs={'pk': self.rackgroup1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(RackGroup.objects.count(), 5) - rackgroup1 = RackGroup.objects.get(pk=response.data['id']) - self.assertEqual(rackgroup1.name, data['name']) - self.assertEqual(rackgroup1.slug, data['slug']) - self.assertEqual(rackgroup1.site_id, data['site']) - self.assertEqual(rackgroup1.parent_id, data['parent']) - - def test_delete_rackgroup(self): - - url = reverse('dcim-api:rackgroup-detail', kwargs={'pk': self.rackgroup1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(RackGroup.objects.count(), 4) + rack_roles = ( + RackRole(name='Rack Role 1', slug='rack-role-1', color='ff0000'), + RackRole(name='Rack Role 2', slug='rack-role-2', color='00ff00'), + RackRole(name='Rack Role 3', slug='rack-role-3', color='0000ff'), + ) + RackRole.objects.bulk_create(rack_roles) -class RackRoleTest(APITestCase): +class RackTest(APIViewTestCases.APIViewTestCase): + model = Rack + brief_fields = ['device_count', 'display_name', 'id', 'name', 'url'] - def setUp(self): + @classmethod + def setUpTestData(cls): - super().setUp() + sites = ( + Site(name='Site 1', slug='site-1'), + Site(name='Site 2', slug='site-2'), + ) + Site.objects.bulk_create(sites) - self.rackrole1 = RackRole.objects.create(name='Test Rack Role 1', slug='test-rack-role-1', color='ff0000') - self.rackrole2 = RackRole.objects.create(name='Test Rack Role 2', slug='test-rack-role-2', color='00ff00') - self.rackrole3 = RackRole.objects.create(name='Test Rack Role 3', slug='test-rack-role-3', color='0000ff') - - def test_get_rackrole(self): - - url = reverse('dcim-api:rackrole-detail', kwargs={'pk': self.rackrole1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.rackrole1.name) - - def test_list_rackroles(self): - - url = reverse('dcim-api:rackrole-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_rackroles_brief(self): - - url = reverse('dcim-api:rackrole-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'rack_count', 'slug', 'url'] + rack_groups = ( + RackGroup.objects.create(site=sites[0], name='Rack Group 1', slug='rack-group-1'), + RackGroup.objects.create(site=sites[1], name='Rack Group 2', slug='rack-group-2'), ) - def test_create_rackrole(self): + rack_roles = ( + RackRole(name='Rack Role 1', slug='rack-role-1', color='ff0000'), + RackRole(name='Rack Role 2', slug='rack-role-2', color='00ff00'), + ) + RackRole.objects.bulk_create(rack_roles) - data = { - 'name': 'Test Rack Role 4', - 'slug': 'test-rack-role-4', - 'color': 'ffff00', - } + racks = ( + Rack(site=sites[0], group=rack_groups[0], role=rack_roles[0], name='Rack 1'), + Rack(site=sites[0], group=rack_groups[0], role=rack_roles[0], name='Rack 2'), + Rack(site=sites[0], group=rack_groups[0], role=rack_roles[0], name='Rack 3'), + ) + Rack.objects.bulk_create(racks) - url = reverse('dcim-api:rackrole-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(RackRole.objects.count(), 4) - rackrole1 = RackRole.objects.get(pk=response.data['id']) - self.assertEqual(rackrole1.name, data['name']) - self.assertEqual(rackrole1.slug, data['slug']) - self.assertEqual(rackrole1.color, data['color']) - - def test_create_rackrole_bulk(self): - - data = [ + cls.create_data = [ { - 'name': 'Test Rack Role 4', - 'slug': 'test-rack-role-4', - 'color': 'ffff00', + 'name': 'Test Rack 4', + 'site': sites[1].pk, + 'group': rack_groups[1].pk, + 'role': rack_roles[1].pk, }, { - 'name': 'Test Rack Role 5', - 'slug': 'test-rack-role-5', - 'color': 'ffff00', + 'name': 'Test Rack 5', + 'site': sites[1].pk, + 'group': rack_groups[1].pk, + 'role': rack_roles[1].pk, }, { - 'name': 'Test Rack Role 6', - 'slug': 'test-rack-role-6', - 'color': 'ffff00', + 'name': 'Test Rack 6', + 'site': sites[1].pk, + 'group': rack_groups[1].pk, + 'role': rack_roles[1].pk, }, ] - url = reverse('dcim-api:rackrole-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(RackRole.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_rackrole(self): - - data = { - 'name': 'Test Rack Role X', - 'slug': 'test-rack-role-x', - 'color': 'ffff00', - } - - url = reverse('dcim-api:rackrole-detail', kwargs={'pk': self.rackrole1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(RackRole.objects.count(), 3) - rackrole1 = RackRole.objects.get(pk=response.data['id']) - self.assertEqual(rackrole1.name, data['name']) - self.assertEqual(rackrole1.slug, data['slug']) - self.assertEqual(rackrole1.color, data['color']) - - def test_delete_rackrole(self): - - url = reverse('dcim-api:rackrole-detail', kwargs={'pk': self.rackrole1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(RackRole.objects.count(), 2) - - -class RackTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.site2 = Site.objects.create(name='Test Site 2', slug='test-site-2') - self.rackgroup1 = RackGroup.objects.create(site=self.site1, name='Test Rack Group 1', slug='test-rack-group-1') - self.rackgroup2 = RackGroup.objects.create(site=self.site2, name='Test Rack Group 2', slug='test-rack-group-2') - self.rackrole1 = RackRole.objects.create(name='Test Rack Role 1', slug='test-rack-role-1', color='ff0000') - self.rackrole2 = RackRole.objects.create(name='Test Rack Role 2', slug='test-rack-role-2', color='00ff00') - self.rack1 = Rack.objects.create( - site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 1', u_height=42, - ) - self.rack2 = Rack.objects.create( - site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 2', u_height=42, - ) - self.rack3 = Rack.objects.create( - site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 3', u_height=42, - ) - - def test_get_rack(self): - - url = reverse('dcim-api:rack-detail', kwargs={'pk': self.rack1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.rack1.name) - + # TODO: Document this test def test_get_elevation_rack_units(self): + rack = Rack.objects.first() - url = '{}?q=3'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk})) + url = '{}?q=3'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk})) response = self.client.get(url, **self.header) self.assertEqual(response.data['count'], 13) - url = '{}?q=U3'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk})) + url = '{}?q=U3'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk})) response = self.client.get(url, **self.header) self.assertEqual(response.data['count'], 11) - url = '{}?q=10'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk})) + url = '{}?q=10'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk})) response = self.client.get(url, **self.header) self.assertEqual(response.data['count'], 1) - url = '{}?q=U20'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk})) + url = '{}?q=U20'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk})) response = self.client.get(url, **self.header) self.assertEqual(response.data['count'], 1) def test_get_rack_elevation(self): - - url = reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk}) + """ + GET a single rack elevation. + """ + rack = Rack.objects.first() + url = reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk}) response = self.client.get(url, **self.header) self.assertEqual(response.data['count'], 42) def test_get_rack_elevation_svg(self): - - url = '{}?render=svg'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': self.rack1.pk})) + """ + GET a single rack elevation in SVG format. + """ + rack = Rack.objects.first() + url = '{}?render=svg'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk})) response = self.client.get(url, **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.get('Content-Type'), 'image/svg+xml') - def test_list_racks(self): - url = reverse('dcim-api:rack-list') - response = self.client.get(url, **self.header) +class RackReservationTest(APIViewTestCases.APIViewTestCase): + model = RackReservation + brief_fields = ['id', 'units', 'url', 'user'] - self.assertEqual(response.data['count'], 3) + @classmethod + def setUpTestData(cls): - def test_list_racks_brief(self): + user = User.objects.create(username='user1', is_active=True) - url = reverse('dcim-api:rack-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) + site = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.assertEqual( - sorted(response.data['results'][0]), - ['device_count', 'display_name', 'id', 'name', 'url'] + cls.racks = ( + Rack(site=site, name='Rack 1'), + Rack(site=site, name='Rack 2'), ) + Rack.objects.bulk_create(cls.racks) - def test_create_rack(self): - - data = { - 'name': 'Test Rack 4', - 'facility_id': '1234', - 'site': self.site1.pk, - 'group': self.rackgroup1.pk, - 'role': self.rackrole1.pk, - } - - url = reverse('dcim-api:rack-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Rack.objects.count(), 4) - rack4 = Rack.objects.get(pk=response.data['id']) - self.assertEqual(rack4.name, data['name']) - self.assertEqual(rack4.site_id, data['site']) - self.assertEqual(rack4.group_id, data['group']) - self.assertEqual(rack4.role_id, data['role']) - - def test_create_rack_bulk(self): - - data = [ - { - 'name': 'Test Rack 4', - 'site': self.site1.pk, - 'group': self.rackgroup1.pk, - 'role': self.rackrole1.pk, - }, - { - 'name': 'Test Rack 5', - 'site': self.site1.pk, - 'group': self.rackgroup1.pk, - 'role': self.rackrole1.pk, - }, - { - 'name': 'Test Rack 6', - 'site': self.site1.pk, - 'group': self.rackgroup1.pk, - 'role': self.rackrole1.pk, - }, - ] - - url = reverse('dcim-api:rack-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Rack.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_rack(self): - - data = { - 'name': 'Test Rack X', - 'site': self.site2.pk, - 'group': self.rackgroup2.pk, - 'role': self.rackrole2.pk, - } - - url = reverse('dcim-api:rack-detail', kwargs={'pk': self.rack1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Rack.objects.count(), 3) - rack1 = Rack.objects.get(pk=response.data['id']) - self.assertEqual(rack1.name, data['name']) - self.assertEqual(rack1.site_id, data['site']) - self.assertEqual(rack1.group_id, data['group']) - self.assertEqual(rack1.role_id, data['role']) - - def test_delete_rack(self): - - url = reverse('dcim-api:rack-detail', kwargs={'pk': self.rack1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Rack.objects.count(), 2) - - -class RackReservationTest(APITestCase): + rack_reservations = ( + RackReservation(rack=cls.racks[0], units=[1, 2, 3], user=user, description='Reservation #1'), + RackReservation(rack=cls.racks[0], units=[4, 5, 6], user=user, description='Reservation #2'), + RackReservation(rack=cls.racks[0], units=[7, 8, 9], user=user, description='Reservation #3'), + ) + RackReservation.objects.bulk_create(rack_reservations) def setUp(self): - super().setUp() - self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.rack1 = Rack.objects.create(site=self.site1, name='Test Rack 1') - self.rackreservation1 = RackReservation.objects.create( - rack=self.rack1, units=[1, 2, 3], user=self.user, description='Reservation #1', - ) - self.rackreservation2 = RackReservation.objects.create( - rack=self.rack1, units=[4, 5, 6], user=self.user, description='Reservation #2', - ) - self.rackreservation3 = RackReservation.objects.create( - rack=self.rack1, units=[7, 8, 9], user=self.user, description='Reservation #3', - ) - - def test_get_rackreservation(self): - - url = reverse('dcim-api:rackreservation-detail', kwargs={'pk': self.rackreservation1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['id'], self.rackreservation1.pk) - - def test_list_rackreservations(self): - - url = reverse('dcim-api:rackreservation-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_rackreservation(self): - - data = { - 'rack': self.rack1.pk, - 'units': [10, 11, 12], - 'user': self.user.pk, - 'description': 'Fourth reservation', - } - - url = reverse('dcim-api:rackreservation-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(RackReservation.objects.count(), 4) - rackreservation4 = RackReservation.objects.get(pk=response.data['id']) - self.assertEqual(rackreservation4.rack_id, data['rack']) - self.assertEqual(rackreservation4.units, data['units']) - self.assertEqual(rackreservation4.user_id, data['user']) - self.assertEqual(rackreservation4.description, data['description']) - - def test_create_rackreservation_bulk(self): - - data = [ + # We have to set creation data under setUp() because we need access to the test user. + self.create_data = [ { - 'rack': self.rack1.pk, + 'rack': self.racks[1].pk, 'units': [10, 11, 12], 'user': self.user.pk, 'description': 'Reservation #4', }, { - 'rack': self.rack1.pk, + 'rack': self.racks[1].pk, 'units': [13, 14, 15], 'user': self.user.pk, 'description': 'Reservation #5', }, { - 'rack': self.rack1.pk, + 'rack': self.racks[1].pk, 'units': [16, 17, 18], 'user': self.user.pk, 'description': 'Reservation #6', }, ] - url = reverse('dcim-api:rackreservation-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(RackReservation.objects.count(), 6) - self.assertEqual(response.data[0]['description'], data[0]['description']) - self.assertEqual(response.data[1]['description'], data[1]['description']) - self.assertEqual(response.data[2]['description'], data[2]['description']) +class ManufacturerTest(APIViewTestCases.APIViewTestCase): + model = Manufacturer + brief_fields = ['devicetype_count', 'id', 'name', 'slug', 'url'] + create_data = [ + { + 'name': 'Manufacturer 4', + 'slug': 'manufacturer-4', + }, + { + 'name': 'Manufacturer 5', + 'slug': 'manufacturer-5', + }, + { + 'name': 'Manufacturer 6', + 'slug': 'manufacturer-6', + }, + ] - def test_update_rackreservation(self): + @classmethod + def setUpTestData(cls): - data = { - 'rack': self.rack1.pk, - 'units': [10, 11, 12], - 'user': self.user.pk, - 'description': 'Modified reservation', - } - - url = reverse('dcim-api:rackreservation-detail', kwargs={'pk': self.rackreservation1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(RackReservation.objects.count(), 3) - rackreservation1 = RackReservation.objects.get(pk=response.data['id']) - self.assertEqual(rackreservation1.units, data['units']) - self.assertEqual(rackreservation1.description, data['description']) - - def test_delete_rackreservation(self): - - url = reverse('dcim-api:rackreservation-detail', kwargs={'pk': self.rackreservation1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(RackReservation.objects.count(), 2) - - -class ManufacturerTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.manufacturer1 = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - self.manufacturer2 = Manufacturer.objects.create(name='Test Manufacturer 2', slug='test-manufacturer-2') - self.manufacturer3 = Manufacturer.objects.create(name='Test Manufacturer 3', slug='test-manufacturer-3') - - def test_get_manufacturer(self): - - url = reverse('dcim-api:manufacturer-detail', kwargs={'pk': self.manufacturer1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.manufacturer1.name) - - def test_list_manufacturers(self): - - url = reverse('dcim-api:manufacturer-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_manufacturers_brief(self): - - url = reverse('dcim-api:manufacturer-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['devicetype_count', 'id', 'name', 'slug', 'url'] + manufacturers = ( + Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), + Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), + Manufacturer(name='Manufacturer 3', slug='manufacturer-3'), ) + Manufacturer.objects.bulk_create(manufacturers) - def test_create_manufacturer(self): - data = { - 'name': 'Test Manufacturer 4', - 'slug': 'test-manufacturer-4', - } +class DeviceTypeTest(APIViewTestCases.APIViewTestCase): + model = DeviceType + brief_fields = ['device_count', 'display_name', 'id', 'manufacturer', 'model', 'slug', 'url'] - url = reverse('dcim-api:manufacturer-list') - response = self.client.post(url, data, format='json', **self.header) + @classmethod + def setUpTestData(cls): - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Manufacturer.objects.count(), 4) - manufacturer4 = Manufacturer.objects.get(pk=response.data['id']) - self.assertEqual(manufacturer4.name, data['name']) - self.assertEqual(manufacturer4.slug, data['slug']) + manufacturers = ( + Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), + Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), + ) + Manufacturer.objects.bulk_create(manufacturers) - def test_create_manufacturer_bulk(self): + device_types = ( + DeviceType(manufacturer=manufacturers[0], model='Device Type 1', slug='device-type-1'), + DeviceType(manufacturer=manufacturers[0], model='Device Type 2', slug='device-type-2'), + DeviceType(manufacturer=manufacturers[0], model='Device Type 3', slug='device-type-3'), + ) + DeviceType.objects.bulk_create(device_types) - data = [ + cls.create_data = [ { - 'name': 'Test Manufacturer 4', - 'slug': 'test-manufacturer-4', + 'manufacturer': manufacturers[1].pk, + 'model': 'Device Type 4', + 'slug': 'device-type-4', }, { - 'name': 'Test Manufacturer 5', - 'slug': 'test-manufacturer-5', + 'manufacturer': manufacturers[1].pk, + 'model': 'Device Type 5', + 'slug': 'device-type-5', }, { - 'name': 'Test Manufacturer 6', - 'slug': 'test-manufacturer-6', + 'manufacturer': manufacturers[1].pk, + 'model': 'Device Type 6', + 'slug': 'device-type-6', }, ] - url = reverse('dcim-api:manufacturer-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Manufacturer.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) +class ConsolePortTemplateTest(APIViewTestCases.APIViewTestCase): + model = ConsolePortTemplate + brief_fields = ['id', 'name', 'url'] - def test_update_manufacturer(self): - - data = { - 'name': 'Test Manufacturer X', - 'slug': 'test-manufacturer-x', - } - - url = reverse('dcim-api:manufacturer-detail', kwargs={'pk': self.manufacturer1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Manufacturer.objects.count(), 3) - manufacturer1 = Manufacturer.objects.get(pk=response.data['id']) - self.assertEqual(manufacturer1.name, data['name']) - self.assertEqual(manufacturer1.slug, data['slug']) - - def test_delete_manufacturer(self): - - url = reverse('dcim-api:manufacturer-detail', kwargs={'pk': self.manufacturer1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Manufacturer.objects.count(), 2) - - -class DeviceTypeTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.manufacturer1 = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - self.manufacturer2 = Manufacturer.objects.create(name='Test Manufacturer 2', slug='test-manufacturer-2') - self.devicetype1 = DeviceType.objects.create( - manufacturer=self.manufacturer1, model='Test Device Type 1', slug='test-device-type-1' - ) - self.devicetype2 = DeviceType.objects.create( - manufacturer=self.manufacturer1, model='Test Device Type 2', slug='test-device-type-2' - ) - self.devicetype3 = DeviceType.objects.create( - manufacturer=self.manufacturer1, model='Test Device Type 3', slug='test-device-type-3' - ) - - def test_get_devicetype(self): - - url = reverse('dcim-api:devicetype-detail', kwargs={'pk': self.devicetype1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['model'], self.devicetype1.model) - - def test_list_devicetypes(self): - - url = reverse('dcim-api:devicetype-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_devicetypes_brief(self): - - url = reverse('dcim-api:devicetype-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['device_count', 'display_name', 'id', 'manufacturer', 'model', 'slug', 'url'] - ) - - def test_create_devicetype(self): - - data = { - 'manufacturer': self.manufacturer1.pk, - 'model': 'Test Device Type 4', - 'slug': 'test-device-type-4', - } - - url = reverse('dcim-api:devicetype-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(DeviceType.objects.count(), 4) - devicetype4 = DeviceType.objects.get(pk=response.data['id']) - self.assertEqual(devicetype4.manufacturer_id, data['manufacturer']) - self.assertEqual(devicetype4.model, data['model']) - self.assertEqual(devicetype4.slug, data['slug']) - - def test_create_devicetype_bulk(self): - - data = [ - { - 'manufacturer': self.manufacturer1.pk, - 'model': 'Test Device Type 4', - 'slug': 'test-device-type-4', - }, - { - 'manufacturer': self.manufacturer1.pk, - 'model': 'Test Device Type 5', - 'slug': 'test-device-type-5', - }, - { - 'manufacturer': self.manufacturer1.pk, - 'model': 'Test Device Type 6', - 'slug': 'test-device-type-6', - }, - ] - - url = reverse('dcim-api:devicetype-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(DeviceType.objects.count(), 6) - self.assertEqual(response.data[0]['model'], data[0]['model']) - self.assertEqual(response.data[1]['model'], data[1]['model']) - self.assertEqual(response.data[2]['model'], data[2]['model']) - - def test_update_devicetype(self): - - data = { - 'manufacturer': self.manufacturer2.pk, - 'model': 'Test Device Type X', - 'slug': 'test-device-type-x', - } - - url = reverse('dcim-api:devicetype-detail', kwargs={'pk': self.devicetype1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(DeviceType.objects.count(), 3) - devicetype1 = DeviceType.objects.get(pk=response.data['id']) - self.assertEqual(devicetype1.manufacturer_id, data['manufacturer']) - self.assertEqual(devicetype1.model, data['model']) - self.assertEqual(devicetype1.slug, data['slug']) - - def test_delete_devicetype(self): - - url = reverse('dcim-api:devicetype-detail', kwargs={'pk': self.devicetype1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(DeviceType.objects.count(), 2) - - -class ConsolePortTemplateTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - self.devicetype = DeviceType.objects.create( - manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1' - ) - self.consoleporttemplate1 = ConsolePortTemplate.objects.create( - device_type=self.devicetype, name='Test CP Template 1' - ) - self.consoleporttemplate2 = ConsolePortTemplate.objects.create( - device_type=self.devicetype, name='Test CP Template 2' - ) - self.consoleporttemplate3 = ConsolePortTemplate.objects.create( - device_type=self.devicetype, name='Test CP Template 3' - ) - - def test_get_consoleporttemplate(self): - - url = reverse('dcim-api:consoleporttemplate-detail', kwargs={'pk': self.consoleporttemplate1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.consoleporttemplate1.name) - - def test_list_consoleporttemplates(self): - - url = reverse('dcim-api:consoleporttemplate-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_consoleporttemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test CP Template 4', - } - - url = reverse('dcim-api:consoleporttemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ConsolePortTemplate.objects.count(), 4) - consoleporttemplate4 = ConsolePortTemplate.objects.get(pk=response.data['id']) - self.assertEqual(consoleporttemplate4.device_type_id, data['device_type']) - self.assertEqual(consoleporttemplate4.name, data['name']) - - def test_create_consoleporttemplate_bulk(self): - - data = [ - { - 'device_type': self.devicetype.pk, - 'name': 'Test CP Template 4', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test CP Template 5', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test CP Template 6', - }, - ] - - url = reverse('dcim-api:consoleporttemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ConsolePortTemplate.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_consoleporttemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test CP Template X', - } - - url = reverse('dcim-api:consoleporttemplate-detail', kwargs={'pk': self.consoleporttemplate1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(ConsolePortTemplate.objects.count(), 3) - consoleporttemplate1 = ConsolePortTemplate.objects.get(pk=response.data['id']) - self.assertEqual(consoleporttemplate1.name, data['name']) - - def test_delete_consoleporttemplate(self): - - url = reverse('dcim-api:consoleporttemplate-detail', kwargs={'pk': self.consoleporttemplate1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(ConsolePortTemplate.objects.count(), 2) - - -class ConsoleServerPortTemplateTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - self.devicetype = DeviceType.objects.create( - manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1' - ) - self.consoleserverporttemplate1 = ConsoleServerPortTemplate.objects.create( - device_type=self.devicetype, name='Test CSP Template 1' - ) - self.consoleserverporttemplate2 = ConsoleServerPortTemplate.objects.create( - device_type=self.devicetype, name='Test CSP Template 2' - ) - self.consoleserverporttemplate3 = ConsoleServerPortTemplate.objects.create( - device_type=self.devicetype, name='Test CSP Template 3' - ) - - def test_get_consoleserverporttemplate(self): - - url = reverse('dcim-api:consoleserverporttemplate-detail', kwargs={'pk': self.consoleserverporttemplate1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.consoleserverporttemplate1.name) - - def test_list_consoleserverporttemplates(self): - - url = reverse('dcim-api:consoleserverporttemplate-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_consoleserverporttemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test CSP Template 4', - } - - url = reverse('dcim-api:consoleserverporttemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ConsoleServerPortTemplate.objects.count(), 4) - consoleserverporttemplate4 = ConsoleServerPortTemplate.objects.get(pk=response.data['id']) - self.assertEqual(consoleserverporttemplate4.device_type_id, data['device_type']) - self.assertEqual(consoleserverporttemplate4.name, data['name']) - - def test_create_consoleserverporttemplate_bulk(self): - - data = [ - { - 'device_type': self.devicetype.pk, - 'name': 'Test CSP Template 4', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test CSP Template 5', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test CSP Template 6', - }, - ] - - url = reverse('dcim-api:consoleserverporttemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ConsoleServerPortTemplate.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_consoleserverporttemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test CSP Template X', - } - - url = reverse('dcim-api:consoleserverporttemplate-detail', kwargs={'pk': self.consoleserverporttemplate1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(ConsoleServerPortTemplate.objects.count(), 3) - consoleserverporttemplate1 = ConsoleServerPortTemplate.objects.get(pk=response.data['id']) - self.assertEqual(consoleserverporttemplate1.name, data['name']) - - def test_delete_consoleserverporttemplate(self): - - url = reverse('dcim-api:consoleserverporttemplate-detail', kwargs={'pk': self.consoleserverporttemplate1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(ConsoleServerPortTemplate.objects.count(), 2) - - -class PowerPortTemplateTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - self.devicetype = DeviceType.objects.create( - manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1' - ) - self.powerporttemplate1 = PowerPortTemplate.objects.create( - device_type=self.devicetype, name='Test PP Template 1' - ) - self.powerporttemplate2 = PowerPortTemplate.objects.create( - device_type=self.devicetype, name='Test PP Template 2' - ) - self.powerporttemplate3 = PowerPortTemplate.objects.create( - device_type=self.devicetype, name='Test PP Template 3' - ) - - def test_get_powerporttemplate(self): - - url = reverse('dcim-api:powerporttemplate-detail', kwargs={'pk': self.powerporttemplate1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.powerporttemplate1.name) - - def test_list_powerporttemplates(self): - - url = reverse('dcim-api:powerporttemplate-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_powerporttemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test PP Template 4', - } - - url = reverse('dcim-api:powerporttemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerPortTemplate.objects.count(), 4) - powerporttemplate4 = PowerPortTemplate.objects.get(pk=response.data['id']) - self.assertEqual(powerporttemplate4.device_type_id, data['device_type']) - self.assertEqual(powerporttemplate4.name, data['name']) - - def test_create_powerporttemplate_bulk(self): - - data = [ - { - 'device_type': self.devicetype.pk, - 'name': 'Test PP Template 4', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test PP Template 5', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test PP Template 6', - }, - ] - - url = reverse('dcim-api:powerporttemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerPortTemplate.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_powerporttemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test PP Template X', - } - - url = reverse('dcim-api:powerporttemplate-detail', kwargs={'pk': self.powerporttemplate1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(PowerPortTemplate.objects.count(), 3) - powerporttemplate1 = PowerPortTemplate.objects.get(pk=response.data['id']) - self.assertEqual(powerporttemplate1.name, data['name']) - - def test_delete_powerporttemplate(self): - - url = reverse('dcim-api:powerporttemplate-detail', kwargs={'pk': self.powerporttemplate1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(PowerPortTemplate.objects.count(), 2) - - -class PowerOutletTemplateTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - self.devicetype = DeviceType.objects.create( - manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1' - ) - self.poweroutlettemplate1 = PowerOutletTemplate.objects.create( - device_type=self.devicetype, name='Test PO Template 1' - ) - self.poweroutlettemplate2 = PowerOutletTemplate.objects.create( - device_type=self.devicetype, name='Test PO Template 2' - ) - self.poweroutlettemplate3 = PowerOutletTemplate.objects.create( - device_type=self.devicetype, name='Test PO Template 3' - ) - - def test_get_poweroutlettemplate(self): - - url = reverse('dcim-api:poweroutlettemplate-detail', kwargs={'pk': self.poweroutlettemplate1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.poweroutlettemplate1.name) - - def test_list_poweroutlettemplates(self): - - url = reverse('dcim-api:poweroutlettemplate-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_poweroutlettemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test PO Template 4', - } - - url = reverse('dcim-api:poweroutlettemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerOutletTemplate.objects.count(), 4) - poweroutlettemplate4 = PowerOutletTemplate.objects.get(pk=response.data['id']) - self.assertEqual(poweroutlettemplate4.device_type_id, data['device_type']) - self.assertEqual(poweroutlettemplate4.name, data['name']) - - def test_create_poweroutlettemplate_bulk(self): - - data = [ - { - 'device_type': self.devicetype.pk, - 'name': 'Test PO Template 4', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test PO Template 5', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test PO Template 6', - }, - ] - - url = reverse('dcim-api:poweroutlettemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerOutletTemplate.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_poweroutlettemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test PO Template X', - } - - url = reverse('dcim-api:poweroutlettemplate-detail', kwargs={'pk': self.poweroutlettemplate1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(PowerOutletTemplate.objects.count(), 3) - poweroutlettemplate1 = PowerOutletTemplate.objects.get(pk=response.data['id']) - self.assertEqual(poweroutlettemplate1.name, data['name']) - - def test_delete_poweroutlettemplate(self): - - url = reverse('dcim-api:poweroutlettemplate-detail', kwargs={'pk': self.poweroutlettemplate1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(PowerOutletTemplate.objects.count(), 2) - - -class InterfaceTemplateTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - self.devicetype = DeviceType.objects.create( - manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1' - ) - self.interfacetemplate1 = InterfaceTemplate.objects.create( - device_type=self.devicetype, name='Test Interface Template 1', type='1000base-t' - ) - self.interfacetemplate2 = InterfaceTemplate.objects.create( - device_type=self.devicetype, name='Test Interface Template 2', type='1000base-t' - ) - self.interfacetemplate3 = InterfaceTemplate.objects.create( - device_type=self.devicetype, name='Test Interface Template 3', type='1000base-t' - ) - - def test_get_interfacetemplate(self): - - url = reverse('dcim-api:interfacetemplate-detail', kwargs={'pk': self.interfacetemplate1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.interfacetemplate1.name) - - def test_list_interfacetemplates(self): - - url = reverse('dcim-api:interfacetemplate-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_interfacetemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test Interface Template 4', - 'type': '1000base-t', - } - - url = reverse('dcim-api:interfacetemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(InterfaceTemplate.objects.count(), 4) - interfacetemplate4 = InterfaceTemplate.objects.get(pk=response.data['id']) - self.assertEqual(interfacetemplate4.device_type_id, data['device_type']) - self.assertEqual(interfacetemplate4.name, data['name']) - - def test_create_interfacetemplate_bulk(self): - - data = [ - { - 'device_type': self.devicetype.pk, - 'name': 'Test Interface Template 4', - 'type': '1000base-t', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test Interface Template 5', - 'type': '1000base-t', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test Interface Template 6', - 'type': '1000base-t', - }, - ] - - url = reverse('dcim-api:interfacetemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(InterfaceTemplate.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_interfacetemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test Interface Template X', - 'type': '1000base-x-gbic', - } - - url = reverse('dcim-api:interfacetemplate-detail', kwargs={'pk': self.interfacetemplate1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(InterfaceTemplate.objects.count(), 3) - interfacetemplate1 = InterfaceTemplate.objects.get(pk=response.data['id']) - self.assertEqual(interfacetemplate1.name, data['name']) - - def test_delete_interfacetemplate(self): - - url = reverse('dcim-api:interfacetemplate-detail', kwargs={'pk': self.interfacetemplate1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(InterfaceTemplate.objects.count(), 2) - - -class DeviceBayTemplateTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - self.devicetype = DeviceType.objects.create( - manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1' - ) - self.devicebaytemplate1 = DeviceBayTemplate.objects.create( - device_type=self.devicetype, name='Test Device Bay Template 1' - ) - self.devicebaytemplate2 = DeviceBayTemplate.objects.create( - device_type=self.devicetype, name='Test Device Bay Template 2' - ) - self.devicebaytemplate3 = DeviceBayTemplate.objects.create( - device_type=self.devicetype, name='Test Device Bay Template 3' - ) - - def test_get_devicebaytemplate(self): - - url = reverse('dcim-api:devicebaytemplate-detail', kwargs={'pk': self.devicebaytemplate1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.devicebaytemplate1.name) - - def test_list_devicebaytemplates(self): - - url = reverse('dcim-api:devicebaytemplate-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_devicebaytemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test Device Bay Template 4', - } - - url = reverse('dcim-api:devicebaytemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(DeviceBayTemplate.objects.count(), 4) - devicebaytemplate4 = DeviceBayTemplate.objects.get(pk=response.data['id']) - self.assertEqual(devicebaytemplate4.device_type_id, data['device_type']) - self.assertEqual(devicebaytemplate4.name, data['name']) - - def test_create_devicebaytemplate_bulk(self): - - data = [ - { - 'device_type': self.devicetype.pk, - 'name': 'Test Device Bay Template 4', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test Device Bay Template 5', - }, - { - 'device_type': self.devicetype.pk, - 'name': 'Test Device Bay Template 6', - }, - ] - - url = reverse('dcim-api:devicebaytemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(DeviceBayTemplate.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_devicebaytemplate(self): - - data = { - 'device_type': self.devicetype.pk, - 'name': 'Test Device Bay Template X', - } - - url = reverse('dcim-api:devicebaytemplate-detail', kwargs={'pk': self.devicebaytemplate1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(DeviceBayTemplate.objects.count(), 3) - devicebaytemplate1 = DeviceBayTemplate.objects.get(pk=response.data['id']) - self.assertEqual(devicebaytemplate1.name, data['name']) - - def test_delete_devicebaytemplate(self): - - url = reverse('dcim-api:devicebaytemplate-detail', kwargs={'pk': self.devicebaytemplate1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(DeviceBayTemplate.objects.count(), 2) - - -class DeviceRoleTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.devicerole1 = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' - ) - self.devicerole2 = DeviceRole.objects.create( - name='Test Device Role 2', slug='test-device-role-2', color='00ff00' - ) - self.devicerole3 = DeviceRole.objects.create( - name='Test Device Role 3', slug='test-device-role-3', color='0000ff' - ) - - def test_get_devicerole(self): - - url = reverse('dcim-api:devicerole-detail', kwargs={'pk': self.devicerole1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.devicerole1.name) - - def test_list_deviceroles(self): - - url = reverse('dcim-api:devicerole-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_deviceroles_brief(self): - - url = reverse('dcim-api:devicerole-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['device_count', 'id', 'name', 'slug', 'url', 'virtualmachine_count'] - ) - - def test_create_devicerole(self): - - data = { - 'name': 'Test Device Role 4', - 'slug': 'test-device-role-4', - 'color': 'ffff00', - } - - url = reverse('dcim-api:devicerole-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(DeviceRole.objects.count(), 4) - devicerole4 = DeviceRole.objects.get(pk=response.data['id']) - self.assertEqual(devicerole4.name, data['name']) - self.assertEqual(devicerole4.slug, data['slug']) - self.assertEqual(devicerole4.color, data['color']) - - def test_create_devicerole_bulk(self): - - data = [ - { - 'name': 'Test Device Role 4', - 'slug': 'test-device-role-4', - 'color': 'ffff00', - }, - { - 'name': 'Test Device Role 5', - 'slug': 'test-device-role-5', - 'color': 'ffff00', - }, - { - 'name': 'Test Device Role 6', - 'slug': 'test-device-role-6', - 'color': 'ffff00', - }, - ] - - url = reverse('dcim-api:devicerole-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(DeviceRole.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_devicerole(self): - - data = { - 'name': 'Test Device Role X', - 'slug': 'test-device-role-x', - 'color': '00ffff', - } - - url = reverse('dcim-api:devicerole-detail', kwargs={'pk': self.devicerole1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(DeviceRole.objects.count(), 3) - devicerole1 = DeviceRole.objects.get(pk=response.data['id']) - self.assertEqual(devicerole1.name, data['name']) - self.assertEqual(devicerole1.slug, data['slug']) - self.assertEqual(devicerole1.color, data['color']) - - def test_delete_devicerole(self): - - url = reverse('dcim-api:devicerole-detail', kwargs={'pk': self.devicerole1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(DeviceRole.objects.count(), 2) - - -class PlatformTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.platform1 = Platform.objects.create(name='Test Platform 1', slug='test-platform-1') - self.platform2 = Platform.objects.create(name='Test Platform 2', slug='test-platform-2') - self.platform3 = Platform.objects.create(name='Test Platform 3', slug='test-platform-3') - - def test_get_platform(self): - - url = reverse('dcim-api:platform-detail', kwargs={'pk': self.platform1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.platform1.name) - - def test_list_platforms(self): - - url = reverse('dcim-api:platform-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_platforms_brief(self): - - url = reverse('dcim-api:platform-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['device_count', 'id', 'name', 'slug', 'url', 'virtualmachine_count'] - ) - - def test_create_platform(self): - - data = { - 'name': 'Test Platform 4', - 'slug': 'test-platform-4', - } - - url = reverse('dcim-api:platform-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Platform.objects.count(), 4) - platform4 = Platform.objects.get(pk=response.data['id']) - self.assertEqual(platform4.name, data['name']) - self.assertEqual(platform4.slug, data['slug']) - - def test_create_platform_bulk(self): - - data = [ - { - 'name': 'Test Platform 4', - 'slug': 'test-platform-4', - }, - { - 'name': 'Test Platform 5', - 'slug': 'test-platform-5', - }, - { - 'name': 'Test Platform 6', - 'slug': 'test-platform-6', - }, - ] - - url = reverse('dcim-api:platform-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Platform.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_platform(self): - - data = { - 'name': 'Test Platform X', - 'slug': 'test-platform-x', - } - - url = reverse('dcim-api:platform-detail', kwargs={'pk': self.platform1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Platform.objects.count(), 3) - platform1 = Platform.objects.get(pk=response.data['id']) - self.assertEqual(platform1.name, data['name']) - self.assertEqual(platform1.slug, data['slug']) - - def test_delete_platform(self): - - url = reverse('dcim-api:platform-detail', kwargs={'pk': self.platform1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Platform.objects.count(), 2) - - -class DeviceTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.site2 = Site.objects.create(name='Test Site 2', slug='test-site-2') - self.rack1 = Rack.objects.create(name='Test Rack 1', site=self.site1, u_height=48) + @classmethod + def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - self.devicetype1 = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1' - ) - self.devicetype2 = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type 2', slug='test-device-type-2' - ) - self.devicerole1 = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' - ) - self.devicerole2 = DeviceRole.objects.create( - name='Test Device Role 2', slug='test-device-role-2', color='00ff00' - ) - cluster_type = ClusterType.objects.create(name='Test Cluster Type 1', slug='test-cluster-type-1') - self.cluster1 = Cluster.objects.create(name='Test Cluster 1', type=cluster_type) - self.device1 = Device.objects.create( - device_type=self.devicetype1, - device_role=self.devicerole1, - name='Test Device 1', - site=self.site1, - cluster=self.cluster1 - ) - self.device2 = Device.objects.create( - device_type=self.devicetype1, - device_role=self.devicerole1, - name='Test Device 2', - site=self.site1, - cluster=self.cluster1 - ) - self.device3 = Device.objects.create( - device_type=self.devicetype1, - device_role=self.devicerole1, - name='Test Device 3', - site=self.site1, - cluster=self.cluster1 - ) - self.device_with_context_data = Device.objects.create( - device_type=self.devicetype1, - device_role=self.devicerole1, - name='Device with context data', - site=self.site1, - local_context_data={ - 'A': 1, - 'B': 2 - } + devicetype = DeviceType.objects.create( + manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' ) - def test_get_device(self): + console_port_templates = ( + ConsolePortTemplate(device_type=devicetype, name='Console Port Template 1'), + ConsolePortTemplate(device_type=devicetype, name='Console Port Template 2'), + ConsolePortTemplate(device_type=devicetype, name='Console Port Template 3'), + ) + ConsolePortTemplate.objects.bulk_create(console_port_templates) - url = reverse('dcim-api:device-detail', kwargs={'pk': self.device1.pk}) - response = self.client.get(url, **self.header) + cls.create_data = [ + { + 'device_type': devicetype.pk, + 'name': 'Console Port Template 4', + }, + { + 'device_type': devicetype.pk, + 'name': 'Console Port Template 5', + }, + { + 'device_type': devicetype.pk, + 'name': 'Console Port Template 6', + }, + ] - self.assertEqual(response.data['name'], self.device1.name) - self.assertEqual(response.data['device_role']['id'], self.devicerole1.pk) - self.assertEqual(response.data['cluster']['id'], self.cluster1.pk) + +class ConsoleServerPortTemplateTest(APIViewTestCases.APIViewTestCase): + model = ConsoleServerPortTemplate + brief_fields = ['id', 'name', 'url'] + + @classmethod + def setUpTestData(cls): + manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') + devicetype = DeviceType.objects.create( + manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' + ) + + console_server_port_templates = ( + ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 1'), + ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 2'), + ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 3'), + ) + ConsoleServerPortTemplate.objects.bulk_create(console_server_port_templates) + + cls.create_data = [ + { + 'device_type': devicetype.pk, + 'name': 'Console Server Port Template 4', + }, + { + 'device_type': devicetype.pk, + 'name': 'Console Server Port Template 5', + }, + { + 'device_type': devicetype.pk, + 'name': 'Console Server Port Template 6', + }, + ] + + +class PowerPortTemplateTest(APIViewTestCases.APIViewTestCase): + model = PowerPortTemplate + brief_fields = ['id', 'name', 'url'] + + @classmethod + def setUpTestData(cls): + manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') + devicetype = DeviceType.objects.create( + manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' + ) + + power_port_templates = ( + PowerPortTemplate(device_type=devicetype, name='Power Port Template 1'), + PowerPortTemplate(device_type=devicetype, name='Power Port Template 2'), + PowerPortTemplate(device_type=devicetype, name='Power Port Template 3'), + ) + PowerPortTemplate.objects.bulk_create(power_port_templates) + + cls.create_data = [ + { + 'device_type': devicetype.pk, + 'name': 'Power Port Template 4', + }, + { + 'device_type': devicetype.pk, + 'name': 'Power Port Template 5', + }, + { + 'device_type': devicetype.pk, + 'name': 'Power Port Template 6', + }, + ] + + +class PowerOutletTemplateTest(APIViewTestCases.APIViewTestCase): + model = PowerOutletTemplate + brief_fields = ['id', 'name', 'url'] + + @classmethod + def setUpTestData(cls): + manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') + devicetype = DeviceType.objects.create( + manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' + ) + + power_outlet_templates = ( + PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 1'), + PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 2'), + PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 3'), + ) + PowerOutletTemplate.objects.bulk_create(power_outlet_templates) + + cls.create_data = [ + { + 'device_type': devicetype.pk, + 'name': 'Power Outlet Template 4', + }, + { + 'device_type': devicetype.pk, + 'name': 'Power Outlet Template 5', + }, + { + 'device_type': devicetype.pk, + 'name': 'Power Outlet Template 6', + }, + ] + + +class InterfaceTemplateTest(APIViewTestCases.APIViewTestCase): + model = InterfaceTemplate + brief_fields = ['id', 'name', 'url'] + + @classmethod + def setUpTestData(cls): + manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') + devicetype = DeviceType.objects.create( + manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' + ) + + interface_templates = ( + InterfaceTemplate(device_type=devicetype, name='Interface Template 1', type='1000base-t'), + InterfaceTemplate(device_type=devicetype, name='Interface Template 2', type='1000base-t'), + InterfaceTemplate(device_type=devicetype, name='Interface Template 3', type='1000base-t'), + ) + InterfaceTemplate.objects.bulk_create(interface_templates) + + cls.create_data = [ + { + 'device_type': devicetype.pk, + 'name': 'Interface Template 4', + 'type': '1000base-t', + }, + { + 'device_type': devicetype.pk, + 'name': 'Interface Template 5', + 'type': '1000base-t', + }, + { + 'device_type': devicetype.pk, + 'name': 'Interface Template 6', + 'type': '1000base-t', + }, + ] + + +class DeviceBayTemplateTest(APIViewTestCases.APIViewTestCase): + model = DeviceBayTemplate + brief_fields = ['id', 'name', 'url'] + + @classmethod + def setUpTestData(cls): + manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') + devicetype = DeviceType.objects.create( + manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' + ) + + device_bay_templates = ( + DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 1'), + DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 2'), + DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 3'), + ) + DeviceBayTemplate.objects.bulk_create(device_bay_templates) + + cls.create_data = [ + { + 'device_type': devicetype.pk, + 'name': 'Device Bay Template 4', + }, + { + 'device_type': devicetype.pk, + 'name': 'Device Bay Template 5', + }, + { + 'device_type': devicetype.pk, + 'name': 'Device Bay Template 6', + }, + ] + + +class DeviceRoleTest(APIViewTestCases.APIViewTestCase): + model = DeviceRole + brief_fields = ['device_count', 'id', 'name', 'slug', 'url', 'virtualmachine_count'] + create_data = [ + { + 'name': 'Device Role 4', + 'slug': 'device-role-4', + 'color': 'ffff00', + }, + { + 'name': 'Device Role 5', + 'slug': 'device-role-5', + 'color': 'ffff00', + }, + { + 'name': 'Device Role 6', + 'slug': 'device-role-6', + 'color': 'ffff00', + }, + ] + + @classmethod + def setUpTestData(cls): + + device_roles = ( + DeviceRole(name='Device Role 1', slug='device-role-1', color='ff0000'), + DeviceRole(name='Device Role 2', slug='device-role-2', color='00ff00'), + DeviceRole(name='Device Role 3', slug='device-role-3', color='0000ff'), + ) + DeviceRole.objects.bulk_create(device_roles) + + +class PlatformTest(APIViewTestCases.APIViewTestCase): + model = Platform + brief_fields = ['device_count', 'id', 'name', 'slug', 'url', 'virtualmachine_count'] + create_data = [ + { + 'name': 'Platform 4', + 'slug': 'platform-4', + }, + { + 'name': 'Platform 5', + 'slug': 'platform-5', + }, + { + 'name': 'Platform 6', + 'slug': 'platform-6', + }, + ] + + @classmethod + def setUpTestData(cls): + + platforms = ( + Platform(name='Platform 1', slug='platform-1'), + Platform(name='Platform 2', slug='platform-2'), + Platform(name='Platform 3', slug='platform-3'), + ) + Platform.objects.bulk_create(platforms) + + +class DeviceTest(APIViewTestCases.APIViewTestCase): + model = Device + brief_fields = ['display_name', 'id', 'name', 'url'] + + @classmethod + def setUpTestData(cls): + + sites = ( + Site(name='Site 1', slug='site-1'), + Site(name='Site 2', slug='site-2'), + ) + Site.objects.bulk_create(sites) + + racks = ( + Rack(name='Rack 1', site=sites[0]), + Rack(name='Rack 2', site=sites[1]), + ) + Rack.objects.bulk_create(racks) + + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + + device_types = ( + DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'), + DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'), + ) + DeviceType.objects.bulk_create(device_types) + + device_roles = ( + DeviceRole(name='Device Role 1', slug='device-role-1', color='ff0000'), + DeviceRole(name='Device Role 2', slug='device-role-2', color='00ff00'), + ) + DeviceRole.objects.bulk_create(device_roles) + + cluster_type = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') + + clusters = ( + Cluster(name='Cluster 1', type=cluster_type), + Cluster(name='Cluster 2', type=cluster_type), + ) + Cluster.objects.bulk_create(clusters) + + devices = ( + Device( + device_type=device_types[0], + device_role=device_roles[0], + name='Device 1', + site=sites[0], + rack=racks[0], + cluster=clusters[0], + local_context_data={'A': 1} + ), + Device( + device_type=device_types[0], + device_role=device_roles[0], + name='Device 2', + site=sites[0], + rack=racks[0], + cluster=clusters[0], + local_context_data={'B': 2} + ), + Device( + device_type=device_types[0], + device_role=device_roles[0], + name='Device 3', + site=sites[0], + rack=racks[0], + cluster=clusters[0], + local_context_data={'C': 3} + ), + ) + Device.objects.bulk_create(devices) + + cls.create_data = [ + { + 'device_type': device_types[1].pk, + 'device_role': device_roles[1].pk, + 'name': 'Test Device 4', + 'site': sites[1].pk, + 'rack': racks[1].pk, + 'cluster': clusters[1].pk, + }, + { + 'device_type': device_types[1].pk, + 'device_role': device_roles[1].pk, + 'name': 'Test Device 5', + 'site': sites[1].pk, + 'rack': racks[1].pk, + 'cluster': clusters[1].pk, + }, + { + 'device_type': device_types[1].pk, + 'device_role': device_roles[1].pk, + 'name': 'Test Device 6', + 'site': sites[1].pk, + 'rack': racks[1].pk, + 'cluster': clusters[1].pk, + }, + ] def test_get_device_graphs(self): + """ + Test retrieval of Graphs assigned to Devices. + """ + ct = ContentType.objects.get_for_model(Device) + graphs = ( + Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?device={{ obj.name }}&foo=1'), + Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?device={{ obj.name }}&foo=2'), + Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?device={{ obj.name }}&foo=3'), + ) + Graph.objects.bulk_create(graphs) - device_ct = ContentType.objects.get_for_model(Device) - self.graph1 = Graph.objects.create( - type=device_ct, - name='Test Graph 1', - source='http://example.com/graphs.py?device={{ obj.name }}&foo=1' - ) - self.graph2 = Graph.objects.create( - type=device_ct, - name='Test Graph 2', - source='http://example.com/graphs.py?device={{ obj.name }}&foo=2' - ) - self.graph3 = Graph.objects.create( - type=device_ct, - name='Test Graph 3', - source='http://example.com/graphs.py?device={{ obj.name }}&foo=3' - ) - - url = reverse('dcim-api:device-graphs', kwargs={'pk': self.device1.pk}) + url = reverse('dcim-api:device-graphs', kwargs={'pk': Device.objects.first().pk}) response = self.client.get(url, **self.header) self.assertEqual(len(response.data), 3) - self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?device=Test Device 1&foo=1') - - def test_list_devices(self): - - url = reverse('dcim-api:device-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 4) - - def test_list_devices_brief(self): - - url = reverse('dcim-api:device-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['display_name', 'id', 'name', 'url'] - ) - - def test_create_device(self): - - data = { - 'device_type': self.devicetype1.pk, - 'device_role': self.devicerole1.pk, - 'name': 'Test Device 4', - 'site': self.site1.pk, - 'rack': self.rack1.pk, - 'face': DeviceFaceChoices.FACE_FRONT, - 'position': 1, - 'cluster': self.cluster1.pk, - } - - url = reverse('dcim-api:device-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Device.objects.count(), 5) - device4 = Device.objects.get(pk=response.data['id']) - self.assertEqual(device4.device_type_id, data['device_type']) - self.assertEqual(device4.device_role_id, data['device_role']) - self.assertEqual(device4.name, data['name']) - self.assertEqual(device4.site.pk, data['site']) - self.assertEqual(device4.cluster.pk, data['cluster']) - - def test_create_device_bulk(self): - - data = [ - { - 'device_type': self.devicetype1.pk, - 'device_role': self.devicerole1.pk, - 'name': 'Test Device 4', - 'site': self.site1.pk, - }, - { - 'device_type': self.devicetype1.pk, - 'device_role': self.devicerole1.pk, - 'name': 'Test Device 5', - 'site': self.site1.pk, - }, - { - 'device_type': self.devicetype1.pk, - 'device_role': self.devicerole1.pk, - 'name': 'Test Device 6', - 'site': self.site1.pk, - }, - ] - - url = reverse('dcim-api:device-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Device.objects.count(), 7) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_device(self): - - interface = Interface.objects.create(name='Test Interface 1', device=self.device1) - ip4_address = IPAddress.objects.create(address=IPNetwork('192.0.2.1/24'), interface=interface) - ip6_address = IPAddress.objects.create(address=IPNetwork('2001:db8::1/64'), interface=interface) - - data = { - 'device_type': self.devicetype2.pk, - 'device_role': self.devicerole2.pk, - 'name': 'Test Device X', - 'site': self.site2.pk, - 'primary_ip4': ip4_address.pk, - 'primary_ip6': ip6_address.pk, - } - - url = reverse('dcim-api:device-detail', kwargs={'pk': self.device1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Device.objects.count(), 4) - device1 = Device.objects.get(pk=response.data['id']) - self.assertEqual(device1.device_type_id, data['device_type']) - self.assertEqual(device1.device_role_id, data['device_role']) - self.assertEqual(device1.name, data['name']) - self.assertEqual(device1.site.pk, data['site']) - self.assertEqual(device1.primary_ip4.pk, data['primary_ip4']) - self.assertEqual(device1.primary_ip6.pk, data['primary_ip6']) - - def test_delete_device(self): - - url = reverse('dcim-api:device-detail', kwargs={'pk': self.device1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Device.objects.count(), 3) + self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?device=Device 1&foo=1') def test_config_context_included_by_default_in_list_view(self): - + """ + Check that config context data is included by default in the devices list. + """ url = reverse('dcim-api:device-list') + '?slug=device-with-context-data' response = self.client.get(url, **self.header) self.assertEqual(response.data['results'][0].get('config_context', {}).get('A'), 1) def test_config_context_excluded(self): - + """ + Check that config context data can be excluded by passing ?exclude=config_context. + """ url = reverse('dcim-api:device-list') + '?exclude=config_context' response = self.client.get(url, **self.header) self.assertFalse('config_context' in response.data['results'][0]) def test_unique_name_per_site_constraint(self): - + """ + Check that creating a device with a duplicate name within a site fails. + """ + device = Device.objects.first() data = { - 'device_type': self.devicetype1.pk, - 'device_role': self.devicerole1.pk, - 'name': 'Test Device 1', - 'site': self.site1.pk, + 'device_type': device.device_type.pk, + 'device_role': device.device_role.pk, + 'site': device.site.pk, + 'name': device.name, } url = reverse('dcim-api:device-list') @@ -2037,1401 +826,578 @@ class DeviceTest(APITestCase): self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) -class ConsolePortTest(APITestCase): +class ConsolePortTest(APIViewTestCases.APIViewTestCase): + model = ConsolePort + brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url'] - def setUp(self): - - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') + @classmethod + def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1' + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') + site = Site.objects.create(name='Site 1', slug='site-1') + devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000') + device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site) + + console_ports = ( + ConsolePort(device=device, name='Console Port 1'), + ConsolePort(device=device, name='Console Port 2'), + ConsolePort(device=device, name='Console Port 3'), ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' - ) - self.device = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site - ) - self.consoleport1 = ConsolePort.objects.create(device=self.device, name='Test Console Port 1') - self.consoleport2 = ConsolePort.objects.create(device=self.device, name='Test Console Port 2') - self.consoleport3 = ConsolePort.objects.create(device=self.device, name='Test Console Port 3') + ConsolePort.objects.bulk_create(console_ports) - def test_get_consoleport(self): - - url = reverse('dcim-api:consoleport-detail', kwargs={'pk': self.consoleport1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.consoleport1.name) - - def test_list_consoleports(self): - - url = reverse('dcim-api:consoleport-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_consoleports_brief(self): - - url = reverse('dcim-api:consoleport-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['cable', 'connection_status', 'device', 'id', 'name', 'url'] - ) - - def test_create_consoleport(self): - - data = { - 'device': self.device.pk, - 'name': 'Test Console Port 4', - } - - url = reverse('dcim-api:consoleport-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ConsolePort.objects.count(), 4) - consoleport4 = ConsolePort.objects.get(pk=response.data['id']) - self.assertEqual(consoleport4.device_id, data['device']) - self.assertEqual(consoleport4.name, data['name']) - - def test_create_consoleport_bulk(self): - - data = [ + cls.create_data = [ { - 'device': self.device.pk, - 'name': 'Test Console Port 4', + 'device': device.pk, + 'name': 'Console Port 4', }, { - 'device': self.device.pk, - 'name': 'Test Console Port 5', + 'device': device.pk, + 'name': 'Console Port 5', }, { - 'device': self.device.pk, - 'name': 'Test Console Port 6', + 'device': device.pk, + 'name': 'Console Port 6', }, ] - url = reverse('dcim-api:consoleport-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ConsolePort.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_consoleport(self): - - consoleserverport = ConsoleServerPort.objects.create(device=self.device, name='Test CS Port 1') - - data = { - 'device': self.device.pk, - 'name': 'Test Console Port X', - } - - url = reverse('dcim-api:consoleport-detail', kwargs={'pk': self.consoleport1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(ConsolePort.objects.count(), 3) - consoleport1 = ConsolePort.objects.get(pk=response.data['id']) - self.assertEqual(consoleport1.name, data['name']) - - def test_delete_consoleport(self): - - url = reverse('dcim-api:consoleport-detail', kwargs={'pk': self.consoleport1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(ConsolePort.objects.count(), 2) - def test_trace_consoleport(self): - + """ + Test tracing a ConsolePort cable. + """ + consoleport = ConsolePort.objects.first() peer_device = Device.objects.create( site=Site.objects.first(), device_type=DeviceType.objects.first(), device_role=DeviceRole.objects.first(), name='Peer Device' ) - console_server_port = ConsoleServerPort.objects.create( + consoleserverport = ConsoleServerPort.objects.create( device=peer_device, name='Console Server Port 1' ) - cable = Cable(termination_a=self.consoleport1, termination_b=console_server_port, label='Cable 1') + cable = Cable(termination_a=consoleport, termination_b=consoleserverport, label='Cable 1') cable.save() - url = reverse('dcim-api:consoleport-trace', kwargs={'pk': self.consoleport1.pk}) + url = reverse('dcim-api:consoleport-trace', kwargs={'pk': consoleport.pk}) response = self.client.get(url, **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(len(response.data), 1) segment1 = response.data[0] - self.assertEqual(segment1[0]['name'], self.consoleport1.name) + self.assertEqual(segment1[0]['name'], consoleport.name) self.assertEqual(segment1[1]['label'], cable.label) - self.assertEqual(segment1[2]['name'], console_server_port.name) + self.assertEqual(segment1[2]['name'], consoleserverport.name) -class ConsoleServerPortTest(APITestCase): +class ConsoleServerPortTest(APIViewTestCases.APIViewTestCase): + model = ConsoleServerPort + brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url'] - def setUp(self): - - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') + @classmethod + def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1' + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') + site = Site.objects.create(name='Site 1', slug='site-1') + devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000') + device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site) + + console_server_ports = ( + ConsoleServerPort(device=device, name='Console Server Port 1'), + ConsoleServerPort(device=device, name='Console Server Port 2'), + ConsoleServerPort(device=device, name='Console Server Port 3'), ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' - ) - self.device = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site - ) - self.consoleserverport1 = ConsoleServerPort.objects.create(device=self.device, name='Test CS Port 1') - self.consoleserverport2 = ConsoleServerPort.objects.create(device=self.device, name='Test CS Port 2') - self.consoleserverport3 = ConsoleServerPort.objects.create(device=self.device, name='Test CS Port 3') + ConsoleServerPort.objects.bulk_create(console_server_ports) - def test_get_consoleserverport(self): - - url = reverse('dcim-api:consoleserverport-detail', kwargs={'pk': self.consoleserverport1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.consoleserverport1.name) - - def test_list_consoleserverports(self): - - url = reverse('dcim-api:consoleserverport-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_consoleserverports_brief(self): - - url = reverse('dcim-api:consoleserverport-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['cable', 'connection_status', 'device', 'id', 'name', 'url'] - ) - - def test_create_consoleserverport(self): - - data = { - 'device': self.device.pk, - 'name': 'Test CS Port 4', - } - - url = reverse('dcim-api:consoleserverport-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ConsoleServerPort.objects.count(), 4) - consoleserverport4 = ConsoleServerPort.objects.get(pk=response.data['id']) - self.assertEqual(consoleserverport4.device_id, data['device']) - self.assertEqual(consoleserverport4.name, data['name']) - - def test_create_consoleserverport_bulk(self): - - data = [ + cls.create_data = [ { - 'device': self.device.pk, - 'name': 'Test CS Port 4', + 'device': device.pk, + 'name': 'Console Server Port 4', }, { - 'device': self.device.pk, - 'name': 'Test CS Port 5', + 'device': device.pk, + 'name': 'Console Server Port 5', }, { - 'device': self.device.pk, - 'name': 'Test CS Port 6', + 'device': device.pk, + 'name': 'Console Server Port 6', }, ] - url = reverse('dcim-api:consoleserverport-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ConsoleServerPort.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_consoleserverport(self): - - data = { - 'device': self.device.pk, - 'name': 'Test CS Port X', - } - - url = reverse('dcim-api:consoleserverport-detail', kwargs={'pk': self.consoleserverport1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(ConsoleServerPort.objects.count(), 3) - consoleserverport1 = ConsoleServerPort.objects.get(pk=response.data['id']) - self.assertEqual(consoleserverport1.name, data['name']) - - def test_delete_consoleserverport(self): - - url = reverse('dcim-api:consoleserverport-detail', kwargs={'pk': self.consoleserverport1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(ConsoleServerPort.objects.count(), 2) - def test_trace_consoleserverport(self): - + """ + Test tracing a ConsoleServerPort cable. + """ + consoleserverport = ConsoleServerPort.objects.first() peer_device = Device.objects.create( site=Site.objects.first(), device_type=DeviceType.objects.first(), device_role=DeviceRole.objects.first(), name='Peer Device' ) - console_port = ConsolePort.objects.create( + consoleport = ConsolePort.objects.create( device=peer_device, name='Console Port 1' ) - cable = Cable(termination_a=self.consoleserverport1, termination_b=console_port, label='Cable 1') + cable = Cable(termination_a=consoleserverport, termination_b=consoleport, label='Cable 1') cable.save() - url = reverse('dcim-api:consoleserverport-trace', kwargs={'pk': self.consoleserverport1.pk}) + url = reverse('dcim-api:consoleserverport-trace', kwargs={'pk': consoleserverport.pk}) response = self.client.get(url, **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(len(response.data), 1) segment1 = response.data[0] - self.assertEqual(segment1[0]['name'], self.consoleserverport1.name) + self.assertEqual(segment1[0]['name'], consoleserverport.name) self.assertEqual(segment1[1]['label'], cable.label) - self.assertEqual(segment1[2]['name'], console_port.name) + self.assertEqual(segment1[2]['name'], consoleport.name) -class PowerPortTest(APITestCase): +class PowerPortTest(APIViewTestCases.APIViewTestCase): + model = PowerPort + brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url'] - def setUp(self): - - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') + @classmethod + def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1' + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') + site = Site.objects.create(name='Site 1', slug='site-1') + devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000') + device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site) + + power_ports = ( + PowerPort(device=device, name='Power Port 1'), + PowerPort(device=device, name='Power Port 2'), + PowerPort(device=device, name='Power Port 3'), ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' - ) - self.device = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site - ) - self.powerport1 = PowerPort.objects.create(device=self.device, name='Test Power Port 1') - self.powerport2 = PowerPort.objects.create(device=self.device, name='Test Power Port 2') - self.powerport3 = PowerPort.objects.create(device=self.device, name='Test Power Port 3') + PowerPort.objects.bulk_create(power_ports) - def test_get_powerport(self): - - url = reverse('dcim-api:powerport-detail', kwargs={'pk': self.powerport1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.powerport1.name) - - def test_list_powerports(self): - - url = reverse('dcim-api:powerport-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_powerports_brief(self): - - url = reverse('dcim-api:powerport-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['cable', 'connection_status', 'device', 'id', 'name', 'url'] - ) - - def test_create_powerport(self): - - data = { - 'device': self.device.pk, - 'name': 'Test Power Port 4', - } - - url = reverse('dcim-api:powerport-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerPort.objects.count(), 4) - powerport4 = PowerPort.objects.get(pk=response.data['id']) - self.assertEqual(powerport4.device_id, data['device']) - self.assertEqual(powerport4.name, data['name']) - - def test_create_powerport_bulk(self): - - data = [ + cls.create_data = [ { - 'device': self.device.pk, - 'name': 'Test Power Port 4', + 'device': device.pk, + 'name': 'Power Port 4', }, { - 'device': self.device.pk, - 'name': 'Test Power Port 5', + 'device': device.pk, + 'name': 'Power Port 5', }, { - 'device': self.device.pk, - 'name': 'Test Power Port 6', + 'device': device.pk, + 'name': 'Power Port 6', }, ] - url = reverse('dcim-api:powerport-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerPort.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_powerport(self): - - poweroutlet = PowerOutlet.objects.create(device=self.device, name='Test Power Outlet 1') - - data = { - 'device': self.device.pk, - 'name': 'Test Power Port X', - } - - url = reverse('dcim-api:powerport-detail', kwargs={'pk': self.powerport1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(PowerPort.objects.count(), 3) - powerport1 = PowerPort.objects.get(pk=response.data['id']) - self.assertEqual(powerport1.name, data['name']) - - def test_delete_powerport(self): - - url = reverse('dcim-api:powerport-detail', kwargs={'pk': self.powerport1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(PowerPort.objects.count(), 2) - def test_trace_powerport(self): - + """ + Test tracing a PowerPort cable. + """ + powerport = PowerPort.objects.first() peer_device = Device.objects.create( site=Site.objects.first(), device_type=DeviceType.objects.first(), device_role=DeviceRole.objects.first(), name='Peer Device' ) - power_outlet = PowerOutlet.objects.create( + poweroutlet = PowerOutlet.objects.create( device=peer_device, name='Power Outlet 1' ) - cable = Cable(termination_a=self.powerport1, termination_b=power_outlet, label='Cable 1') + cable = Cable(termination_a=powerport, termination_b=poweroutlet, label='Cable 1') cable.save() - url = reverse('dcim-api:powerport-trace', kwargs={'pk': self.powerport1.pk}) + url = reverse('dcim-api:powerport-trace', kwargs={'pk': powerport.pk}) response = self.client.get(url, **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(len(response.data), 1) segment1 = response.data[0] - self.assertEqual(segment1[0]['name'], self.powerport1.name) + self.assertEqual(segment1[0]['name'], powerport.name) self.assertEqual(segment1[1]['label'], cable.label) - self.assertEqual(segment1[2]['name'], power_outlet.name) + self.assertEqual(segment1[2]['name'], poweroutlet.name) -class PowerOutletTest(APITestCase): +class PowerOutletTest(APIViewTestCases.APIViewTestCase): + model = PowerOutlet + brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url'] - def setUp(self): - - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') + @classmethod + def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1' + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') + site = Site.objects.create(name='Site 1', slug='site-1') + devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000') + device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site) + + power_outlets = ( + PowerOutlet(device=device, name='Power Outlet 1'), + PowerOutlet(device=device, name='Power Outlet 2'), + PowerOutlet(device=device, name='Power Outlet 3'), ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' - ) - self.device = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site - ) - self.poweroutlet1 = PowerOutlet.objects.create(device=self.device, name='Test Power Outlet 1') - self.poweroutlet2 = PowerOutlet.objects.create(device=self.device, name='Test Power Outlet 2') - self.poweroutlet3 = PowerOutlet.objects.create(device=self.device, name='Test Power Outlet 3') + PowerOutlet.objects.bulk_create(power_outlets) - def test_get_poweroutlet(self): - - url = reverse('dcim-api:poweroutlet-detail', kwargs={'pk': self.poweroutlet1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.poweroutlet1.name) - - def test_list_poweroutlets(self): - - url = reverse('dcim-api:poweroutlet-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_poweroutlets_brief(self): - - url = reverse('dcim-api:poweroutlet-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['cable', 'connection_status', 'device', 'id', 'name', 'url'] - ) - - def test_create_poweroutlet(self): - - data = { - 'device': self.device.pk, - 'name': 'Test Power Outlet 4', - } - - url = reverse('dcim-api:poweroutlet-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerOutlet.objects.count(), 4) - poweroutlet4 = PowerOutlet.objects.get(pk=response.data['id']) - self.assertEqual(poweroutlet4.device_id, data['device']) - self.assertEqual(poweroutlet4.name, data['name']) - - def test_create_poweroutlet_bulk(self): - - data = [ + cls.create_data = [ { - 'device': self.device.pk, - 'name': 'Test Power Outlet 4', + 'device': device.pk, + 'name': 'Power Outlet 4', }, { - 'device': self.device.pk, - 'name': 'Test Power Outlet 5', + 'device': device.pk, + 'name': 'Power Outlet 5', }, { - 'device': self.device.pk, - 'name': 'Test Power Outlet 6', + 'device': device.pk, + 'name': 'Power Outlet 6', }, ] - url = reverse('dcim-api:poweroutlet-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerOutlet.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_poweroutlet(self): - - data = { - 'device': self.device.pk, - 'name': 'Test Power Outlet X', - } - - url = reverse('dcim-api:poweroutlet-detail', kwargs={'pk': self.poweroutlet1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(PowerOutlet.objects.count(), 3) - poweroutlet1 = PowerOutlet.objects.get(pk=response.data['id']) - self.assertEqual(poweroutlet1.name, data['name']) - - def test_delete_poweroutlet(self): - - url = reverse('dcim-api:poweroutlet-detail', kwargs={'pk': self.poweroutlet1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(PowerOutlet.objects.count(), 2) - def test_trace_poweroutlet(self): - + """ + Test tracing a PowerOutlet cable. + """ + poweroutlet = PowerOutlet.objects.first() peer_device = Device.objects.create( site=Site.objects.first(), device_type=DeviceType.objects.first(), device_role=DeviceRole.objects.first(), name='Peer Device' ) - power_port = PowerPort.objects.create( + powerport = PowerPort.objects.create( device=peer_device, name='Power Port 1' ) - cable = Cable(termination_a=self.poweroutlet1, termination_b=power_port, label='Cable 1') + cable = Cable(termination_a=poweroutlet, termination_b=powerport, label='Cable 1') cable.save() - url = reverse('dcim-api:poweroutlet-trace', kwargs={'pk': self.poweroutlet1.pk}) + url = reverse('dcim-api:poweroutlet-trace', kwargs={'pk': poweroutlet.pk}) response = self.client.get(url, **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(len(response.data), 1) segment1 = response.data[0] - self.assertEqual(segment1[0]['name'], self.poweroutlet1.name) + self.assertEqual(segment1[0]['name'], poweroutlet.name) self.assertEqual(segment1[1]['label'], cable.label) - self.assertEqual(segment1[2]['name'], power_port.name) + self.assertEqual(segment1[2]['name'], powerport.name) -class InterfaceTest(APITestCase): +class InterfaceTest(APIViewTestCases.APIViewTestCase): + model = Interface + brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url'] - def setUp(self): - - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') + @classmethod + def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1' + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') + site = Site.objects.create(name='Site 1', slug='site-1') + devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000') + device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site) + + interfaces = ( + Interface(device=device, name='Interface 1', type='1000base-t'), + Interface(device=device, name='Interface 2', type='1000base-t'), + Interface(device=device, name='Interface 3', type='1000base-t'), ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' + Interface.objects.bulk_create(interfaces) + + vlans = ( + VLAN(name='VLAN 1', vid=1), + VLAN(name='VLAN 2', vid=2), + VLAN(name='VLAN 3', vid=3), ) - self.device = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site - ) - self.interface1 = Interface.objects.create(device=self.device, name='Test Interface 1', type='1000base-t') - self.interface2 = Interface.objects.create(device=self.device, name='Test Interface 2', type='1000base-t') - self.interface3 = Interface.objects.create(device=self.device, name='Test Interface 3', type='1000base-t') + VLAN.objects.bulk_create(vlans) - self.vlan1 = VLAN.objects.create(name="Test VLAN 1", vid=1) - self.vlan2 = VLAN.objects.create(name="Test VLAN 2", vid=2) - self.vlan3 = VLAN.objects.create(name="Test VLAN 3", vid=3) - - def test_get_interface(self): - - url = reverse('dcim-api:interface-detail', kwargs={'pk': self.interface1.pk}) - response = self.client.get(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(response.data['name'], self.interface1.name) + cls.create_data = [ + { + 'device': device.pk, + 'name': 'Interface 4', + 'type': '1000base-t', + 'mode': InterfaceModeChoices.MODE_TAGGED, + 'tagged_vlans': [vlans[0].pk, vlans[1].pk], + 'untagged_vlan': vlans[2].pk, + }, + { + 'device': device.pk, + 'name': 'Interface 5', + 'type': '1000base-t', + 'mode': InterfaceModeChoices.MODE_TAGGED, + 'tagged_vlans': [vlans[0].pk, vlans[1].pk], + 'untagged_vlan': vlans[2].pk, + }, + { + 'device': device.pk, + 'name': 'Interface 6', + 'type': '1000base-t', + 'mode': InterfaceModeChoices.MODE_TAGGED, + 'tagged_vlans': [vlans[0].pk, vlans[1].pk], + 'untagged_vlan': vlans[2].pk, + }, + ] def test_get_interface_graphs(self): + """ + Test retrieval of Graphs assigned to Devices. + """ + ct = ContentType.objects.get_for_model(Interface) + graphs = ( + Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=1'), + Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=2'), + Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=3'), + ) + Graph.objects.bulk_create(graphs) - interface_ct = ContentType.objects.get_for_model(Interface) - self.graph1 = Graph.objects.create( - type=interface_ct, - name='Test Graph 1', - source='http://example.com/graphs.py?interface={{ obj.name }}&foo=1' - ) - self.graph2 = Graph.objects.create( - type=interface_ct, - name='Test Graph 2', - source='http://example.com/graphs.py?interface={{ obj.name }}&foo=2' - ) - self.graph3 = Graph.objects.create( - type=interface_ct, - name='Test Graph 3', - source='http://example.com/graphs.py?interface={{ obj.name }}&foo=3' - ) - - url = reverse('dcim-api:interface-graphs', kwargs={'pk': self.interface1.pk}) + url = reverse('dcim-api:interface-graphs', kwargs={'pk': Interface.objects.first().pk}) response = self.client.get(url, **self.header) self.assertEqual(len(response.data), 3) - self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?interface=Test Interface 1&foo=1') - - def test_list_interfaces(self): - - url = reverse('dcim-api:interface-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_interfaces_brief(self): - - url = reverse('dcim-api:interface-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['cable', 'connection_status', 'device', 'id', 'name', 'url'] - ) - - def test_create_interface(self): - - data = { - 'device': self.device.pk, - 'name': 'Test Interface 4', - 'type': '1000base-t', - } - - url = reverse('dcim-api:interface-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Interface.objects.count(), 4) - interface4 = Interface.objects.get(pk=response.data['id']) - self.assertEqual(interface4.device_id, data['device']) - self.assertEqual(interface4.name, data['name']) - - def test_create_interface_with_802_1q(self): - - data = { - 'device': self.device.pk, - 'name': 'Test Interface 4', - 'type': '1000base-t', - 'mode': InterfaceModeChoices.MODE_TAGGED, - 'untagged_vlan': self.vlan3.id, - 'tagged_vlans': [self.vlan1.id, self.vlan2.id], - } - - url = reverse('dcim-api:interface-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Interface.objects.count(), 4) - self.assertEqual(response.data['device']['id'], data['device']) - self.assertEqual(response.data['name'], data['name']) - self.assertEqual(response.data['untagged_vlan']['id'], data['untagged_vlan']) - self.assertEqual([v['id'] for v in response.data['tagged_vlans']], data['tagged_vlans']) - - def test_create_interface_bulk(self): - - data = [ - { - 'device': self.device.pk, - 'name': 'Test Interface 4', - 'type': '1000base-t', - }, - { - 'device': self.device.pk, - 'name': 'Test Interface 5', - 'type': '1000base-t', - }, - { - 'device': self.device.pk, - 'name': 'Test Interface 6', - 'type': '1000base-t', - }, - ] - - url = reverse('dcim-api:interface-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Interface.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_create_interface_802_1q_bulk(self): - - data = [ - { - 'device': self.device.pk, - 'name': 'Test Interface 4', - 'type': '1000base-t', - 'mode': InterfaceModeChoices.MODE_TAGGED, - 'untagged_vlan': self.vlan2.id, - 'tagged_vlans': [self.vlan1.id], - }, - { - 'device': self.device.pk, - 'name': 'Test Interface 5', - 'type': '1000base-t', - 'mode': InterfaceModeChoices.MODE_TAGGED, - 'untagged_vlan': self.vlan2.id, - 'tagged_vlans': [self.vlan1.id], - }, - { - 'device': self.device.pk, - 'name': 'Test Interface 6', - 'type': '1000base-t', - 'mode': InterfaceModeChoices.MODE_TAGGED, - 'untagged_vlan': self.vlan2.id, - 'tagged_vlans': [self.vlan1.id], - }, - ] - - url = reverse('dcim-api:interface-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Interface.objects.count(), 6) - for i in range(0, 3): - self.assertEqual(response.data[i]['name'], data[i]['name']) - self.assertEqual([v['id'] for v in response.data[i]['tagged_vlans']], data[i]['tagged_vlans']) - self.assertEqual(response.data[i]['untagged_vlan']['id'], data[i]['untagged_vlan']) - - def test_update_interface(self): - - lag_interface = Interface.objects.create( - device=self.device, name='Test LAG Interface', type=InterfaceTypeChoices.TYPE_LAG - ) - - data = { - 'device': self.device.pk, - 'name': 'Test Interface X', - 'type': '1000base-x-gbic', - 'lag': lag_interface.pk, - } - - url = reverse('dcim-api:interface-detail', kwargs={'pk': self.interface1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Interface.objects.count(), 4) - interface1 = Interface.objects.get(pk=response.data['id']) - self.assertEqual(interface1.name, data['name']) - self.assertEqual(interface1.lag_id, data['lag']) - - def test_delete_interface(self): - - url = reverse('dcim-api:interface-detail', kwargs={'pk': self.interface1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Interface.objects.count(), 2) + self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?interface=Interface 1&foo=1') -class FrontPortTest(APITestCase): +class FrontPortTest(APIViewTestCases.APIViewTestCase): + model = FrontPort + brief_fields = ['cable', 'device', 'id', 'name', 'url'] - def setUp(self): - - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') + @classmethod + def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1' + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') + site = Site.objects.create(name='Site 1', slug='site-1') + devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000') + device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site) + + rear_ports = ( + RearPort(device=device, name='Rear Port 1', type=PortTypeChoices.TYPE_8P8C), + RearPort(device=device, name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C), + RearPort(device=device, name='Rear Port 3', type=PortTypeChoices.TYPE_8P8C), + RearPort(device=device, name='Rear Port 4', type=PortTypeChoices.TYPE_8P8C), + RearPort(device=device, name='Rear Port 5', type=PortTypeChoices.TYPE_8P8C), + RearPort(device=device, name='Rear Port 6', type=PortTypeChoices.TYPE_8P8C), ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' + RearPort.objects.bulk_create(rear_ports) + + front_ports = ( + FrontPort(device=device, name='Front Port 1', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[0]), + FrontPort(device=device, name='Front Port 2', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[1]), + FrontPort(device=device, name='Front Port 3', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[2]), ) - self.device = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site - ) - rear_ports = RearPort.objects.bulk_create(( - RearPort(device=self.device, name='Rear Port 1', type=PortTypeChoices.TYPE_8P8C), - RearPort(device=self.device, name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C), - RearPort(device=self.device, name='Rear Port 3', type=PortTypeChoices.TYPE_8P8C), - RearPort(device=self.device, name='Rear Port 4', type=PortTypeChoices.TYPE_8P8C), - RearPort(device=self.device, name='Rear Port 5', type=PortTypeChoices.TYPE_8P8C), - RearPort(device=self.device, name='Rear Port 6', type=PortTypeChoices.TYPE_8P8C), - )) - self.frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[0]) - self.frontport3 = FrontPort.objects.create(device=self.device, name='Front Port 2', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[1]) - self.frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 3', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[2]) + FrontPort.objects.bulk_create(front_ports) - def test_get_frontport(self): - - url = reverse('dcim-api:frontport-detail', kwargs={'pk': self.frontport1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.frontport1.name) - - def test_list_frontports(self): - - url = reverse('dcim-api:frontport-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_frontports_brief(self): - - url = reverse('dcim-api:frontport-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['cable', 'device', 'id', 'name', 'url'] - ) - - def test_create_frontport(self): - - rear_port = RearPort.objects.get(name='Rear Port 4') - data = { - 'device': self.device.pk, - 'name': 'Front Port 4', - 'type': PortTypeChoices.TYPE_8P8C, - 'rear_port': rear_port.pk, - 'rear_port_position': 1, - } - - url = reverse('dcim-api:frontport-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(FrontPort.objects.count(), 4) - frontport4 = FrontPort.objects.get(pk=response.data['id']) - self.assertEqual(frontport4.device_id, data['device']) - self.assertEqual(frontport4.name, data['name']) - - def test_create_frontport_bulk(self): - - rear_ports = RearPort.objects.filter(frontports__isnull=True) - data = [ + cls.create_data = [ { - 'device': self.device.pk, + 'device': device.pk, 'name': 'Front Port 4', 'type': PortTypeChoices.TYPE_8P8C, - 'rear_port': rear_ports[0].pk, + 'rear_port': rear_ports[3].pk, 'rear_port_position': 1, }, { - 'device': self.device.pk, + 'device': device.pk, 'name': 'Front Port 5', 'type': PortTypeChoices.TYPE_8P8C, - 'rear_port': rear_ports[1].pk, + 'rear_port': rear_ports[4].pk, 'rear_port_position': 1, }, { - 'device': self.device.pk, + 'device': device.pk, 'name': 'Front Port 6', 'type': PortTypeChoices.TYPE_8P8C, - 'rear_port': rear_ports[2].pk, + 'rear_port': rear_ports[5].pk, 'rear_port_position': 1, }, ] - url = reverse('dcim-api:frontport-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(FrontPort.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) +class RearPortTest(APIViewTestCases.APIViewTestCase): + model = RearPort + brief_fields = ['cable', 'device', 'id', 'name', 'url'] - def test_update_frontport(self): - - rear_port = RearPort.objects.get(name='Rear Port 4') - data = { - 'device': self.device.pk, - 'name': 'Front Port X', - 'type': PortTypeChoices.TYPE_110_PUNCH, - 'rear_port': rear_port.pk, - 'rear_port_position': 1, - } - - url = reverse('dcim-api:frontport-detail', kwargs={'pk': self.frontport1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(FrontPort.objects.count(), 3) - frontport1 = FrontPort.objects.get(pk=response.data['id']) - self.assertEqual(frontport1.name, data['name']) - self.assertEqual(frontport1.type, data['type']) - self.assertEqual(frontport1.rear_port, rear_port) - - def test_delete_frontport(self): - - url = reverse('dcim-api:frontport-detail', kwargs={'pk': self.frontport1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(FrontPort.objects.count(), 2) - - -class RearPortTest(APITestCase): - - def setUp(self): - - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') + @classmethod + def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1' + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') + site = Site.objects.create(name='Site 1', slug='site-1') + devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000') + device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site) + + rear_ports = ( + RearPort(device=device, name='Rear Port 1', type=PortTypeChoices.TYPE_8P8C), + RearPort(device=device, name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C), + RearPort(device=device, name='Rear Port 3', type=PortTypeChoices.TYPE_8P8C), ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' - ) - self.device = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site - ) - self.rearport1 = RearPort.objects.create(device=self.device, type=PortTypeChoices.TYPE_8P8C, name='Rear Port 1') - self.rearport3 = RearPort.objects.create(device=self.device, type=PortTypeChoices.TYPE_8P8C, name='Rear Port 2') - self.rearport1 = RearPort.objects.create(device=self.device, type=PortTypeChoices.TYPE_8P8C, name='Rear Port 3') + RearPort.objects.bulk_create(rear_ports) - def test_get_rearport(self): - - url = reverse('dcim-api:rearport-detail', kwargs={'pk': self.rearport1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.rearport1.name) - - def test_list_rearports(self): - - url = reverse('dcim-api:rearport-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_rearports_brief(self): - - url = reverse('dcim-api:rearport-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['cable', 'device', 'id', 'name', 'url'] - ) - - def test_create_rearport(self): - - data = { - 'device': self.device.pk, - 'name': 'Front Port 4', - 'type': PortTypeChoices.TYPE_8P8C, - } - - url = reverse('dcim-api:rearport-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(RearPort.objects.count(), 4) - rearport4 = RearPort.objects.get(pk=response.data['id']) - self.assertEqual(rearport4.device_id, data['device']) - self.assertEqual(rearport4.name, data['name']) - - def test_create_rearport_bulk(self): - - data = [ + cls.create_data = [ { - 'device': self.device.pk, + 'device': device.pk, 'name': 'Rear Port 4', 'type': PortTypeChoices.TYPE_8P8C, }, { - 'device': self.device.pk, + 'device': device.pk, 'name': 'Rear Port 5', 'type': PortTypeChoices.TYPE_8P8C, }, { - 'device': self.device.pk, + 'device': device.pk, 'name': 'Rear Port 6', 'type': PortTypeChoices.TYPE_8P8C, }, ] - url = reverse('dcim-api:rearport-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(RearPort.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) +class DeviceBayTest(APIViewTestCases.APIViewTestCase): + model = DeviceBay + brief_fields = ['device', 'id', 'name', 'url'] - def test_update_rearport(self): - - data = { - 'device': self.device.pk, - 'name': 'Front Port X', - 'type': PortTypeChoices.TYPE_110_PUNCH - } - - url = reverse('dcim-api:rearport-detail', kwargs={'pk': self.rearport1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(RearPort.objects.count(), 3) - rearport1 = RearPort.objects.get(pk=response.data['id']) - self.assertEqual(rearport1.name, data['name']) - self.assertEqual(rearport1.type, data['type']) - - def test_delete_rearport(self): - - url = reverse('dcim-api:rearport-detail', kwargs={'pk': self.rearport1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(RearPort.objects.count(), 2) - - -class DeviceBayTest(APITestCase): - - def setUp(self): - - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') + @classmethod + def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - self.devicetype1 = DeviceType.objects.create( - manufacturer=manufacturer, model='Parent Device Type', slug='parent-device-type', - subdevice_role=SubdeviceRoleChoices.ROLE_PARENT + site = Site.objects.create(name='Site 1', slug='site-1') + devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000') + + device_types = ( + DeviceType( + manufacturer=manufacturer, + model='Device Type 1', + slug='device-type-1', + subdevice_role=SubdeviceRoleChoices.ROLE_PARENT + ), + DeviceType( + manufacturer=manufacturer, + model='Device Type 2', + slug='device-type-2', + subdevice_role=SubdeviceRoleChoices.ROLE_CHILD + ), ) - self.devicetype2 = DeviceType.objects.create( - manufacturer=manufacturer, model='Child Device Type', slug='child-device-type', - subdevice_role=SubdeviceRoleChoices.ROLE_CHILD + DeviceType.objects.bulk_create(device_types) + + devices = ( + Device(device_type=device_types[0], device_role=devicerole, name='Device 1', site=site), + Device(device_type=device_types[1], device_role=devicerole, name='Device 2', site=site), + Device(device_type=device_types[1], device_role=devicerole, name='Device 3', site=site), + Device(device_type=device_types[1], device_role=devicerole, name='Device 4', site=site), ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' + Device.objects.bulk_create(devices) + + device_bays = ( + DeviceBay(device=devices[0], name='Device Bay 1'), + DeviceBay(device=devices[0], name='Device Bay 2'), + DeviceBay(device=devices[0], name='Device Bay 3'), ) - self.parent_device = Device.objects.create( - device_type=self.devicetype1, device_role=devicerole, name='Parent Device 1', site=site - ) - self.child_device = Device.objects.create( - device_type=self.devicetype2, device_role=devicerole, name='Child Device 1', site=site - ) - self.devicebay1 = DeviceBay.objects.create(device=self.parent_device, name='Test Device Bay 1') - self.devicebay2 = DeviceBay.objects.create(device=self.parent_device, name='Test Device Bay 2') - self.devicebay3 = DeviceBay.objects.create(device=self.parent_device, name='Test Device Bay 3') + DeviceBay.objects.bulk_create(device_bays) - def test_get_devicebay(self): - - url = reverse('dcim-api:devicebay-detail', kwargs={'pk': self.devicebay1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.devicebay1.name) - - def test_list_devicebays(self): - - url = reverse('dcim-api:devicebay-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_devicebays_brief(self): - - url = reverse('dcim-api:devicebay-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['device', 'id', 'name', 'url'] - ) - - def test_create_devicebay(self): - - data = { - 'device': self.parent_device.pk, - 'name': 'Test Device Bay 4', - 'installed_device': self.child_device.pk, - } - - url = reverse('dcim-api:devicebay-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(DeviceBay.objects.count(), 4) - devicebay4 = DeviceBay.objects.get(pk=response.data['id']) - self.assertEqual(devicebay4.device_id, data['device']) - self.assertEqual(devicebay4.name, data['name']) - self.assertEqual(devicebay4.installed_device_id, data['installed_device']) - - def test_create_devicebay_bulk(self): - - data = [ + cls.create_data = [ { - 'device': self.parent_device.pk, - 'name': 'Test Device Bay 4', + 'device': devices[0].pk, + 'name': 'Device Bay 4', + 'installed_device': devices[1].pk, }, { - 'device': self.parent_device.pk, - 'name': 'Test Device Bay 5', + 'device': devices[0].pk, + 'name': 'Device Bay 5', + 'installed_device': devices[2].pk, }, { - 'device': self.parent_device.pk, - 'name': 'Test Device Bay 6', + 'device': devices[0].pk, + 'name': 'Device Bay 6', + 'installed_device': devices[3].pk, }, ] - url = reverse('dcim-api:devicebay-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(DeviceBay.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) +class InventoryItemTest(APIViewTestCases.APIViewTestCase): + model = InventoryItem + brief_fields = ['device', 'id', 'name', 'url'] - def test_update_devicebay(self): + @classmethod + def setUpTestData(cls): + manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') + site = Site.objects.create(name='Site 1', slug='site-1') + devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000') + device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site) - data = { - 'device': self.parent_device.pk, - 'name': 'Test Device Bay X', - 'installed_device': self.child_device.pk, - } - - url = reverse('dcim-api:devicebay-detail', kwargs={'pk': self.devicebay1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(DeviceBay.objects.count(), 3) - devicebay1 = DeviceBay.objects.get(pk=response.data['id']) - self.assertEqual(devicebay1.name, data['name']) - self.assertEqual(devicebay1.installed_device_id, data['installed_device']) - - def test_delete_devicebay(self): - - url = reverse('dcim-api:devicebay-detail', kwargs={'pk': self.devicebay1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(DeviceBay.objects.count(), 2) - - -class InventoryItemTest(APITestCase): - - def setUp(self): - - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - devicetype = DeviceType.objects.create( - manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1' + inventory_items = ( + InventoryItem(device=device, name='Inventory Item 1', manufacturer=manufacturer), + InventoryItem(device=device, name='Inventory Item 2', manufacturer=manufacturer), + InventoryItem(device=device, name='Inventory Item 3', manufacturer=manufacturer), ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' - ) - self.device = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site - ) - self.inventoryitem1 = InventoryItem.objects.create(device=self.device, name='Test Inventory Item 1') - self.inventoryitem2 = InventoryItem.objects.create(device=self.device, name='Test Inventory Item 2') - self.inventoryitem3 = InventoryItem.objects.create(device=self.device, name='Test Inventory Item 3') + InventoryItem.objects.bulk_create(inventory_items) - def test_get_inventoryitem(self): - - url = reverse('dcim-api:inventoryitem-detail', kwargs={'pk': self.inventoryitem1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.inventoryitem1.name) - - def test_list_inventoryitems(self): - - url = reverse('dcim-api:inventoryitem-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_inventoryitem(self): - - data = { - 'device': self.device.pk, - 'parent': self.inventoryitem1.pk, - 'name': 'Test Inventory Item 4', - 'manufacturer': self.manufacturer.pk, - } - - url = reverse('dcim-api:inventoryitem-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(InventoryItem.objects.count(), 4) - inventoryitem4 = InventoryItem.objects.get(pk=response.data['id']) - self.assertEqual(inventoryitem4.device_id, data['device']) - self.assertEqual(inventoryitem4.parent_id, data['parent']) - self.assertEqual(inventoryitem4.name, data['name']) - self.assertEqual(inventoryitem4.manufacturer_id, data['manufacturer']) - - def test_create_inventoryitem_bulk(self): - - data = [ + cls.create_data = [ { - 'device': self.device.pk, - 'parent': self.inventoryitem1.pk, - 'name': 'Test Inventory Item 4', - 'manufacturer': self.manufacturer.pk, + 'device': device.pk, + 'name': 'Inventory Item 4', + 'manufacturer': manufacturer.pk, }, { - 'device': self.device.pk, - 'parent': self.inventoryitem1.pk, - 'name': 'Test Inventory Item 5', - 'manufacturer': self.manufacturer.pk, + 'device': device.pk, + 'name': 'Inventory Item 5', + 'manufacturer': manufacturer.pk, }, { - 'device': self.device.pk, - 'parent': self.inventoryitem1.pk, - 'name': 'Test Inventory Item 6', - 'manufacturer': self.manufacturer.pk, + 'device': device.pk, + 'name': 'Inventory Item 6', + 'manufacturer': manufacturer.pk, }, ] - url = reverse('dcim-api:inventoryitem-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(InventoryItem.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) +class CableTest(APIViewTestCases.APIViewTestCase): + model = Cable + brief_fields = ['id', 'label', 'url'] - def test_update_inventoryitem(self): + # TODO: Allow updating cable terminations + test_update_object = None - data = { - 'device': self.device.pk, - 'parent': self.inventoryitem1.pk, - 'name': 'Test Inventory Item X', - 'manufacturer': self.manufacturer.pk, - } + @classmethod + def setUpTestData(cls): + site = Site.objects.create(name='Site 1', slug='site-1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') + devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1', color='ff0000') - url = reverse('dcim-api:inventoryitem-detail', kwargs={'pk': self.inventoryitem1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(InventoryItem.objects.count(), 3) - inventoryitem1 = InventoryItem.objects.get(pk=response.data['id']) - self.assertEqual(inventoryitem1.device_id, data['device']) - self.assertEqual(inventoryitem1.parent_id, data['parent']) - self.assertEqual(inventoryitem1.name, data['name']) - self.assertEqual(inventoryitem1.manufacturer_id, data['manufacturer']) - - def test_delete_inventoryitem(self): - - url = reverse('dcim-api:inventoryitem-detail', kwargs={'pk': self.inventoryitem1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(InventoryItem.objects.count(), 2) - - -class CableTest(APITestCase): - - def setUp(self): - - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - devicetype = DeviceType.objects.create( - manufacturer=self.manufacturer, model='Test Device Type 1', slug='test-device-type-1' + devices = ( + Device(device_type=devicetype, device_role=devicerole, name='Device 1', site=site), + Device(device_type=devicetype, device_role=devicerole, name='Device 2', site=site), ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' - ) - self.device1 = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site - ) - self.device2 = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 2', site=site - ) - for device in [self.device1, self.device2]: + Device.objects.bulk_create(devices) + + interfaces = [] + for device in devices: for i in range(0, 10): - Interface(device=device, type=InterfaceTypeChoices.TYPE_1GE_FIXED, name='eth{}'.format(i)).save() + interfaces.append(Interface(device=device, type=InterfaceTypeChoices.TYPE_1GE_FIXED, name=f'eth{i}')) + Interface.objects.bulk_create(interfaces) - self.cable1 = Cable( - termination_a=self.device1.interfaces.get(name='eth0'), - termination_b=self.device2.interfaces.get(name='eth0'), - label='Test Cable 1' + cables = ( + Cable(termination_a=interfaces[0], termination_b=interfaces[10], label='Cable 1'), + Cable(termination_a=interfaces[1], termination_b=interfaces[11], label='Cable 2'), + Cable(termination_a=interfaces[2], termination_b=interfaces[12], label='Cable 3'), ) - self.cable1.save() - self.cable2 = Cable( - termination_a=self.device1.interfaces.get(name='eth1'), - termination_b=self.device2.interfaces.get(name='eth1'), - label='Test Cable 2' - ) - self.cable2.save() - self.cable3 = Cable( - termination_a=self.device1.interfaces.get(name='eth2'), - termination_b=self.device2.interfaces.get(name='eth2'), - label='Test Cable 3' - ) - self.cable3.save() + for cable in cables: + cable.save() - def test_get_cable(self): - - url = reverse('dcim-api:cable-detail', kwargs={'pk': self.cable1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['id'], self.cable1.pk) - - def test_list_cables(self): - - url = reverse('dcim-api:cable-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_cable(self): - - interface_a = self.device1.interfaces.get(name='eth3') - interface_b = self.device2.interfaces.get(name='eth3') - data = { - 'termination_a_type': 'dcim.interface', - 'termination_a_id': interface_a.pk, - 'termination_b_type': 'dcim.interface', - 'termination_b_id': interface_b.pk, - 'status': CableStatusChoices.STATUS_PLANNED, - 'label': 'Test Cable 4', - } - - url = reverse('dcim-api:cable-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Cable.objects.count(), 4) - cable4 = Cable.objects.get(pk=response.data['id']) - self.assertEqual(cable4.termination_a, interface_a) - self.assertEqual(cable4.termination_b, interface_b) - self.assertEqual(cable4.status, data['status']) - self.assertEqual(cable4.label, data['label']) - - def test_create_cable_bulk(self): - - data = [ + cls.create_data = [ { 'termination_a_type': 'dcim.interface', - 'termination_a_id': self.device1.interfaces.get(name='eth3').pk, + 'termination_a_id': interfaces[4].pk, 'termination_b_type': 'dcim.interface', - 'termination_b_id': self.device2.interfaces.get(name='eth3').pk, - 'label': 'Test Cable 4', + 'termination_b_id': interfaces[14].pk, + 'label': 'Cable 4', }, { 'termination_a_type': 'dcim.interface', - 'termination_a_id': self.device1.interfaces.get(name='eth4').pk, + 'termination_a_id': interfaces[5].pk, 'termination_b_type': 'dcim.interface', - 'termination_b_id': self.device2.interfaces.get(name='eth4').pk, - 'label': 'Test Cable 5', + 'termination_b_id': interfaces[15].pk, + 'label': 'Cable 5', }, { 'termination_a_type': 'dcim.interface', - 'termination_a_id': self.device1.interfaces.get(name='eth5').pk, + 'termination_a_id': interfaces[6].pk, 'termination_b_type': 'dcim.interface', - 'termination_b_id': self.device2.interfaces.get(name='eth5').pk, - 'label': 'Test Cable 6', + 'termination_b_id': interfaces[16].pk, + 'label': 'Cable 6', }, ] - url = reverse('dcim-api:cable-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Cable.objects.count(), 6) - self.assertEqual(response.data[0]['label'], data[0]['label']) - self.assertEqual(response.data[1]['label'], data[1]['label']) - self.assertEqual(response.data[2]['label'], data[2]['label']) - - def test_update_cable(self): - - data = { - 'label': 'Test Cable X', - 'status': CableStatusChoices.STATUS_CONNECTED, - } - - url = reverse('dcim-api:cable-detail', kwargs={'pk': self.cable1.pk}) - response = self.client.patch(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Cable.objects.count(), 3) - cable1 = Cable.objects.get(pk=response.data['id']) - self.assertEqual(cable1.status, data['status']) - self.assertEqual(cable1.label, data['label']) - - def test_delete_cable(self): - - url = reverse('dcim-api:cable-detail', kwargs={'pk': self.cable1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Cable.objects.count(), 2) - class ConnectionTest(APITestCase): @@ -3839,426 +1805,159 @@ class ConnectedDeviceTest(APITestCase): self.assertEqual(response.data['name'], self.device1.name) -class VirtualChassisTest(APITestCase): - - def setUp(self): - - super().setUp() +class VirtualChassisTest(APIViewTestCases.APIViewTestCase): + model = VirtualChassis + brief_fields = ['id', 'master', 'member_count', 'url'] + @classmethod + def setUpTestData(cls): site = Site.objects.create(name='Test Site', slug='test-site') - manufacturer = Manufacturer.objects.create(name='Test Manufacturer', slug='test-manufacturer') - device_type = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type', slug='test-device-type' - ) - device_role = DeviceRole.objects.create( - name='Test Device Role', slug='test-device-role', color='ff0000' - ) + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type', slug='device-type') + devicerole = DeviceRole.objects.create(name='Device Role', slug='device-role', color='ff0000') - # Create 9 member Devices with 12 interfaces each - self.device1 = Device.objects.create( - device_type=device_type, device_role=device_role, name='StackSwitch1', site=site + devices = ( + Device(name='Device 1', device_type=devicetype, device_role=devicerole, site=site), + Device(name='Device 2', device_type=devicetype, device_role=devicerole, site=site), + Device(name='Device 3', device_type=devicetype, device_role=devicerole, site=site), + Device(name='Device 4', device_type=devicetype, device_role=devicerole, site=site), + Device(name='Device 5', device_type=devicetype, device_role=devicerole, site=site), + Device(name='Device 6', device_type=devicetype, device_role=devicerole, site=site), + Device(name='Device 7', device_type=devicetype, device_role=devicerole, site=site), + Device(name='Device 8', device_type=devicetype, device_role=devicerole, site=site), + Device(name='Device 9', device_type=devicetype, device_role=devicerole, site=site), ) - self.device2 = Device.objects.create( - device_type=device_type, device_role=device_role, name='StackSwitch2', site=site - ) - self.device3 = Device.objects.create( - device_type=device_type, device_role=device_role, name='StackSwitch3', site=site - ) - self.device4 = Device.objects.create( - device_type=device_type, device_role=device_role, name='StackSwitch4', site=site - ) - self.device5 = Device.objects.create( - device_type=device_type, device_role=device_role, name='StackSwitch5', site=site - ) - self.device6 = Device.objects.create( - device_type=device_type, device_role=device_role, name='StackSwitch6', site=site - ) - self.device7 = Device.objects.create( - device_type=device_type, device_role=device_role, name='StackSwitch7', site=site - ) - self.device8 = Device.objects.create( - device_type=device_type, device_role=device_role, name='StackSwitch8', site=site - ) - self.device9 = Device.objects.create( - device_type=device_type, device_role=device_role, name='StackSwitch9', site=site - ) - for i in range(0, 13): - Interface.objects.create(device=self.device1, name='1/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED) - for i in range(0, 13): - Interface.objects.create(device=self.device2, name='2/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED) - for i in range(0, 13): - Interface.objects.create(device=self.device3, name='3/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED) - for i in range(0, 13): - Interface.objects.create(device=self.device4, name='1/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED) - for i in range(0, 13): - Interface.objects.create(device=self.device5, name='2/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED) - for i in range(0, 13): - Interface.objects.create(device=self.device6, name='3/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED) - for i in range(0, 13): - Interface.objects.create(device=self.device7, name='1/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED) - for i in range(0, 13): - Interface.objects.create(device=self.device8, name='2/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED) - for i in range(0, 13): - Interface.objects.create(device=self.device9, name='3/{}'.format(i), type=InterfaceTypeChoices.TYPE_1GE_FIXED) + Device.objects.bulk_create(devices) + + # Create 12 interfaces per device + interfaces = [] + for i, device in enumerate(devices): + for j in range(0, 13): + interfaces.append( + # Interface name starts with parent device's position in VC; e.g. 1/1, 1/2, 1/3... + Interface(device=device, name=f'{i%3+1}/{j}', type=InterfaceTypeChoices.TYPE_1GE_FIXED) + ) + Interface.objects.bulk_create(interfaces) # Create two VirtualChassis with three members each - self.vc1 = VirtualChassis.objects.create(master=self.device1, domain='test-domain-1') - Device.objects.filter(pk=self.device2.pk).update(virtual_chassis=self.vc1, vc_position=2) - Device.objects.filter(pk=self.device3.pk).update(virtual_chassis=self.vc1, vc_position=3) - self.vc2 = VirtualChassis.objects.create(master=self.device4, domain='test-domain-2') - Device.objects.filter(pk=self.device5.pk).update(virtual_chassis=self.vc2, vc_position=2) - Device.objects.filter(pk=self.device6.pk).update(virtual_chassis=self.vc2, vc_position=3) - - def test_get_virtualchassis(self): - - url = reverse('dcim-api:virtualchassis-detail', kwargs={'pk': self.vc1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['domain'], self.vc1.domain) - - def test_list_virtualchassis(self): - - url = reverse('dcim-api:virtualchassis-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 2) - - def test_list_virtualchassis_brief(self): - - url = reverse('dcim-api:virtualchassis-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'master', 'member_count', 'url'] + virtual_chassis = ( + VirtualChassis(master=devices[0], domain='domain-1'), + VirtualChassis(master=devices[3], domain='domain-2'), ) + VirtualChassis.objects.bulk_create(virtual_chassis) + Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=virtual_chassis[0], vc_position=2) + Device.objects.filter(pk=devices[2].pk).update(virtual_chassis=virtual_chassis[0], vc_position=3) + Device.objects.filter(pk=devices[4].pk).update(virtual_chassis=virtual_chassis[1], vc_position=2) + Device.objects.filter(pk=devices[5].pk).update(virtual_chassis=virtual_chassis[1], vc_position=3) - def test_create_virtualchassis(self): - - data = { - 'master': self.device7.pk, - 'domain': 'test-domain-3', + cls.update_data = { + 'master': devices[1].pk, + 'domain': 'domain-x', } - url = reverse('dcim-api:virtualchassis-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(VirtualChassis.objects.count(), 3) - vc3 = VirtualChassis.objects.get(pk=response.data['id']) - self.assertEqual(vc3.master.pk, data['master']) - self.assertEqual(vc3.domain, data['domain']) - - # Verify that the master device was automatically assigned to the VC - self.assertTrue(Device.objects.filter(pk=vc3.master.pk, virtual_chassis=vc3.pk).exists()) - - def test_create_virtualchassis_bulk(self): - - data = [ + cls.create_data = [ { - 'master': self.device7.pk, - 'domain': 'test-domain-3', + 'master': devices[6].pk, + 'domain': 'domain-3', }, { - 'master': self.device8.pk, - 'domain': 'test-domain-4', + 'master': devices[7].pk, + 'domain': 'domain-4', }, { - 'master': self.device9.pk, - 'domain': 'test-domain-5', + 'master': devices[8].pk, + 'domain': 'domain-5', }, ] - url = reverse('dcim-api:virtualchassis-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(VirtualChassis.objects.count(), 5) - for i in range(0, 3): - self.assertEqual(response.data[i]['master']['id'], data[i]['master']) - self.assertEqual(response.data[i]['domain'], data[i]['domain']) - def test_update_virtualchassis(self): +class PowerPanelTest(APIViewTestCases.APIViewTestCase): + model = PowerPanel + brief_fields = ['id', 'name', 'powerfeed_count', 'url'] - data = { - 'master': self.device2.pk, - 'domain': 'test-domain-x', - } + @classmethod + def setUpTestData(cls): + site = Site.objects.create(name='Site 1', slug='site-1') - url = reverse('dcim-api:virtualchassis-detail', kwargs={'pk': self.vc1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(VirtualChassis.objects.count(), 2) - vc1 = VirtualChassis.objects.get(pk=response.data['id']) - self.assertEqual(vc1.master.pk, data['master']) - self.assertEqual(vc1.domain, data['domain']) - - def test_delete_virtualchassis(self): - - url = reverse('dcim-api:virtualchassis-detail', kwargs={'pk': self.vc1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(VirtualChassis.objects.count(), 1) - - # Verify that all VC members have had their VC-related fields nullified - for d in [self.device1, self.device2, self.device3]: - self.assertTrue( - Device.objects.filter(pk=d.pk, virtual_chassis=None, vc_position=None, vc_priority=None) - ) - - -class PowerPanelTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.rackgroup1 = RackGroup.objects.create(site=self.site1, name='Test Rack Group 1', slug='test-rack-group-1') - self.rackgroup2 = RackGroup.objects.create(site=self.site1, name='Test Rack Group 2', slug='test-rack-group-2') - self.rackgroup3 = RackGroup.objects.create(site=self.site1, name='Test Rack Group 3', slug='test-rack-group-3') - self.powerpanel1 = PowerPanel.objects.create( - site=self.site1, rack_group=self.rackgroup1, name='Test Power Panel 1' - ) - self.powerpanel2 = PowerPanel.objects.create( - site=self.site1, rack_group=self.rackgroup2, name='Test Power Panel 2' - ) - self.powerpanel3 = PowerPanel.objects.create( - site=self.site1, rack_group=self.rackgroup3, name='Test Power Panel 3' + rack_groups = ( + RackGroup.objects.create(name='Rack Group 1', slug='rack-group-1', site=site), + RackGroup.objects.create(name='Rack Group 2', slug='rack-group-2', site=site), + RackGroup.objects.create(name='Rack Group 3', slug='rack-group-3', site=site), ) - def test_get_powerpanel(self): - - url = reverse('dcim-api:powerpanel-detail', kwargs={'pk': self.powerpanel1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.powerpanel1.name) - - def test_list_powerpanels(self): - - url = reverse('dcim-api:powerpanel-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_powerpanels_brief(self): - - url = reverse('dcim-api:powerpanel-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'powerfeed_count', 'url'] + power_panels = ( + PowerPanel(site=site, rack_group=rack_groups[0], name='Power Panel 1'), + PowerPanel(site=site, rack_group=rack_groups[1], name='Power Panel 2'), + PowerPanel(site=site, rack_group=rack_groups[2], name='Power Panel 3'), ) + PowerPanel.objects.bulk_create(power_panels) - def test_create_powerpanel(self): - - data = { - 'name': 'Test Power Panel 4', - 'site': self.site1.pk, - 'rack_group': self.rackgroup1.pk, - } - - url = reverse('dcim-api:powerpanel-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerPanel.objects.count(), 4) - powerpanel4 = PowerPanel.objects.get(pk=response.data['id']) - self.assertEqual(powerpanel4.name, data['name']) - self.assertEqual(powerpanel4.site_id, data['site']) - self.assertEqual(powerpanel4.rack_group_id, data['rack_group']) - - def test_create_powerpanel_bulk(self): - - data = [ + cls.create_data = [ { - 'name': 'Test Power Panel 4', - 'site': self.site1.pk, - 'rack_group': self.rackgroup1.pk, + 'name': 'Power Panel 4', + 'site': site.pk, + 'rack_group': rack_groups[0].pk, }, { - 'name': 'Test Power Panel 5', - 'site': self.site1.pk, - 'rack_group': self.rackgroup2.pk, + 'name': 'Power Panel 5', + 'site': site.pk, + 'rack_group': rack_groups[1].pk, }, { - 'name': 'Test Power Panel 6', - 'site': self.site1.pk, - 'rack_group': self.rackgroup3.pk, + 'name': 'Power Panel 6', + 'site': site.pk, + 'rack_group': rack_groups[2].pk, }, ] - url = reverse('dcim-api:powerpanel-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerPanel.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) +class PowerFeedTest(APIViewTestCases.APIViewTestCase): + model = PowerFeed + brief_fields = ['id', 'name', 'url'] - def test_update_powerpanel(self): + @classmethod + def setUpTestData(cls): + site = Site.objects.create(name='Site 1', slug='site-1') + rackgroup = RackGroup.objects.create(site=site, name='Rack Group 1', slug='rack-group-1') + rackrole = RackRole.objects.create(name='Rack Role 1', slug='rack-role-1', color='ff0000') - data = { - 'name': 'Test Power Panel X', - 'rack_group': self.rackgroup2.pk, - } - - url = reverse('dcim-api:powerpanel-detail', kwargs={'pk': self.powerpanel1.pk}) - response = self.client.patch(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(PowerPanel.objects.count(), 3) - powerpanel1 = PowerPanel.objects.get(pk=response.data['id']) - self.assertEqual(powerpanel1.name, data['name']) - self.assertEqual(powerpanel1.rack_group_id, data['rack_group']) - - def test_delete_powerpanel(self): - - url = reverse('dcim-api:powerpanel-detail', kwargs={'pk': self.powerpanel1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(PowerPanel.objects.count(), 2) - - -class PowerFeedTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.rackgroup1 = RackGroup.objects.create(site=self.site1, name='Test Rack Group 1', slug='test-rack-group-1') - self.rackrole1 = RackRole.objects.create(name='Test Rack Role 1', slug='test-rack-role-1', color='ff0000') - self.rack1 = Rack.objects.create( - site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 1', u_height=42, + racks = ( + Rack(site=site, group=rackgroup, role=rackrole, name='Rack 1'), + Rack(site=site, group=rackgroup, role=rackrole, name='Rack 2'), + Rack(site=site, group=rackgroup, role=rackrole, name='Rack 3'), + Rack(site=site, group=rackgroup, role=rackrole, name='Rack 4'), ) - self.rack2 = Rack.objects.create( - site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 2', u_height=42, + Rack.objects.bulk_create(racks) + + power_panels = ( + PowerPanel(site=site, rack_group=rackgroup, name='Power Panel 1'), + PowerPanel(site=site, rack_group=rackgroup, name='Power Panel 2'), ) - self.rack3 = Rack.objects.create( - site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 3', u_height=42, - ) - self.rack4 = Rack.objects.create( - site=self.site1, group=self.rackgroup1, role=self.rackrole1, name='Test Rack 4', u_height=42, - ) - self.powerpanel1 = PowerPanel.objects.create( - site=self.site1, rack_group=self.rackgroup1, name='Test Power Panel 1' - ) - self.powerpanel2 = PowerPanel.objects.create( - site=self.site1, rack_group=self.rackgroup1, name='Test Power Panel 2' - ) - self.powerfeed1 = PowerFeed.objects.create( - power_panel=self.powerpanel1, rack=self.rack1, name='Test Power Feed 1A', type=PowerFeedTypeChoices.TYPE_PRIMARY - ) - self.powerfeed2 = PowerFeed.objects.create( - power_panel=self.powerpanel2, rack=self.rack1, name='Test Power Feed 1B', type=PowerFeedTypeChoices.TYPE_REDUNDANT - ) - self.powerfeed3 = PowerFeed.objects.create( - power_panel=self.powerpanel1, rack=self.rack2, name='Test Power Feed 2A', type=PowerFeedTypeChoices.TYPE_PRIMARY - ) - self.powerfeed4 = PowerFeed.objects.create( - power_panel=self.powerpanel2, rack=self.rack2, name='Test Power Feed 2B', type=PowerFeedTypeChoices.TYPE_REDUNDANT - ) - self.powerfeed5 = PowerFeed.objects.create( - power_panel=self.powerpanel1, rack=self.rack3, name='Test Power Feed 3A', type=PowerFeedTypeChoices.TYPE_PRIMARY - ) - self.powerfeed6 = PowerFeed.objects.create( - power_panel=self.powerpanel2, rack=self.rack3, name='Test Power Feed 3B', type=PowerFeedTypeChoices.TYPE_REDUNDANT + PowerPanel.objects.bulk_create(power_panels) + + PRIMARY = PowerFeedTypeChoices.TYPE_PRIMARY + REDUNDANT = PowerFeedTypeChoices.TYPE_REDUNDANT + power_feeds = ( + PowerFeed(power_panel=power_panels[0], rack=racks[0], name='Power Feed 1A', type=PRIMARY), + PowerFeed(power_panel=power_panels[1], rack=racks[0], name='Power Feed 1B', type=REDUNDANT), + PowerFeed(power_panel=power_panels[0], rack=racks[1], name='Power Feed 2A', type=PRIMARY), + PowerFeed(power_panel=power_panels[1], rack=racks[1], name='Power Feed 2B', type=REDUNDANT), + PowerFeed(power_panel=power_panels[0], rack=racks[2], name='Power Feed 3A', type=PRIMARY), + PowerFeed(power_panel=power_panels[1], rack=racks[2], name='Power Feed 3B', type=REDUNDANT), ) + PowerFeed.objects.bulk_create(power_feeds) - def test_get_powerfeed(self): - - url = reverse('dcim-api:powerfeed-detail', kwargs={'pk': self.powerfeed1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.powerfeed1.name) - - def test_list_powerfeeds(self): - - url = reverse('dcim-api:powerfeed-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 6) - - def test_list_powerfeeds_brief(self): - - url = reverse('dcim-api:powerfeed-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'url'] - ) - - def test_create_powerfeed(self): - - data = { - 'name': 'Test Power Feed 4A', - 'power_panel': self.powerpanel1.pk, - 'rack': self.rack4.pk, - 'type': PowerFeedTypeChoices.TYPE_PRIMARY, - } - - url = reverse('dcim-api:powerfeed-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerFeed.objects.count(), 7) - powerfeed4 = PowerFeed.objects.get(pk=response.data['id']) - self.assertEqual(powerfeed4.name, data['name']) - self.assertEqual(powerfeed4.power_panel_id, data['power_panel']) - self.assertEqual(powerfeed4.rack_id, data['rack']) - - def test_create_powerfeed_bulk(self): - - data = [ + cls.create_data = [ { - 'name': 'Test Power Feed 4A', - 'power_panel': self.powerpanel1.pk, - 'rack': self.rack4.pk, - 'type': PowerFeedTypeChoices.TYPE_PRIMARY, + 'name': 'Power Feed 4A', + 'power_panel': power_panels[0].pk, + 'rack': racks[3].pk, + 'type': PRIMARY, }, { - 'name': 'Test Power Feed 4B', - 'power_panel': self.powerpanel1.pk, - 'rack': self.rack4.pk, - 'type': PowerFeedTypeChoices.TYPE_REDUNDANT, + 'name': 'Power Feed 4B', + 'power_panel': power_panels[1].pk, + 'rack': racks[3].pk, + 'type': REDUNDANT, }, ] - - url = reverse('dcim-api:powerfeed-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(PowerFeed.objects.count(), 8) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - - def test_update_powerfeed(self): - - data = { - 'name': 'Test Power Feed X', - 'rack': self.rack4.pk, - 'type': PowerFeedTypeChoices.TYPE_REDUNDANT, - } - - url = reverse('dcim-api:powerfeed-detail', kwargs={'pk': self.powerfeed1.pk}) - response = self.client.patch(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(PowerFeed.objects.count(), 6) - powerfeed1 = PowerFeed.objects.get(pk=response.data['id']) - self.assertEqual(powerfeed1.name, data['name']) - self.assertEqual(powerfeed1.rack_id, data['rack']) - self.assertEqual(powerfeed1.type, data['type']) - - def test_delete_powerfeed(self): - - url = reverse('dcim-api:powerfeed-detail', kwargs={'pk': self.powerfeed1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(PowerFeed.objects.count(), 5) diff --git a/netbox/extras/tests/test_api.py b/netbox/extras/tests/test_api.py index 3ab9eaaf0..2635fbbdc 100644 --- a/netbox/extras/tests/test_api.py +++ b/netbox/extras/tests/test_api.py @@ -5,13 +5,11 @@ from django.urls import reverse from django.utils import timezone 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, Rack, RackGroup, RackRole, Site from extras.api.views import ScriptViewSet from extras.models import ConfigContext, Graph, ExportTemplate, Tag from extras.scripts import BooleanVar, IntegerVar, Script, StringVar -from extras.utils import FeatureQuery -from tenancy.models import Tenant, TenantGroup -from utilities.testing import APITestCase +from utilities.testing import APITestCase, APIViewTestCases class AppTest(APITestCase): @@ -24,489 +22,150 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class GraphTest(APITestCase): - - def setUp(self): - - super().setUp() - - site_ct = ContentType.objects.get_for_model(Site) - self.graph1 = Graph.objects.create( - type=site_ct, - name='Test Graph 1', - source='http://example.com/graphs.py?site={{ obj.name }}&foo=1' - ) - self.graph2 = Graph.objects.create( - type=site_ct, - name='Test Graph 2', - source='http://example.com/graphs.py?site={{ obj.name }}&foo=2' - ) - self.graph3 = Graph.objects.create( - type=site_ct, - name='Test Graph 3', - source='http://example.com/graphs.py?site={{ obj.name }}&foo=3' - ) - - def test_get_graph(self): - - url = reverse('extras-api:graph-detail', kwargs={'pk': self.graph1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.graph1.name) - - def test_list_graphs(self): - - url = reverse('extras-api:graph-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_graph(self): - - data = { +class GraphTest(APIViewTestCases.APIViewTestCase): + model = Graph + brief_fields = ['id', 'name', 'url'] + create_data = [ + { 'type': 'dcim.site', - 'name': 'Test Graph 4', + 'name': 'Graph 4', 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=4', - } - - url = reverse('extras-api:graph-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Graph.objects.count(), 4) - graph4 = Graph.objects.get(pk=response.data['id']) - self.assertEqual(graph4.type, ContentType.objects.get_for_model(Site)) - self.assertEqual(graph4.name, data['name']) - self.assertEqual(graph4.source, data['source']) - - def test_create_graph_bulk(self): - - data = [ - { - 'type': 'dcim.site', - 'name': 'Test Graph 4', - 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=4', - }, - { - 'type': 'dcim.site', - 'name': 'Test Graph 5', - 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=5', - }, - { - 'type': 'dcim.site', - 'name': 'Test Graph 6', - 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=6', - }, - ] - - url = reverse('extras-api:graph-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Graph.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_graph(self): - - data = { + }, + { 'type': 'dcim.site', - 'name': 'Test Graph X', - 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=99', - } + 'name': 'Graph 5', + 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=5', + }, + { + 'type': 'dcim.site', + 'name': 'Graph 6', + 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=6', + }, + ] - url = reverse('extras-api:graph-detail', kwargs={'pk': self.graph1.pk}) - response = self.client.put(url, data, format='json', **self.header) + @classmethod + def setUpTestData(cls): + ct = ContentType.objects.get_for_model(Site) - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Graph.objects.count(), 3) - graph1 = Graph.objects.get(pk=response.data['id']) - self.assertEqual(graph1.type, ContentType.objects.get_for_model(Site)) - self.assertEqual(graph1.name, data['name']) - self.assertEqual(graph1.source, data['source']) - - def test_delete_graph(self): - - url = reverse('extras-api:graph-detail', kwargs={'pk': self.graph1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Graph.objects.count(), 2) - - -class ExportTemplateTest(APITestCase): - - def setUp(self): - - super().setUp() - - content_type = ContentType.objects.get_for_model(Device) - self.exporttemplate1 = ExportTemplate.objects.create( - content_type=content_type, name='Test Export Template 1', - template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}' - ) - self.exporttemplate2 = ExportTemplate.objects.create( - content_type=content_type, name='Test Export Template 2', - template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}' - ) - self.exporttemplate3 = ExportTemplate.objects.create( - content_type=content_type, name='Test Export Template 3', - template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}' + graphs = ( + Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?site={{ obj.name }}&foo=1'), + Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?site={{ obj.name }}&foo=2'), + Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?site={{ obj.name }}&foo=3'), ) + Graph.objects.bulk_create(graphs) - def test_get_exporttemplate(self): - url = reverse('extras-api:exporttemplate-detail', kwargs={'pk': self.exporttemplate1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.exporttemplate1.name) - - def test_list_exporttemplates(self): - - url = reverse('extras-api:exporttemplate-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_exporttemplate(self): - - data = { +class ExportTemplateTest(APIViewTestCases.APIViewTestCase): + model = ExportTemplate + brief_fields = ['id', 'name', 'url'] + create_data = [ + { 'content_type': 'dcim.device', 'name': 'Test Export Template 4', 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}', - } - - url = reverse('extras-api:exporttemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ExportTemplate.objects.count(), 4) - exporttemplate4 = ExportTemplate.objects.get(pk=response.data['id']) - self.assertEqual(exporttemplate4.content_type, ContentType.objects.get_for_model(Device)) - self.assertEqual(exporttemplate4.name, data['name']) - self.assertEqual(exporttemplate4.template_code, data['template_code']) - - def test_create_exporttemplate_bulk(self): - - data = [ - { - 'content_type': 'dcim.device', - 'name': 'Test Export Template 4', - 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}', - }, - { - 'content_type': 'dcim.device', - 'name': 'Test Export Template 5', - 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}', - }, - { - 'content_type': 'dcim.device', - 'name': 'Test Export Template 6', - 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}', - }, - ] - - url = reverse('extras-api:exporttemplate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ExportTemplate.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_exporttemplate(self): - - data = { + }, + { 'content_type': 'dcim.device', - 'name': 'Test Export Template X', + 'name': 'Test Export Template 5', 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}', - } + }, + { + 'content_type': 'dcim.device', + 'name': 'Test Export Template 6', + 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}', + }, + ] - url = reverse('extras-api:exporttemplate-detail', kwargs={'pk': self.exporttemplate1.pk}) - response = self.client.put(url, data, format='json', **self.header) + @classmethod + def setUpTestData(cls): + ct = ContentType.objects.get_for_model(Device) - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(ExportTemplate.objects.count(), 3) - exporttemplate1 = ExportTemplate.objects.get(pk=response.data['id']) - self.assertEqual(exporttemplate1.name, data['name']) - self.assertEqual(exporttemplate1.template_code, data['template_code']) - - def test_delete_exporttemplate(self): - - url = reverse('extras-api:exporttemplate-detail', kwargs={'pk': self.exporttemplate1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(ExportTemplate.objects.count(), 2) - - -class TagTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.tag1 = Tag.objects.create(name='Test Tag 1', slug='test-tag-1') - self.tag2 = Tag.objects.create(name='Test Tag 2', slug='test-tag-2') - self.tag3 = Tag.objects.create(name='Test Tag 3', slug='test-tag-3') - - def test_get_tag(self): - - url = reverse('extras-api:tag-detail', kwargs={'pk': self.tag1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.tag1.name) - - def test_list_tags(self): - - url = reverse('extras-api:tag-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_tag(self): - - data = { - 'name': 'Test Tag 4', - 'slug': 'test-tag-4', - } - - url = reverse('extras-api:tag-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Tag.objects.count(), 4) - tag4 = Tag.objects.get(pk=response.data['id']) - self.assertEqual(tag4.name, data['name']) - self.assertEqual(tag4.slug, data['slug']) - - def test_create_tag_bulk(self): - - data = [ - { - 'name': 'Test Tag 4', - 'slug': 'test-tag-4', - }, - { - 'name': 'Test Tag 5', - 'slug': 'test-tag-5', - }, - { - 'name': 'Test Tag 6', - 'slug': 'test-tag-6', - }, - ] - - url = reverse('extras-api:tag-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Tag.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_tag(self): - - data = { - 'name': 'Test Tag X', - 'slug': 'test-tag-x', - } - - url = reverse('extras-api:tag-detail', kwargs={'pk': self.tag1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Tag.objects.count(), 3) - tag1 = Tag.objects.get(pk=response.data['id']) - self.assertEqual(tag1.name, data['name']) - self.assertEqual(tag1.slug, data['slug']) - - def test_delete_tag(self): - - url = reverse('extras-api:tag-detail', kwargs={'pk': self.tag1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Tag.objects.count(), 2) - - -class ConfigContextTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.configcontext1 = ConfigContext.objects.create( - name='Test Config Context 1', - weight=100, - data={'foo': 123} + export_templates = ( + ExportTemplate( + content_type=ct, + name='Export Template 1', + template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}' + ), + ExportTemplate( + content_type=ct, + name='Export Template 2', + template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}' + ), + ExportTemplate( + content_type=ct, + name='Export Template 3', + template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}' + ), ) - self.configcontext2 = ConfigContext.objects.create( - name='Test Config Context 2', - weight=200, - data={'bar': 456} + ExportTemplate.objects.bulk_create(export_templates) + + +class TagTest(APIViewTestCases.APIViewTestCase): + model = Tag + brief_fields = ['color', 'id', 'name', 'slug', 'tagged_items', 'url'] + create_data = [ + { + 'name': 'Tag 4', + 'slug': 'tag-4', + }, + { + 'name': 'Tag 5', + 'slug': 'tag-5', + }, + { + 'name': 'Tag 6', + 'slug': 'tag-6', + }, + ] + + @classmethod + def setUpTestData(cls): + + tags = ( + Tag(name='Tag 1', slug='tag-1'), + Tag(name='Tag 2', slug='tag-2'), + Tag(name='Tag 3', slug='tag-3'), ) - self.configcontext3 = ConfigContext.objects.create( - name='Test Config Context 3', - weight=300, - data={'baz': 789} + Tag.objects.bulk_create(tags) + + +class ConfigContextTest(APIViewTestCases.APIViewTestCase): + model = ConfigContext + brief_fields = ['id', 'name', 'url'] + create_data = [ + { + 'name': 'Config Context 4', + 'data': {'more_foo': True}, + }, + { + 'name': 'Config Context 5', + 'data': {'more_bar': False}, + }, + { + 'name': 'Config Context 6', + 'data': {'more_baz': None}, + }, + ] + + @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}), + ConfigContext(name='Config Context 3', weight=300, data={'baz': 789}), ) - - def test_get_configcontext(self): - - url = reverse('extras-api:configcontext-detail', kwargs={'pk': self.configcontext1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.configcontext1.name) - self.assertEqual(response.data['data'], self.configcontext1.data) - - def test_list_configcontexts(self): - - url = reverse('extras-api:configcontext-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_configcontext(self): - - region1 = Region.objects.create(name='Test Region 1', slug='test-region-1') - region2 = Region.objects.create(name='Test Region 2', slug='test-region-2') - site1 = Site.objects.create(name='Test Site 1', slug='test-site-1') - site2 = Site.objects.create(name='Test Site 2', slug='test-site-2') - role1 = DeviceRole.objects.create(name='Test Role 1', slug='test-role-1') - role2 = DeviceRole.objects.create(name='Test Role 2', slug='test-role-2') - platform1 = Platform.objects.create(name='Test Platform 1', slug='test-platform-1') - platform2 = Platform.objects.create(name='Test Platform 2', slug='test-platform-2') - tenantgroup1 = TenantGroup(name='Test Tenant Group 1', slug='test-tenant-group-1') - tenantgroup1.save() - tenantgroup2 = TenantGroup(name='Test Tenant Group 2', slug='test-tenant-group-2') - tenantgroup2.save() - tenant1 = Tenant.objects.create(name='Test Tenant 1', slug='test-tenant-1') - tenant2 = Tenant.objects.create(name='Test Tenant 2', slug='test-tenant-2') - tag1 = Tag.objects.create(name='Test Tag 1', slug='test-tag-1') - tag2 = Tag.objects.create(name='Test Tag 2', slug='test-tag-2') - - data = { - 'name': 'Test Config Context 4', - 'weight': 1000, - 'regions': [region1.pk, region2.pk], - 'sites': [site1.pk, site2.pk], - 'roles': [role1.pk, role2.pk], - 'platforms': [platform1.pk, platform2.pk], - 'tenant_groups': [tenantgroup1.pk, tenantgroup2.pk], - 'tenants': [tenant1.pk, tenant2.pk], - 'tags': [tag1.slug, tag2.slug], - 'data': {'foo': 'XXX'} - } - - url = reverse('extras-api:configcontext-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ConfigContext.objects.count(), 4) - configcontext4 = ConfigContext.objects.get(pk=response.data['id']) - self.assertEqual(configcontext4.name, data['name']) - self.assertEqual(region1.pk, data['regions'][0]) - self.assertEqual(region2.pk, data['regions'][1]) - self.assertEqual(site1.pk, data['sites'][0]) - self.assertEqual(site2.pk, data['sites'][1]) - self.assertEqual(role1.pk, data['roles'][0]) - self.assertEqual(role2.pk, data['roles'][1]) - self.assertEqual(platform1.pk, data['platforms'][0]) - self.assertEqual(platform2.pk, data['platforms'][1]) - self.assertEqual(tenantgroup1.pk, data['tenant_groups'][0]) - self.assertEqual(tenantgroup2.pk, data['tenant_groups'][1]) - self.assertEqual(tenant1.pk, data['tenants'][0]) - self.assertEqual(tenant2.pk, data['tenants'][1]) - self.assertEqual(tag1.slug, data['tags'][0]) - self.assertEqual(tag2.slug, data['tags'][1]) - self.assertEqual(configcontext4.data, data['data']) - - def test_create_configcontext_bulk(self): - - data = [ - { - 'name': 'Test Config Context 4', - 'data': {'more_foo': True}, - }, - { - 'name': 'Test Config Context 5', - 'data': {'more_bar': False}, - }, - { - 'name': 'Test Config Context 6', - 'data': {'more_baz': None}, - }, - ] - - url = reverse('extras-api:configcontext-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ConfigContext.objects.count(), 6) - for i in range(0, 3): - self.assertEqual(response.data[i]['name'], data[i]['name']) - self.assertEqual(response.data[i]['data'], data[i]['data']) - - def test_update_configcontext(self): - - region1 = Region.objects.create(name='Test Region 1', slug='test-region-1') - region2 = Region.objects.create(name='Test Region 2', slug='test-region-2') - - data = { - 'name': 'Test Config Context X', - 'weight': 999, - 'regions': [region1.pk, region2.pk], - 'data': {'foo': 'XXX'} - } - - url = reverse('extras-api:configcontext-detail', kwargs={'pk': self.configcontext1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(ConfigContext.objects.count(), 3) - configcontext1 = ConfigContext.objects.get(pk=response.data['id']) - self.assertEqual(configcontext1.name, data['name']) - self.assertEqual(configcontext1.weight, data['weight']) - self.assertEqual(sorted([r.pk for r in configcontext1.regions.all()]), sorted(data['regions'])) - self.assertEqual(configcontext1.data, data['data']) - - def test_delete_configcontext(self): - - url = reverse('extras-api:configcontext-detail', kwargs={'pk': self.configcontext1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(ConfigContext.objects.count(), 2) + ConfigContext.objects.bulk_create(config_contexts) def test_render_configcontext_for_object(self): - - # Create a Device for which we'll render a config context - manufacturer = Manufacturer.objects.create( - name='Test Manufacturer', - slug='test-manufacturer' - ) - device_type = DeviceType.objects.create( - manufacturer=manufacturer, - model='Test Device Type' - ) - device_role = DeviceRole.objects.create( - name='Test Role', - slug='test-role' - ) - site = Site.objects.create( - name='Test Site', - slug='test-site' - ) - device = Device.objects.create( - name='Test Device', - device_type=device_type, - device_role=device_role, - site=site - ) + """ + Test rendering config context data for a device. + """ + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') + devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + site = Site.objects.create(name='Site-1', slug='site-1') + device = Device.objects.create(name='Device 1', device_type=devicetype, device_role=devicerole, site=site) # Test default config contexts (created at test setup) rendered_context = device.get_config_context() @@ -516,7 +175,7 @@ class ConfigContextTest(APITestCase): # Add another context specific to the site configcontext4 = ConfigContext( - name='Test Config Context 4', + name='Config Context 4', data={'site_data': 'ABC'} ) configcontext4.save() @@ -526,7 +185,7 @@ class ConfigContextTest(APITestCase): # Override one of the default contexts configcontext5 = ConfigContext( - name='Test Config Context 5', + name='Config Context 5', weight=2000, data={'foo': 999} ) @@ -536,12 +195,9 @@ class ConfigContextTest(APITestCase): self.assertEqual(rendered_context['foo'], 999) # Add a context which does NOT match our device and ensure it does not apply - site2 = Site.objects.create( - name='Test Site 2', - slug='test-site-2' - ) + site2 = Site.objects.create(name='Site 2', slug='site-2') configcontext6 = ConfigContext( - name='Test Config Context 6', + name='Config Context 6', weight=2000, data={'bar': 999} ) diff --git a/netbox/ipam/tests/test_api.py b/netbox/ipam/tests/test_api.py index c20ef6158..a5cb76953 100644 --- a/netbox/ipam/tests/test_api.py +++ b/netbox/ipam/tests/test_api.py @@ -7,7 +7,7 @@ from rest_framework import status from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site from ipam.choices import * from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF -from utilities.testing import APITestCase, disable_warnings +from utilities.testing import APITestCase, APIViewTestCases, disable_warnings class AppTest(APITestCase): @@ -20,536 +20,158 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class VRFTest(APITestCase): +class VRFTest(APIViewTestCases.APIViewTestCase): + model = VRF + brief_fields = ['id', 'name', 'prefix_count', 'rd', 'url'] + create_data = [ + { + 'name': 'VRF 4', + 'rd': '65000:4', + }, + { + 'name': 'VRF 5', + 'rd': '65000:5', + }, + { + 'name': 'VRF 6', + 'rd': '65000:6', + }, + ] - def setUp(self): + @classmethod + def setUpTestData(cls): - super().setUp() - - self.vrf1 = VRF.objects.create(name='Test VRF 1', rd='65000:1') - self.vrf2 = VRF.objects.create(name='Test VRF 2', rd='65000:2') - self.vrf3 = VRF.objects.create(name='Test VRF 3') # No RD - - def test_get_vrf(self): - - url = reverse('ipam-api:vrf-detail', kwargs={'pk': self.vrf1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.vrf1.name) - - def test_list_vrfs(self): - - url = reverse('ipam-api:vrf-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_vrfs_brief(self): - - url = reverse('ipam-api:vrf-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'prefix_count', 'rd', 'url'] + vrfs = ( + VRF(name='VRF 1', rd='65000:1'), + VRF(name='VRF 2', rd='65000:2'), + VRF(name='VRF 3'), # No RD ) - - def test_create_vrf(self): - - data_list = [ - # VRF with RD - { - 'name': 'Test VRF 4', - 'rd': '65000:4', - }, - # VRF without RD - { - 'name': 'Test VRF 5', - } - ] - - url = reverse('ipam-api:vrf-list') - - for data in data_list: - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - vrf = VRF.objects.get(pk=response.data['id']) - self.assertEqual(vrf.name, data['name']) - self.assertEqual(vrf.rd, data['rd'] if 'rd' in data else None) - - def test_create_vrf_bulk(self): - - data = [ - { - 'name': 'Test VRF 4', - 'rd': '65000:4', - }, - { - 'name': 'Test VRF 5', - 'rd': '65000:5', - }, - { - 'name': 'Test VRF 6', - 'rd': '65000:6', - }, - ] - - url = reverse('ipam-api:vrf-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(VRF.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_vrf(self): - - data = { - 'name': 'Test VRF X', - 'rd': '65000:99', - } - - url = reverse('ipam-api:vrf-detail', kwargs={'pk': self.vrf1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(VRF.objects.count(), 3) - vrf1 = VRF.objects.get(pk=response.data['id']) - self.assertEqual(vrf1.name, data['name']) - self.assertEqual(vrf1.rd, data['rd']) - - def test_delete_vrf(self): - - url = reverse('ipam-api:vrf-detail', kwargs={'pk': self.vrf1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(VRF.objects.count(), 2) + VRF.objects.bulk_create(vrfs) -class RIRTest(APITestCase): +class RIRTest(APIViewTestCases.APIViewTestCase): + model = RIR + brief_fields = ['aggregate_count', 'id', 'name', 'slug', 'url'] + create_data = [ + { + 'name': 'RIR 4', + 'slug': 'rir-4', + }, + { + 'name': 'RIR 5', + 'slug': 'rir-5', + }, + { + 'name': 'RIR 6', + 'slug': 'rir-6', + }, + ] - def setUp(self): + @classmethod + def setUpTestData(cls): - super().setUp() - - self.rir1 = RIR.objects.create(name='Test RIR 1', slug='test-rir-1') - self.rir2 = RIR.objects.create(name='Test RIR 2', slug='test-rir-2') - self.rir3 = RIR.objects.create(name='Test RIR 3', slug='test-rir-3') - - def test_get_rir(self): - - url = reverse('ipam-api:rir-detail', kwargs={'pk': self.rir1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.rir1.name) - - def test_list_rirs(self): - - url = reverse('ipam-api:rir-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_rirs_brief(self): - - url = reverse('ipam-api:rir-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['aggregate_count', 'id', 'name', 'slug', 'url'] + rirs = ( + RIR(name='RIR 1', slug='rir-1'), + RIR(name='RIR 2', slug='rir-2'), + RIR(name='RIR 3', slug='rir-3'), ) - - def test_create_rir(self): - - data = { - 'name': 'Test RIR 4', - 'slug': 'test-rir-4', - } - - url = reverse('ipam-api:rir-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(RIR.objects.count(), 4) - rir4 = RIR.objects.get(pk=response.data['id']) - self.assertEqual(rir4.name, data['name']) - self.assertEqual(rir4.slug, data['slug']) - - def test_create_rir_bulk(self): - - data = [ - { - 'name': 'Test RIR 4', - 'slug': 'test-rir-4', - }, - { - 'name': 'Test RIR 5', - 'slug': 'test-rir-5', - }, - { - 'name': 'Test RIR 6', - 'slug': 'test-rir-6', - }, - ] - - url = reverse('ipam-api:rir-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(RIR.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_rir(self): - - data = { - 'name': 'Test RIR X', - 'slug': 'test-rir-x', - } - - url = reverse('ipam-api:rir-detail', kwargs={'pk': self.rir1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(RIR.objects.count(), 3) - rir1 = RIR.objects.get(pk=response.data['id']) - self.assertEqual(rir1.name, data['name']) - self.assertEqual(rir1.slug, data['slug']) - - def test_delete_rir(self): - - url = reverse('ipam-api:rir-detail', kwargs={'pk': self.rir1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(RIR.objects.count(), 2) + RIR.objects.bulk_create(rirs) -class AggregateTest(APITestCase): +class AggregateTest(APIViewTestCases.APIViewTestCase): + model = Aggregate + brief_fields = ['family', 'id', 'prefix', 'url'] - def setUp(self): + @classmethod + def setUpTestData(cls): - super().setUp() - - self.rir1 = RIR.objects.create(name='Test RIR 1', slug='test-rir-1') - self.rir2 = RIR.objects.create(name='Test RIR 2', slug='test-rir-2') - self.aggregate1 = Aggregate.objects.create(prefix=IPNetwork('10.0.0.0/8'), rir=self.rir1) - self.aggregate2 = Aggregate.objects.create(prefix=IPNetwork('172.16.0.0/12'), rir=self.rir1) - self.aggregate3 = Aggregate.objects.create(prefix=IPNetwork('192.168.0.0/16'), rir=self.rir1) - - def test_get_aggregate(self): - - url = reverse('ipam-api:aggregate-detail', kwargs={'pk': self.aggregate1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['family']['value'], 4) - self.assertEqual(response.data['prefix'], str(self.aggregate1.prefix)) - - def test_list_aggregates(self): - - url = reverse('ipam-api:aggregate-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_aggregates_brief(self): - - url = reverse('ipam-api:aggregate-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['family', 'id', 'prefix', 'url'] + rirs = ( + RIR(name='RIR 1', slug='rir-1'), + RIR(name='RIR 2', slug='rir-2'), ) + RIR.objects.bulk_create(rirs) - def test_create_aggregate(self): + aggregates = ( + Aggregate(prefix=IPNetwork('10.0.0.0/8'), rir=rirs[0]), + Aggregate(prefix=IPNetwork('172.16.0.0/12'), rir=rirs[0]), + Aggregate(prefix=IPNetwork('192.168.0.0/16'), rir=rirs[0]), + ) + Aggregate.objects.bulk_create(aggregates) - data = { - 'prefix': '192.0.2.0/24', - 'rir': self.rir1.pk, - } - - url = reverse('ipam-api:aggregate-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Aggregate.objects.count(), 4) - aggregate4 = Aggregate.objects.get(pk=response.data['id']) - self.assertEqual(str(aggregate4.prefix), data['prefix']) - self.assertEqual(aggregate4.rir_id, data['rir']) - - def test_create_aggregate_bulk(self): - - data = [ + cls.create_data = [ { 'prefix': '100.0.0.0/8', - 'rir': self.rir1.pk, + 'rir': rirs[1].pk, }, { 'prefix': '101.0.0.0/8', - 'rir': self.rir1.pk, + 'rir': rirs[1].pk, }, { 'prefix': '102.0.0.0/8', - 'rir': self.rir1.pk, + 'rir': rirs[1].pk, }, ] - url = reverse('ipam-api:aggregate-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Aggregate.objects.count(), 6) - self.assertEqual(response.data[0]['prefix'], data[0]['prefix']) - self.assertEqual(response.data[1]['prefix'], data[1]['prefix']) - self.assertEqual(response.data[2]['prefix'], data[2]['prefix']) +class RoleTest(APIViewTestCases.APIViewTestCase): + model = Role + brief_fields = ['id', 'name', 'prefix_count', 'slug', 'url', 'vlan_count'] + create_data = [ + { + 'name': 'Role 4', + 'slug': 'role-4', + }, + { + 'name': 'Role 5', + 'slug': 'role-5', + }, + { + 'name': 'Role 6', + 'slug': 'role-6', + }, + ] - def test_update_aggregate(self): + @classmethod + def setUpTestData(cls): - data = { - 'prefix': '11.0.0.0/8', - 'rir': self.rir2.pk, - } - - url = reverse('ipam-api:aggregate-detail', kwargs={'pk': self.aggregate1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Aggregate.objects.count(), 3) - aggregate1 = Aggregate.objects.get(pk=response.data['id']) - self.assertEqual(str(aggregate1.prefix), data['prefix']) - self.assertEqual(aggregate1.rir_id, data['rir']) - - def test_delete_aggregate(self): - - url = reverse('ipam-api:aggregate-detail', kwargs={'pk': self.aggregate1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Aggregate.objects.count(), 2) - - -class RoleTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.role1 = Role.objects.create(name='Test Role 1', slug='test-role-1') - self.role2 = Role.objects.create(name='Test Role 2', slug='test-role-2') - self.role3 = Role.objects.create(name='Test Role 3', slug='test-role-3') - - def test_get_role(self): - - url = reverse('ipam-api:role-detail', kwargs={'pk': self.role1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.role1.name) - - def test_list_roles(self): - - url = reverse('ipam-api:role-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_roles_brief(self): - - url = reverse('ipam-api:role-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'prefix_count', 'slug', 'url', 'vlan_count'] + roles = ( + Role(name='Role 1', slug='role-1'), + Role(name='Role 2', slug='role-2'), + Role(name='Role 3', slug='role-3'), ) - - def test_create_role(self): - - data = { - 'name': 'Test Role 4', - 'slug': 'test-role-4', - } - - url = reverse('ipam-api:role-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Role.objects.count(), 4) - role4 = Role.objects.get(pk=response.data['id']) - self.assertEqual(role4.name, data['name']) - self.assertEqual(role4.slug, data['slug']) - - def test_create_role_bulk(self): - - data = [ - { - 'name': 'Test Role 4', - 'slug': 'test-role-4', - }, - { - 'name': 'Test Role 5', - 'slug': 'test-role-5', - }, - { - 'name': 'Test Role 6', - 'slug': 'test-role-6', - }, - ] - - url = reverse('ipam-api:role-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Role.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_role(self): - - data = { - 'name': 'Test Role X', - 'slug': 'test-role-x', - } - - url = reverse('ipam-api:role-detail', kwargs={'pk': self.role1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Role.objects.count(), 3) - role1 = Role.objects.get(pk=response.data['id']) - self.assertEqual(role1.name, data['name']) - self.assertEqual(role1.slug, data['slug']) - - def test_delete_role(self): - - url = reverse('ipam-api:role-detail', kwargs={'pk': self.role1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Role.objects.count(), 2) + Role.objects.bulk_create(roles) -class PrefixTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.vrf1 = VRF.objects.create(name='Test VRF 1', rd='65000:1') - self.vlan1 = VLAN.objects.create(vid=1, name='Test VLAN 1') - self.role1 = Role.objects.create(name='Test Role 1', slug='test-role-1') - self.prefix1 = Prefix.objects.create(prefix=IPNetwork('192.168.1.0/24')) - self.prefix2 = Prefix.objects.create(prefix=IPNetwork('192.168.2.0/24')) - self.prefix3 = Prefix.objects.create(prefix=IPNetwork('192.168.3.0/24')) - - def test_get_prefix(self): - - url = reverse('ipam-api:prefix-detail', kwargs={'pk': self.prefix1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['family']['value'], 4) - self.assertEqual(response.data['prefix'], str(self.prefix1.prefix)) - - def test_list_prefixes(self): - - url = reverse('ipam-api:prefix-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_prefixes_brief(self): - - url = reverse('ipam-api:prefix-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['family', 'id', 'prefix', 'url'] - ) - - def test_create_prefix(self): - - data = { +class PrefixTest(APIViewTestCases.APIViewTestCase): + model = Prefix + brief_fields = ['family', 'id', 'prefix', 'url'] + create_data = [ + { 'prefix': '192.168.4.0/24', - 'site': self.site1.pk, - 'vrf': self.vrf1.pk, - 'vlan': self.vlan1.pk, - 'role': self.role1.pk, - } + }, + { + 'prefix': '192.168.5.0/24', + }, + { + 'prefix': '192.168.6.0/24', + }, + ] - url = reverse('ipam-api:prefix-list') - response = self.client.post(url, data, format='json', **self.header) + @classmethod + def setUpTestData(cls): - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Prefix.objects.count(), 4) - prefix4 = Prefix.objects.get(pk=response.data['id']) - self.assertEqual(str(prefix4.prefix), data['prefix']) - self.assertEqual(prefix4.site_id, data['site']) - self.assertEqual(prefix4.vrf_id, data['vrf']) - self.assertEqual(prefix4.vlan_id, data['vlan']) - self.assertEqual(prefix4.role_id, data['role']) - - def test_create_prefix_bulk(self): - - data = [ - { - 'prefix': '10.0.1.0/24', - }, - { - 'prefix': '10.0.2.0/24', - }, - { - 'prefix': '10.0.3.0/24', - }, - ] - - url = reverse('ipam-api:prefix-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Prefix.objects.count(), 6) - self.assertEqual(response.data[0]['prefix'], data[0]['prefix']) - self.assertEqual(response.data[1]['prefix'], data[1]['prefix']) - self.assertEqual(response.data[2]['prefix'], data[2]['prefix']) - - def test_update_prefix(self): - - data = { - 'prefix': '192.168.99.0/24', - 'site': self.site1.pk, - 'vrf': self.vrf1.pk, - 'vlan': self.vlan1.pk, - 'role': self.role1.pk, - } - - url = reverse('ipam-api:prefix-detail', kwargs={'pk': self.prefix1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Prefix.objects.count(), 3) - prefix1 = Prefix.objects.get(pk=response.data['id']) - self.assertEqual(str(prefix1.prefix), data['prefix']) - self.assertEqual(prefix1.site_id, data['site']) - self.assertEqual(prefix1.vrf_id, data['vrf']) - self.assertEqual(prefix1.vlan_id, data['vlan']) - self.assertEqual(prefix1.role_id, data['role']) - - def test_delete_prefix(self): - - url = reverse('ipam-api:prefix-detail', kwargs={'pk': self.prefix1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Prefix.objects.count(), 2) + prefixes = ( + Prefix(prefix=IPNetwork('192.168.1.0/24')), + Prefix(prefix=IPNetwork('192.168.2.0/24')), + Prefix(prefix=IPNetwork('192.168.3.0/24')), + ) + Prefix.objects.bulk_create(prefixes) def test_list_available_prefixes(self): - + """ + Test retrieval of all available prefixes within a parent prefix. + """ prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/24')) Prefix.objects.create(prefix=IPNetwork('192.0.2.64/26')) Prefix.objects.create(prefix=IPNetwork('192.0.2.192/27')) @@ -562,7 +184,9 @@ class PrefixTest(APITestCase): self.assertEqual(p['prefix'], available_prefixes[i]) def test_create_single_available_prefix(self): - + """ + Test retrieval of the first available prefix within a parent prefix. + """ vrf = VRF.objects.create(name='Test VRF 1', rd='1234') prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/28'), vrf=vrf, is_pool=True) url = reverse('ipam-api:prefix-available-prefixes', kwargs={'pk': prefix.pk}) @@ -596,7 +220,9 @@ class PrefixTest(APITestCase): self.assertIn('prefix_length', response.data[0]) def test_create_multiple_available_prefixes(self): - + """ + Test the creation of available prefixes within a parent prefix. + """ prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/28'), is_pool=True) url = reverse('ipam-api:prefix-available-prefixes', kwargs={'pk': prefix.pk}) @@ -622,7 +248,9 @@ class PrefixTest(APITestCase): self.assertEqual(len(response.data), 4) def test_list_available_ips(self): - + """ + Test retrieval of all available IP addresses within a parent prefix. + """ prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/29'), is_pool=True) url = reverse('ipam-api:prefix-available-ips', kwargs={'pk': prefix.pk}) @@ -637,7 +265,9 @@ class PrefixTest(APITestCase): self.assertEqual(len(response.data), 6) # 8 - 2 because prefix.is_pool = False def test_create_single_available_ip(self): - + """ + Test retrieval of the first available IP address within a parent prefix. + """ vrf = VRF.objects.create(name='Test VRF 1', rd='1234') prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/30'), vrf=vrf, is_pool=True) url = reverse('ipam-api:prefix-available-ips', kwargs={'pk': prefix.pk}) @@ -658,7 +288,9 @@ class PrefixTest(APITestCase): self.assertIn('detail', response.data) def test_create_multiple_available_ips(self): - + """ + Test the creation of available IP addresses within a parent prefix. + """ prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/29'), is_pool=True) url = reverse('ipam-api:prefix-available-ips', kwargs={'pk': prefix.pk}) @@ -679,317 +311,107 @@ class PrefixTest(APITestCase): self.assertEqual(len(response.data), 8) -class IPAddressTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.vrf1 = VRF.objects.create(name='Test VRF 1', rd='65000:1') - self.ipaddress1 = IPAddress.objects.create(address=IPNetwork('192.168.0.1/24')) - self.ipaddress2 = IPAddress.objects.create(address=IPNetwork('192.168.0.2/24')) - self.ipaddress3 = IPAddress.objects.create(address=IPNetwork('192.168.0.3/24')) - - def test_get_ipaddress(self): - - url = reverse('ipam-api:ipaddress-detail', kwargs={'pk': self.ipaddress1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['family']['value'], 4) - self.assertEqual(response.data['address'], str(self.ipaddress1.address)) - - def test_list_ipaddresss(self): - - url = reverse('ipam-api:ipaddress-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_ipaddresses_brief(self): - - url = reverse('ipam-api:ipaddress-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['address', 'family', 'id', 'url'] - ) - - def test_create_ipaddress(self): - - data = { +class IPAddressTest(APIViewTestCases.APIViewTestCase): + model = IPAddress + brief_fields = ['address', 'family', 'id', 'url'] + create_data = [ + { 'address': '192.168.0.4/24', - 'vrf': self.vrf1.pk, - } + }, + { + 'address': '192.168.0.5/24', + }, + { + 'address': '192.168.0.6/24', + }, + ] - url = reverse('ipam-api:ipaddress-list') - response = self.client.post(url, data, format='json', **self.header) + @classmethod + def setUpTestData(cls): - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(IPAddress.objects.count(), 4) - ipaddress4 = IPAddress.objects.get(pk=response.data['id']) - self.assertEqual(str(ipaddress4.address), data['address']) - self.assertEqual(ipaddress4.vrf_id, data['vrf']) - - def test_create_ipaddress_bulk(self): - - data = [ - { - 'address': '192.168.0.4/24', - }, - { - 'address': '192.168.0.5/24', - }, - { - 'address': '192.168.0.6/24', - }, - ] - - url = reverse('ipam-api:ipaddress-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(IPAddress.objects.count(), 6) - self.assertEqual(response.data[0]['address'], data[0]['address']) - self.assertEqual(response.data[1]['address'], data[1]['address']) - self.assertEqual(response.data[2]['address'], data[2]['address']) - - def test_update_ipaddress(self): - - data = { - 'address': '192.168.0.99/24', - 'vrf': self.vrf1.pk, - } - - url = reverse('ipam-api:ipaddress-detail', kwargs={'pk': self.ipaddress1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(IPAddress.objects.count(), 3) - ipaddress1 = IPAddress.objects.get(pk=response.data['id']) - self.assertEqual(str(ipaddress1.address), data['address']) - self.assertEqual(ipaddress1.vrf_id, data['vrf']) - - def test_delete_ipaddress(self): - - url = reverse('ipam-api:ipaddress-detail', kwargs={'pk': self.ipaddress1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(IPAddress.objects.count(), 2) - - -class VLANGroupTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.site1 = Site.objects.create(name='Test Site 1', slug='test-site-1') - self.vlangroup1 = VLANGroup.objects.create(name='Test VLAN Group 1', slug='test-vlan-group-1') - self.vlangroup2 = VLANGroup.objects.create(name='Test VLAN Group 2', slug='test-vlan-group-2') - self.vlangroup3 = VLANGroup.objects.create(name='Test VLAN Group 3', slug='test-vlan-group-3') - - def test_get_vlangroup(self): - - url = reverse('ipam-api:vlangroup-detail', kwargs={'pk': self.vlangroup1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.vlangroup1.name) - - def test_list_vlangroups(self): - - url = reverse('ipam-api:vlangroup-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_vlangroups_brief(self): - - url = reverse('ipam-api:vlangroup-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'slug', 'url', 'vlan_count'] + ip_addresses = ( + IPAddress(address=IPNetwork('192.168.0.1/24')), + IPAddress(address=IPNetwork('192.168.0.2/24')), + IPAddress(address=IPNetwork('192.168.0.3/24')), ) - - def test_create_vlangroup(self): - - data = { - 'name': 'Test VLAN Group 4', - 'slug': 'test-vlan-group-4', - 'site': self.site1.pk, - } - - url = reverse('ipam-api:vlangroup-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(VLANGroup.objects.count(), 4) - vlangroup4 = VLANGroup.objects.get(pk=response.data['id']) - self.assertEqual(vlangroup4.name, data['name']) - self.assertEqual(vlangroup4.slug, data['slug']) - - def test_create_vlangroup_bulk(self): - - data = [ - { - 'name': 'Test VLAN Group 4', - 'slug': 'test-vlan-group-4', - }, - { - 'name': 'Test VLAN Group 5', - 'slug': 'test-vlan-group-5', - }, - { - 'name': 'Test VLAN Group 6', - 'slug': 'test-vlan-group-6', - }, - ] - - url = reverse('ipam-api:vlangroup-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(VLANGroup.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_vlangroup(self): - - data = { - 'name': 'Test VLAN Group X', - 'slug': 'test-vlan-group-x', - } - - url = reverse('ipam-api:vlangroup-detail', kwargs={'pk': self.vlangroup1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(VLANGroup.objects.count(), 3) - vlangroup1 = VLANGroup.objects.get(pk=response.data['id']) - self.assertEqual(vlangroup1.name, data['name']) - self.assertEqual(vlangroup1.slug, data['slug']) - - def test_delete_vlangroup(self): - - url = reverse('ipam-api:vlangroup-detail', kwargs={'pk': self.vlangroup1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(VLANGroup.objects.count(), 2) + IPAddress.objects.bulk_create(ip_addresses) -class VLANTest(APITestCase): +class VLANGroupTest(APIViewTestCases.APIViewTestCase): + model = VLANGroup + brief_fields = ['id', 'name', 'slug', 'url', 'vlan_count'] + create_data = [ + { + 'name': 'VLAN Group 4', + 'slug': 'vlan-group-4', + }, + { + 'name': 'VLAN Group 5', + 'slug': 'vlan-group-5', + }, + { + 'name': 'VLAN Group 6', + 'slug': 'vlan-group-6', + }, + ] - def setUp(self): + @classmethod + def setUpTestData(cls): - super().setUp() - - self.group1 = VLANGroup.objects.create(name='Test VLAN Group 1', slug='test-vlan-group-1') - self.vlan1 = VLAN.objects.create(vid=1, name='Test VLAN 1') - self.vlan2 = VLAN.objects.create(vid=2, name='Test VLAN 2') - self.vlan3 = VLAN.objects.create(vid=3, name='Test VLAN 3') - self.prefix1 = Prefix.objects.create(prefix=IPNetwork('192.168.1.0/24')) - - def test_get_vlan(self): - - url = reverse('ipam-api:vlan-detail', kwargs={'pk': self.vlan1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.vlan1.name) - - def test_list_vlans(self): - - url = reverse('ipam-api:vlan-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_vlans_brief(self): - - url = reverse('ipam-api:vlan-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['display_name', 'id', 'name', 'url', 'vid'] + vlan_groups = ( + VLANGroup(name='VLAN Group 1', slug='vlan-group-1'), + VLANGroup(name='VLAN Group 2', slug='vlan-group-2'), + VLANGroup(name='VLAN Group 3', slug='vlan-group-3'), ) + VLANGroup.objects.bulk_create(vlan_groups) - def test_create_vlan(self): - data = { - 'vid': 4, - 'name': 'Test VLAN 4', - 'group': self.group1.pk, - } +class VLANTest(APIViewTestCases.APIViewTestCase): + model = VLAN + brief_fields = ['display_name', 'id', 'name', 'url', 'vid'] - url = reverse('ipam-api:vlan-list') - response = self.client.post(url, data, format='json', **self.header) + @classmethod + def setUpTestData(cls): - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(VLAN.objects.count(), 4) - vlan4 = VLAN.objects.get(pk=response.data['id']) - self.assertEqual(vlan4.vid, data['vid']) - self.assertEqual(vlan4.name, data['name']) + vlan_groups = ( + VLANGroup(name='VLAN Group 1', slug='vlan-group-1'), + VLANGroup(name='VLAN Group 2', slug='vlan-group-2'), + ) + VLANGroup.objects.bulk_create(vlan_groups) - def test_create_vlan_bulk(self): + vlans = ( + VLAN(name='VLAN 1', vid=1, group=vlan_groups[0]), + VLAN(name='VLAN 2', vid=2, group=vlan_groups[0]), + VLAN(name='VLAN 3', vid=3, group=vlan_groups[0]), + ) + VLAN.objects.bulk_create(vlans) - data = [ + cls.create_data = [ { 'vid': 4, - 'name': 'Test VLAN 4', + 'name': 'VLAN 4', + 'group': vlan_groups[1].pk, }, { 'vid': 5, - 'name': 'Test VLAN 5', + 'name': 'VLAN 5', + 'group': vlan_groups[1].pk, }, { 'vid': 6, - 'name': 'Test VLAN 6', + 'name': 'VLAN 6', + 'group': vlan_groups[1].pk, }, ] - url = reverse('ipam-api:vlan-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(VLAN.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_vlan(self): - - data = { - 'vid': 99, - 'name': 'Test VLAN X', - } - - url = reverse('ipam-api:vlan-detail', kwargs={'pk': self.vlan1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(VLAN.objects.count(), 3) - vlan1 = VLAN.objects.get(pk=response.data['id']) - self.assertEqual(vlan1.vid, data['vid']) - self.assertEqual(vlan1.name, data['name']) - - def test_delete_vlan(self): - - url = reverse('ipam-api:vlan-detail', kwargs={'pk': self.vlan1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(VLAN.objects.count(), 2) - def test_delete_vlan_with_prefix(self): - self.prefix1.vlan = self.vlan1 - self.prefix1.save() + """ + Attempt and fail to delete a VLAN with a Prefix assigned to it. + """ + vlan = VLAN.objects.first() + Prefix.objects.create(prefix=IPNetwork('192.0.2.0/24'), vlan=vlan) - url = reverse('ipam-api:vlan-detail', kwargs={'pk': self.vlan1.pk}) + url = reverse('ipam-api:vlan-detail', kwargs={'pk': vlan.pk}) with disable_warnings('django.request'): response = self.client.delete(url, **self.header) @@ -1000,125 +422,47 @@ class VLANTest(APITestCase): self.assertTrue(content['detail'].startswith('Unable to delete object.')) -class ServiceTest(APITestCase): +class ServiceTest(APIViewTestCases.APIViewTestCase): + model = Service + brief_fields = ['id', 'name', 'port', 'protocol', 'url'] - def setUp(self): + @classmethod + def setUpTestData(cls): + site = Site.objects.create(name='Site 1', slug='site-1') + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1') + devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') - super().setUp() - - site = Site.objects.create(name='Test Site 1', slug='test-site-1') - manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') - devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Test Device Type 1') - devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1') - self.device1 = Device.objects.create( - name='Test Device 1', site=site, device_type=devicetype, device_role=devicerole + devices = ( + Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole), + Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole), ) - self.device2 = Device.objects.create( - name='Test Device 2', site=site, device_type=devicetype, device_role=devicerole - ) - self.service1 = Service.objects.create( - device=self.device1, name='Test Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=1 - ) - self.service1 = Service.objects.create( - device=self.device1, name='Test Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=2 - ) - self.service1 = Service.objects.create( - device=self.device1, name='Test Service 3', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=3 + Device.objects.bulk_create(devices) + + services = ( + Service(device=devices[0], name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=1), + Service(device=devices[0], name='Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=2), + Service(device=devices[0], name='Service 3', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=3), ) + Service.objects.bulk_create(services) - def test_get_service(self): - - url = reverse('ipam-api:service-detail', kwargs={'pk': self.service1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.service1.name) - - def test_list_services(self): - - url = reverse('ipam-api:service-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_create_service(self): - - data = { - 'device': self.device1.pk, - 'name': 'Test Service 4', - 'protocol': ServiceProtocolChoices.PROTOCOL_TCP, - 'port': 4, - 'tags': ['Foo', 'Bar'], - } - - url = reverse('ipam-api:service-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Service.objects.count(), 4) - service4 = Service.objects.get(pk=response.data['id']) - self.assertEqual(service4.device_id, data['device']) - self.assertEqual(service4.name, data['name']) - self.assertEqual(service4.protocol, data['protocol']) - self.assertEqual(service4.port, data['port']) - tags = [tag.name for tag in service4.tags.all()] - self.assertEqual(sorted(tags), sorted(data['tags'])) - - def test_create_service_bulk(self): - - data = [ + cls.create_data = [ { - 'device': self.device1.pk, - 'name': 'Test Service 4', + 'device': devices[1].pk, + 'name': 'Service 4', 'protocol': ServiceProtocolChoices.PROTOCOL_TCP, 'port': 4, }, { - 'device': self.device1.pk, - 'name': 'Test Service 5', + 'device': devices[1].pk, + 'name': 'Service 5', 'protocol': ServiceProtocolChoices.PROTOCOL_TCP, 'port': 5, }, { - 'device': self.device1.pk, - 'name': 'Test Service 6', + 'device': devices[1].pk, + 'name': 'Service 6', 'protocol': ServiceProtocolChoices.PROTOCOL_TCP, 'port': 6, }, ] - - url = reverse('ipam-api:service-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Service.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_service(self): - - data = { - 'device': self.device2.pk, - 'name': 'Test Service X', - 'protocol': ServiceProtocolChoices.PROTOCOL_UDP, - 'port': 99, - } - - url = reverse('ipam-api:service-detail', kwargs={'pk': self.service1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Service.objects.count(), 3) - service1 = Service.objects.get(pk=response.data['id']) - self.assertEqual(service1.device_id, data['device']) - self.assertEqual(service1.name, data['name']) - self.assertEqual(service1.protocol, data['protocol']) - self.assertEqual(service1.port, data['port']) - - def test_delete_service(self): - - url = reverse('ipam-api:service-detail', kwargs={'pk': self.service1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Service.objects.count(), 2) diff --git a/netbox/secrets/tests/test_api.py b/netbox/secrets/tests/test_api.py index 339c370d8..e3078c81f 100644 --- a/netbox/secrets/tests/test_api.py +++ b/netbox/secrets/tests/test_api.py @@ -6,7 +6,7 @@ from rest_framework import status from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site from secrets.models import Secret, SecretRole, SessionKey, UserKey from users.models import Token -from utilities.testing import APITestCase, create_test_user +from utilities.testing import APITestCase, APIViewTestCases, create_test_user from .constants import PRIVATE_KEY, PUBLIC_KEY @@ -20,107 +20,36 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class SecretRoleTest(APITestCase): +class SecretRoleTest(APIViewTestCases.APIViewTestCase): + model = SecretRole + brief_fields = ['id', 'name', 'secret_count', 'slug', 'url'] + create_data = [ + { + 'name': 'Secret Role 4', + 'slug': 'secret-role-4', + }, + { + 'name': 'Secret Role 5', + 'slug': 'secret-role-5', + }, + { + 'name': 'Secret Role 6', + 'slug': 'secret-role-6', + }, + ] - def setUp(self): + @classmethod + def setUpTestData(cls): - super().setUp() - - self.secretrole1 = SecretRole.objects.create(name='Test Secret Role 1', slug='test-secret-role-1') - self.secretrole2 = SecretRole.objects.create(name='Test Secret Role 2', slug='test-secret-role-2') - self.secretrole3 = SecretRole.objects.create(name='Test Secret Role 3', slug='test-secret-role-3') - - def test_get_secretrole(self): - - url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.secretrole1.name) - - def test_list_secretroles(self): - - url = reverse('secrets-api:secretrole-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_secretroles_brief(self): - - url = reverse('secrets-api:secretrole-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'secret_count', 'slug', 'url'] + secret_roles = ( + SecretRole(name='Secret Role 1', slug='secret-role-1'), + SecretRole(name='Secret Role 2', slug='secret-role-2'), + SecretRole(name='Secret Role 3', slug='secret-role-3'), ) - - def test_create_secretrole(self): - - data = { - 'name': 'Test Secret Role 4', - 'slug': 'test-secret-role-4', - } - - url = reverse('secrets-api:secretrole-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(SecretRole.objects.count(), 4) - secretrole4 = SecretRole.objects.get(pk=response.data['id']) - self.assertEqual(secretrole4.name, data['name']) - self.assertEqual(secretrole4.slug, data['slug']) - - def test_create_secretrole_bulk(self): - - data = [ - { - 'name': 'Test Secret Role 4', - 'slug': 'test-secret-role-4', - }, - { - 'name': 'Test Secret Role 5', - 'slug': 'test-secret-role-5', - }, - { - 'name': 'Test Secret Role 6', - 'slug': 'test-secret-role-6', - }, - ] - - url = reverse('secrets-api:secretrole-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(SecretRole.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_secretrole(self): - - data = { - 'name': 'Test SecretRole X', - 'slug': 'test-secretrole-x', - } - - url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(SecretRole.objects.count(), 3) - secretrole1 = SecretRole.objects.get(pk=response.data['id']) - self.assertEqual(secretrole1.name, data['name']) - self.assertEqual(secretrole1.slug, data['slug']) - - def test_delete_secretrole(self): - - url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(SecretRole.objects.count(), 2) + SecretRole.objects.bulk_create(secret_roles) +# TODO: Standardize SecretTest class SecretTest(APITestCase): def setUp(self): diff --git a/netbox/tenancy/tests/test_api.py b/netbox/tenancy/tests/test_api.py index 8da3d7594..b06a8213a 100644 --- a/netbox/tenancy/tests/test_api.py +++ b/netbox/tenancy/tests/test_api.py @@ -1,8 +1,7 @@ from django.urls import reverse -from rest_framework import status from tenancy.models import Tenant, TenantGroup -from utilities.testing import APITestCase +from utilities.testing import APITestCase, APIViewTestCases class AppTest(APITestCase): @@ -15,235 +14,74 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class TenantGroupTest(APITestCase): +class TenantGroupTest(APIViewTestCases.APIViewTestCase): + model = TenantGroup + brief_fields = ['id', 'name', 'slug', 'tenant_count', 'url'] - def setUp(self): + @classmethod + def setUpTestData(cls): - super().setUp() - - self.parent_tenant_groups = ( - TenantGroup(name='Parent Tenant Group 1', slug='parent-tenant-group-1'), - TenantGroup(name='Parent Tenant Group 2', slug='parent-tenant-group-2'), - ) - for tenantgroup in self.parent_tenant_groups: - tenantgroup.save() - - self.tenant_groups = ( - TenantGroup(name='Tenant Group 1', slug='tenant-group-1', parent=self.parent_tenant_groups[0]), - TenantGroup(name='Tenant Group 2', slug='tenant-group-2', parent=self.parent_tenant_groups[0]), - TenantGroup(name='Tenant Group 3', slug='tenant-group-3', parent=self.parent_tenant_groups[0]), - ) - for tenantgroup in self.tenant_groups: - tenantgroup.save() - - def test_get_tenantgroup(self): - - url = reverse('tenancy-api:tenantgroup-detail', kwargs={'pk': self.tenant_groups[0].pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.tenant_groups[0].name) - - def test_list_tenantgroups(self): - - url = reverse('tenancy-api:tenantgroup-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 5) - - def test_list_tenantgroups_brief(self): - - url = reverse('tenancy-api:tenantgroup-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'slug', 'tenant_count', 'url'] + parent_tenant_groups = ( + TenantGroup.objects.create(name='Parent Tenant Group 1', slug='parent-tenant-group-1'), + TenantGroup.objects.create(name='Parent Tenant Group 2', slug='parent-tenant-group-2'), ) - def test_create_tenantgroup(self): + TenantGroup.objects.create(name='Tenant Group 1', slug='tenant-group-1', parent=parent_tenant_groups[0]) + TenantGroup.objects.create(name='Tenant Group 2', slug='tenant-group-2', parent=parent_tenant_groups[0]) + TenantGroup.objects.create(name='Tenant Group 3', slug='tenant-group-3', parent=parent_tenant_groups[0]) - data = { - 'name': 'Tenant Group 4', - 'slug': 'tenant-group-4', - 'parent': self.parent_tenant_groups[0].pk, - } - - url = reverse('tenancy-api:tenantgroup-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(TenantGroup.objects.count(), 6) - tenantgroup4 = TenantGroup.objects.get(pk=response.data['id']) - self.assertEqual(tenantgroup4.name, data['name']) - self.assertEqual(tenantgroup4.slug, data['slug']) - self.assertEqual(tenantgroup4.parent_id, data['parent']) - - def test_create_tenantgroup_bulk(self): - - data = [ + cls.create_data = [ { 'name': 'Tenant Group 4', 'slug': 'tenant-group-4', - 'parent': self.parent_tenant_groups[0].pk, + 'parent': parent_tenant_groups[1].pk, }, { 'name': 'Tenant Group 5', 'slug': 'tenant-group-5', - 'parent': self.parent_tenant_groups[0].pk, + 'parent': parent_tenant_groups[1].pk, }, { 'name': 'Tenant Group 6', 'slug': 'tenant-group-6', - 'parent': self.parent_tenant_groups[0].pk, + 'parent': parent_tenant_groups[1].pk, }, ] - url = reverse('tenancy-api:tenantgroup-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(TenantGroup.objects.count(), 8) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) +class TenantTest(APIViewTestCases.APIViewTestCase): + model = Tenant + brief_fields = ['id', 'name', 'slug', 'url'] - def test_update_tenantgroup(self): + @classmethod + def setUpTestData(cls): - data = { - 'name': 'Tenant Group X', - 'slug': 'tenant-group-x', - 'parent': self.parent_tenant_groups[1].pk, - } - - url = reverse('tenancy-api:tenantgroup-detail', kwargs={'pk': self.tenant_groups[0].pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(TenantGroup.objects.count(), 5) - tenantgroup1 = TenantGroup.objects.get(pk=response.data['id']) - self.assertEqual(tenantgroup1.name, data['name']) - self.assertEqual(tenantgroup1.slug, data['slug']) - self.assertEqual(tenantgroup1.parent_id, data['parent']) - - def test_delete_tenantgroup(self): - - url = reverse('tenancy-api:tenantgroup-detail', kwargs={'pk': self.tenant_groups[0].pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(TenantGroup.objects.count(), 4) - - -class TenantTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.tenant_groups = ( - TenantGroup(name='Tenant Group 1', slug='tenant-group-1'), - TenantGroup(name='Tenant Group 2', slug='tenant-group-2'), - ) - for tenantgroup in self.tenant_groups: - tenantgroup.save() - - self.tenants = ( - Tenant(name='Test Tenant 1', slug='test-tenant-1', group=self.tenant_groups[0]), - Tenant(name='Test Tenant 2', slug='test-tenant-2', group=self.tenant_groups[0]), - Tenant(name='Test Tenant 3', slug='test-tenant-3', group=self.tenant_groups[0]), - ) - Tenant.objects.bulk_create(self.tenants) - - def test_get_tenant(self): - - url = reverse('tenancy-api:tenant-detail', kwargs={'pk': self.tenants[0].pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.tenants[0].name) - - def test_list_tenants(self): - - url = reverse('tenancy-api:tenant-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_tenants_brief(self): - - url = reverse('tenancy-api:tenant-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'slug', 'url'] + tenant_groups = ( + TenantGroup.objects.create(name='Tenant Group 1', slug='tenant-group-1'), + TenantGroup.objects.create(name='Tenant Group 2', slug='tenant-group-2'), ) - def test_create_tenant(self): + tenants = ( + Tenant(name='Tenant 1', slug='tenant-1', group=tenant_groups[0]), + Tenant(name='Tenant 2', slug='tenant-2', group=tenant_groups[0]), + Tenant(name='Tenant 3', slug='tenant-3', group=tenant_groups[0]), + ) + Tenant.objects.bulk_create(tenants) - data = { - 'name': 'Test Tenant 4', - 'slug': 'test-tenant-4', - 'group': self.tenant_groups[0].pk, - } - - url = reverse('tenancy-api:tenant-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Tenant.objects.count(), 4) - tenant4 = Tenant.objects.get(pk=response.data['id']) - self.assertEqual(tenant4.name, data['name']) - self.assertEqual(tenant4.slug, data['slug']) - self.assertEqual(tenant4.group_id, data['group']) - - def test_create_tenant_bulk(self): - - data = [ + cls.create_data = [ { - 'name': 'Test Tenant 4', - 'slug': 'test-tenant-4', + 'name': 'Tenant 4', + 'slug': 'tenant-4', + 'group': tenant_groups[1].pk, }, { - 'name': 'Test Tenant 5', - 'slug': 'test-tenant-5', + 'name': 'Tenant 5', + 'slug': 'tenant-5', + 'group': tenant_groups[1].pk, }, { - 'name': 'Test Tenant 6', - 'slug': 'test-tenant-6', + 'name': 'Tenant 6', + 'slug': 'tenant-6', + 'group': tenant_groups[1].pk, }, ] - - url = reverse('tenancy-api:tenant-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Tenant.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_tenant(self): - - data = { - 'name': 'Test Tenant X', - 'slug': 'test-tenant-x', - 'group': self.tenant_groups[1].pk, - } - - url = reverse('tenancy-api:tenant-detail', kwargs={'pk': self.tenants[0].pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Tenant.objects.count(), 3) - tenant1 = Tenant.objects.get(pk=response.data['id']) - self.assertEqual(tenant1.name, data['name']) - self.assertEqual(tenant1.slug, data['slug']) - self.assertEqual(tenant1.group_id, data['group']) - - def test_delete_tenant(self): - - url = reverse('tenancy-api:tenant-detail', kwargs={'pk': self.tenants[0].pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Tenant.objects.count(), 2) diff --git a/netbox/utilities/api.py b/netbox/utilities/api.py index 205055669..b4482198a 100644 --- a/netbox/utilities/api.py +++ b/netbox/utilities/api.py @@ -6,14 +6,13 @@ from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.core.exceptions import FieldError, MultipleObjectsReturned, ObjectDoesNotExist from django.db.models import ManyToManyField, ProtectedError -from django.http import Http404 from django.urls import reverse from rest_framework.exceptions import APIException from rest_framework.permissions import BasePermission from rest_framework.relations import PrimaryKeyRelatedField, RelatedField from rest_framework.response import Response from rest_framework.serializers import Field, ModelSerializer, ValidationError -from rest_framework.viewsets import ModelViewSet as _ModelViewSet, ViewSet +from rest_framework.viewsets import ModelViewSet as _ModelViewSet from .utils import dict_to_filter_params, dynamic_import diff --git a/netbox/utilities/testing/testcases.py b/netbox/utilities/testing/testcases.py index d10bb025a..a0020119b 100644 --- a/netbox/utilities/testing/testcases.py +++ b/netbox/utilities/testing/testcases.py @@ -1,8 +1,11 @@ from django.contrib.auth.models import Permission, User +from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist from django.forms.models import model_to_dict from django.test import Client, TestCase as _TestCase, override_settings from django.urls import reverse, NoReverseMatch +from netaddr import IPNetwork +from rest_framework import status from rest_framework.test import APIClient from users.models import Token @@ -57,6 +60,49 @@ class TestCase(_TestCase): expected_status, response.status_code, getattr(response, 'data', 'No data') )) + def assertInstanceEqual(self, instance, data, api=False): + """ + Compare a model instance to a dictionary, checking that its attribute values match those specified + in the dictionary. + + :instance: Python object instance + :data: Dictionary of test data used to define the instance + :api: Set to True is the data is a JSON representation of the instance + """ + model_dict = model_to_dict(instance, fields=data.keys()) + + for key, value in list(model_dict.items()): + + # TODO: Differentiate between tags assigned to the instance and a M2M field for tags (ex: ConfigContext) + if key == 'tags': + model_dict[key] = ','.join(sorted([tag.name for tag in value])) + + # Convert ManyToManyField to list of instance PKs + elif model_dict[key] and type(value) in (list, tuple) and hasattr(value[0], 'pk'): + model_dict[key] = [obj.pk for obj in value] + + if api: + + # Replace ContentType numeric IDs with . + if type(getattr(instance, key)) is ContentType: + ct = ContentType.objects.get(pk=value) + model_dict[key] = f'{ct.app_label}.{ct.model}' + + # Convert IPNetwork instances to strings + if type(value) is IPNetwork: + model_dict[key] = str(value) + + # Omit any dictionary keys which are not instance attributes + relevant_data = { + k: v for k, v in data.items() if hasattr(instance, k) + } + + self.assertDictEqual(model_dict, relevant_data) + + +# +# UI Tests +# class ModelViewTestCase(TestCase): """ @@ -104,42 +150,6 @@ class ModelViewTestCase(TestCase): else: raise Exception("Invalid action for URL resolution: {}".format(action)) - def assertInstanceEqual(self, instance, data): - """ - Compare a model instance to a dictionary, checking that its attribute values match those specified - in the dictionary. - """ - model_dict = model_to_dict(instance, fields=data.keys()) - - for key in list(model_dict.keys()): - - # TODO: Differentiate between tags assigned to the instance and a M2M field for tags (ex: ConfigContext) - if key == 'tags': - model_dict[key] = ','.join(sorted([tag.name for tag in model_dict['tags']])) - - # Convert ManyToManyField to list of instance PKs - elif model_dict[key] and type(model_dict[key]) in (list, tuple) and hasattr(model_dict[key][0], 'pk'): - model_dict[key] = [obj.pk for obj in model_dict[key]] - - # Omit any dictionary keys which are not instance attributes - relevant_data = { - k: v for k, v in data.items() if hasattr(instance, k) - } - - self.assertDictEqual(model_dict, relevant_data) - - -class APITestCase(TestCase): - client_class = APIClient - - def setUp(self): - """ - Create a superuser and token for API calls. - """ - self.user = User.objects.create(username='testuser', is_superuser=True) - self.token = Token.objects.create(user=self.user) - self.header = {'HTTP_AUTHORIZATION': 'Token {}'.format(self.token.key)} - class ViewTestCases: """ @@ -165,7 +175,7 @@ class ViewTestCases: self.assertHttpStatus(response, 200) @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) - def test_list_objects_anonymous(self): + def test_get_object_anonymous(self): # Make the request as an unauthenticated user self.client.logout() response = self.client.get(self.model.objects.first().get_absolute_url()) @@ -488,3 +498,129 @@ class ViewTestCases: TestCase suitable for testing device component models (ConsolePorts, Interfaces, etc.) """ maxDiff = None + + +# +# REST API Tests +# + +class APITestCase(TestCase): + client_class = APIClient + model = None + + def setUp(self): + """ + Create a superuser and token for API calls. + """ + self.user = User.objects.create(username='testuser', is_superuser=True) + self.token = Token.objects.create(user=self.user) + self.header = {'HTTP_AUTHORIZATION': 'Token {}'.format(self.token.key)} + + def _get_detail_url(self, instance): + viewname = f'{instance._meta.app_label}-api:{instance._meta.model_name}-detail' + return reverse(viewname, kwargs={'pk': instance.pk}) + + def _get_list_url(self): + viewname = f'{self.model._meta.app_label}-api:{self.model._meta.model_name}-list' + return reverse(viewname) + + +class APIViewTestCases: + + class GetObjectViewTestCase(APITestCase): + + def test_get_object(self): + """ + GET a single object identified by its numeric ID. + """ + instance = self.model.objects.first() + url = self._get_detail_url(instance) + response = self.client.get(url, **self.header) + + self.assertEqual(response.data['id'], instance.pk) + + class ListObjectsViewTestCase(APITestCase): + brief_fields = [] + + def test_list_objects(self): + """ + GET a list of objects. + """ + url = self._get_list_url() + response = self.client.get(url, **self.header) + + self.assertEqual(len(response.data['results']), self.model.objects.count()) + + def test_list_objects_brief(self): + """ + GET a list of objects using the "brief" parameter. + """ + url = f'{self._get_list_url()}?brief=1' + response = self.client.get(url, **self.header) + + self.assertEqual(len(response.data['results']), self.model.objects.count()) + self.assertEqual(sorted(response.data['results'][0]), self.brief_fields) + + class CreateObjectViewTestCase(APITestCase): + create_data = [] + + def test_create_object(self): + """ + POST a single object. + """ + initial_count = self.model.objects.count() + url = self._get_list_url() + response = self.client.post(url, self.create_data[0], format='json', **self.header) + + self.assertHttpStatus(response, status.HTTP_201_CREATED) + self.assertEqual(self.model.objects.count(), initial_count + 1) + self.assertInstanceEqual(self.model.objects.get(pk=response.data['id']), self.create_data[0], api=True) + + def test_bulk_create_object(self): + """ + POST a set of objects in a single request. + """ + initial_count = self.model.objects.count() + url = self._get_list_url() + response = self.client.post(url, self.create_data, format='json', **self.header) + + self.assertHttpStatus(response, status.HTTP_201_CREATED) + self.assertEqual(self.model.objects.count(), initial_count + len(self.create_data)) + + class UpdateObjectViewTestCase(APITestCase): + update_data = {} + + def test_update_object(self): + """ + PATCH a single object identified by its numeric ID. + """ + instance = self.model.objects.first() + url = self._get_detail_url(instance) + update_data = self.update_data or getattr(self, 'create_data')[0] + response = self.client.patch(url, update_data, format='json', **self.header) + + self.assertHttpStatus(response, status.HTTP_200_OK) + instance.refresh_from_db() + self.assertInstanceEqual(instance, self.update_data, api=True) + + class DeleteObjectViewTestCase(APITestCase): + + def test_delete_object(self): + """ + DELETE a single object identified by its numeric ID. + """ + instance = self.model.objects.first() + url = self._get_detail_url(instance) + response = self.client.delete(url, **self.header) + + self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) + self.assertFalse(self.model.objects.filter(pk=instance.pk).exists()) + + class APIViewTestCase( + GetObjectViewTestCase, + ListObjectsViewTestCase, + CreateObjectViewTestCase, + UpdateObjectViewTestCase, + DeleteObjectViewTestCase + ): + pass diff --git a/netbox/virtualization/tests/test_api.py b/netbox/virtualization/tests/test_api.py index 8568e21e9..e436a46c5 100644 --- a/netbox/virtualization/tests/test_api.py +++ b/netbox/virtualization/tests/test_api.py @@ -1,11 +1,10 @@ from django.urls import reverse -from netaddr import IPNetwork from rest_framework import status from dcim.choices import InterfaceModeChoices from dcim.models import Interface -from ipam.models import IPAddress, VLAN -from utilities.testing import APITestCase, disable_warnings +from ipam.models import VLAN +from utilities.testing import APITestCase, APIViewTestCases from virtualization.choices import * from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine @@ -20,487 +19,181 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class ClusterTypeTest(APITestCase): +class ClusterTypeTest(APIViewTestCases.APIViewTestCase): + model = ClusterType + brief_fields = ['cluster_count', 'id', 'name', 'slug', 'url'] + create_data = [ + { + 'name': 'Cluster Type 4', + 'slug': 'cluster-type-4', + }, + { + 'name': 'Cluster Type 5', + 'slug': 'cluster-type-5', + }, + { + 'name': 'Cluster Type 6', + 'slug': 'cluster-type-6', + }, + ] - def setUp(self): + @classmethod + def setUpTestData(cls): - super().setUp() - - self.clustertype1 = ClusterType.objects.create(name='Test Cluster Type 1', slug='test-cluster-type-1') - self.clustertype2 = ClusterType.objects.create(name='Test Cluster Type 2', slug='test-cluster-type-2') - self.clustertype3 = ClusterType.objects.create(name='Test Cluster Type 3', slug='test-cluster-type-3') - - def test_get_clustertype(self): - - url = reverse('virtualization-api:clustertype-detail', kwargs={'pk': self.clustertype1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.clustertype1.name) - - def test_list_clustertypes(self): - - url = reverse('virtualization-api:clustertype-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_clustertypes_brief(self): - - url = reverse('virtualization-api:clustertype-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['cluster_count', 'id', 'name', 'slug', 'url'] + cluster_types = ( + ClusterType(name='Cluster Type 1', slug='cluster-type-1'), + ClusterType(name='Cluster Type 2', slug='cluster-type-2'), + ClusterType(name='Cluster Type 3', slug='cluster-type-3'), ) + ClusterType.objects.bulk_create(cluster_types) - def test_create_clustertype(self): - data = { - 'name': 'Test Cluster Type 4', - 'slug': 'test-cluster-type-4', - } +class ClusterGroupTest(APIViewTestCases.APIViewTestCase): + model = ClusterGroup + brief_fields = ['cluster_count', 'id', 'name', 'slug', 'url'] + create_data = [ + { + 'name': 'Cluster Group 4', + 'slug': 'cluster-type-4', + }, + { + 'name': 'Cluster Group 5', + 'slug': 'cluster-type-5', + }, + { + 'name': 'Cluster Group 6', + 'slug': 'cluster-type-6', + }, + ] - url = reverse('virtualization-api:clustertype-list') - response = self.client.post(url, data, format='json', **self.header) + @classmethod + def setUpTestData(cls): - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ClusterType.objects.count(), 4) - clustertype4 = ClusterType.objects.get(pk=response.data['id']) - self.assertEqual(clustertype4.name, data['name']) - self.assertEqual(clustertype4.slug, data['slug']) + cluster_Groups = ( + ClusterGroup(name='Cluster Group 1', slug='cluster-type-1'), + ClusterGroup(name='Cluster Group 2', slug='cluster-type-2'), + ClusterGroup(name='Cluster Group 3', slug='cluster-type-3'), + ) + ClusterGroup.objects.bulk_create(cluster_Groups) - def test_create_clustertype_bulk(self): - data = [ +class ClusterTest(APIViewTestCases.APIViewTestCase): + model = Cluster + brief_fields = ['id', 'name', 'url', 'virtualmachine_count'] + + @classmethod + def setUpTestData(cls): + + cluster_types = ( + ClusterType(name='Cluster Type 1', slug='cluster-type-1'), + ClusterType(name='Cluster Type 2', slug='cluster-type-2'), + ) + ClusterType.objects.bulk_create(cluster_types) + + cluster_groups = ( + ClusterGroup(name='Cluster Group 1', slug='cluster-group-1'), + ClusterGroup(name='Cluster Group 2', slug='cluster-group-2'), + ) + ClusterGroup.objects.bulk_create(cluster_groups) + + clusters = ( + Cluster(name='Cluster 1', type=cluster_types[0], group=cluster_groups[0]), + Cluster(name='Cluster 2', type=cluster_types[0], group=cluster_groups[0]), + Cluster(name='Cluster 3', type=cluster_types[0], group=cluster_groups[0]), + ) + Cluster.objects.bulk_create(clusters) + + cls.create_data = [ { - 'name': 'Test Cluster Type 4', - 'slug': 'test-cluster-type-4', + 'name': 'Cluster 4', + 'type': cluster_types[1].pk, + 'group': cluster_groups[1].pk, }, { - 'name': 'Test Cluster Type 5', - 'slug': 'test-cluster-type-5', + 'name': 'Cluster 5', + 'type': cluster_types[1].pk, + 'group': cluster_groups[1].pk, }, { - 'name': 'Test Cluster Type 6', - 'slug': 'test-cluster-type-6', + 'name': 'Cluster 6', + 'type': cluster_types[1].pk, + 'group': cluster_groups[1].pk, }, ] - url = reverse('virtualization-api:clustertype-list') - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ClusterType.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) +class VirtualMachineTest(APIViewTestCases.APIViewTestCase): + model = VirtualMachine + brief_fields = ['id', 'name', 'url'] - def test_update_clustertype(self): + @classmethod + def setUpTestData(cls): + clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') + clustergroup = ClusterGroup.objects.create(name='Cluster Group 1', slug='cluster-group-1') - data = { - 'name': 'Test Cluster Type X', - 'slug': 'test-cluster-type-x', - } - - url = reverse('virtualization-api:clustertype-detail', kwargs={'pk': self.clustertype1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(ClusterType.objects.count(), 3) - clustertype1 = ClusterType.objects.get(pk=response.data['id']) - self.assertEqual(clustertype1.name, data['name']) - self.assertEqual(clustertype1.slug, data['slug']) - - def test_delete_clustertype(self): - - url = reverse('virtualization-api:clustertype-detail', kwargs={'pk': self.clustertype1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(ClusterType.objects.count(), 2) - - -class ClusterGroupTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.clustergroup1 = ClusterGroup.objects.create(name='Test Cluster Group 1', slug='test-cluster-group-1') - self.clustergroup2 = ClusterGroup.objects.create(name='Test Cluster Group 2', slug='test-cluster-group-2') - self.clustergroup3 = ClusterGroup.objects.create(name='Test Cluster Group 3', slug='test-cluster-group-3') - - def test_get_clustergroup(self): - - url = reverse('virtualization-api:clustergroup-detail', kwargs={'pk': self.clustergroup1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.clustergroup1.name) - - def test_list_clustergroups(self): - - url = reverse('virtualization-api:clustergroup-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_clustergroups_brief(self): - - url = reverse('virtualization-api:clustergroup-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['cluster_count', 'id', 'name', 'slug', 'url'] + clusters = ( + Cluster(name='Cluster 1', type=clustertype, group=clustergroup), + Cluster(name='Cluster 2', type=clustertype, group=clustergroup), ) + Cluster.objects.bulk_create(clusters) - def test_create_clustergroup(self): + virtual_machines = ( + VirtualMachine(name='Virtual Machine 1', cluster=clusters[0], local_context_data={'A': 1}), + VirtualMachine(name='Virtual Machine 2', cluster=clusters[0], local_context_data={'B': 2}), + VirtualMachine(name='Virtual Machine 3', cluster=clusters[0], local_context_data={'C': 3}), + ) + VirtualMachine.objects.bulk_create(virtual_machines) - data = { - 'name': 'Test Cluster Group 4', - 'slug': 'test-cluster-group-4', - } - - url = reverse('virtualization-api:clustergroup-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ClusterGroup.objects.count(), 4) - clustergroup4 = ClusterGroup.objects.get(pk=response.data['id']) - self.assertEqual(clustergroup4.name, data['name']) - self.assertEqual(clustergroup4.slug, data['slug']) - - def test_create_clustergroup_bulk(self): - - data = [ + cls.create_data = [ { - 'name': 'Test Cluster Group 4', - 'slug': 'test-cluster-group-4', + 'name': 'Virtual Machine 4', + 'cluster': clusters[1].pk, }, { - 'name': 'Test Cluster Group 5', - 'slug': 'test-cluster-group-5', + 'name': 'Virtual Machine 5', + 'cluster': clusters[1].pk, }, { - 'name': 'Test Cluster Group 6', - 'slug': 'test-cluster-group-6', + 'name': 'Virtual Machine 6', + 'cluster': clusters[1].pk, }, ] - url = reverse('virtualization-api:clustergroup-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(ClusterGroup.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_clustergroup(self): - - data = { - 'name': 'Test Cluster Group X', - 'slug': 'test-cluster-group-x', - } - - url = reverse('virtualization-api:clustergroup-detail', kwargs={'pk': self.clustergroup1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(ClusterGroup.objects.count(), 3) - clustergroup1 = ClusterGroup.objects.get(pk=response.data['id']) - self.assertEqual(clustergroup1.name, data['name']) - self.assertEqual(clustergroup1.slug, data['slug']) - - def test_delete_clustergroup(self): - - url = reverse('virtualization-api:clustergroup-detail', kwargs={'pk': self.clustergroup1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(ClusterGroup.objects.count(), 2) - - -class ClusterTest(APITestCase): - - def setUp(self): - - super().setUp() - - cluster_type = ClusterType.objects.create(name='Test Cluster Type 1', slug='test-cluster-type-1') - cluster_group = ClusterGroup.objects.create(name='Test Cluster Group 1', slug='test-cluster-group-1') - - self.cluster1 = Cluster.objects.create(name='Test Cluster 1', type=cluster_type, group=cluster_group) - self.cluster2 = Cluster.objects.create(name='Test Cluster 2', type=cluster_type, group=cluster_group) - self.cluster3 = Cluster.objects.create(name='Test Cluster 3', type=cluster_type, group=cluster_group) - - def test_get_cluster(self): - - url = reverse('virtualization-api:cluster-detail', kwargs={'pk': self.cluster1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.cluster1.name) - - def test_list_clusters(self): - - url = reverse('virtualization-api:cluster-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 3) - - def test_list_clusters_brief(self): - - url = reverse('virtualization-api:cluster-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'url', 'virtualmachine_count'] - ) - - def test_create_cluster(self): - - data = { - 'name': 'Test Cluster 4', - 'type': ClusterType.objects.first().pk, - 'group': ClusterGroup.objects.first().pk, - } - - url = reverse('virtualization-api:cluster-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Cluster.objects.count(), 4) - cluster4 = Cluster.objects.get(pk=response.data['id']) - self.assertEqual(cluster4.name, data['name']) - self.assertEqual(cluster4.type.pk, data['type']) - self.assertEqual(cluster4.group.pk, data['group']) - - def test_create_cluster_bulk(self): - - data = [ - { - 'name': 'Test Cluster 4', - 'type': ClusterType.objects.first().pk, - 'group': ClusterGroup.objects.first().pk, - }, - { - 'name': 'Test Cluster 5', - 'type': ClusterType.objects.first().pk, - 'group': ClusterGroup.objects.first().pk, - }, - { - 'name': 'Test Cluster 6', - 'type': ClusterType.objects.first().pk, - 'group': ClusterGroup.objects.first().pk, - }, - ] - - url = reverse('virtualization-api:cluster-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Cluster.objects.count(), 6) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_cluster(self): - - cluster_type2 = ClusterType.objects.create(name='Test Cluster Type 2', slug='test-cluster-type-2') - cluster_group2 = ClusterGroup.objects.create(name='Test Cluster Group 2', slug='test-cluster-group-2') - data = { - 'name': 'Test Cluster X', - 'type': cluster_type2.pk, - 'group': cluster_group2.pk, - } - - url = reverse('virtualization-api:cluster-detail', kwargs={'pk': self.cluster1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(Cluster.objects.count(), 3) - cluster1 = Cluster.objects.get(pk=response.data['id']) - self.assertEqual(cluster1.name, data['name']) - self.assertEqual(cluster1.type.pk, data['type']) - self.assertEqual(cluster1.group.pk, data['group']) - - def test_delete_cluster(self): - - url = reverse('virtualization-api:cluster-detail', kwargs={'pk': self.cluster1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(Cluster.objects.count(), 2) - - -class VirtualMachineTest(APITestCase): - - def setUp(self): - - super().setUp() - - cluster_type = ClusterType.objects.create(name='Test Cluster Type 1', slug='test-cluster-type-1') - cluster_group = ClusterGroup.objects.create(name='Test Cluster Group 1', slug='test-cluster-group-1') - self.cluster1 = Cluster.objects.create(name='Test Cluster 1', type=cluster_type, group=cluster_group) - - self.virtualmachine1 = VirtualMachine.objects.create(name='Test Virtual Machine 1', cluster=self.cluster1) - self.virtualmachine2 = VirtualMachine.objects.create(name='Test Virtual Machine 2', cluster=self.cluster1) - self.virtualmachine3 = VirtualMachine.objects.create(name='Test Virtual Machine 3', cluster=self.cluster1) - self.virtualmachine_with_context_data = VirtualMachine.objects.create( - name='VM with context data', - cluster=self.cluster1, - local_context_data={ - 'A': 1, - 'B': 2 - } - ) - - def test_get_virtualmachine(self): - - url = reverse('virtualization-api:virtualmachine-detail', kwargs={'pk': self.virtualmachine1.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['name'], self.virtualmachine1.name) - - def test_list_virtualmachines(self): - - url = reverse('virtualization-api:virtualmachine-list') - response = self.client.get(url, **self.header) - - self.assertEqual(response.data['count'], 4) - - def test_list_virtualmachines_brief(self): - - url = reverse('virtualization-api:virtualmachine-list') - response = self.client.get('{}?brief=1'.format(url), **self.header) - - self.assertEqual( - sorted(response.data['results'][0]), - ['id', 'name', 'url'] - ) - - def test_create_virtualmachine(self): - - data = { - 'name': 'Test Virtual Machine 4', - 'cluster': self.cluster1.pk, - } - - url = reverse('virtualization-api:virtualmachine-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(VirtualMachine.objects.count(), 5) - virtualmachine4 = VirtualMachine.objects.get(pk=response.data['id']) - self.assertEqual(virtualmachine4.name, data['name']) - self.assertEqual(virtualmachine4.cluster.pk, data['cluster']) - - def test_create_virtualmachine_without_cluster(self): - - data = { - 'name': 'Test Virtual Machine 4', - } - - url = reverse('virtualization-api:virtualmachine-list') - with disable_warnings('django.request'): - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) - self.assertEqual(VirtualMachine.objects.count(), 4) - - def test_create_virtualmachine_bulk(self): - - data = [ - { - 'name': 'Test Virtual Machine 4', - 'cluster': self.cluster1.pk, - }, - { - 'name': 'Test Virtual Machine 5', - 'cluster': self.cluster1.pk, - }, - { - 'name': 'Test Virtual Machine 6', - 'cluster': self.cluster1.pk, - }, - ] - - url = reverse('virtualization-api:virtualmachine-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(VirtualMachine.objects.count(), 7) - self.assertEqual(response.data[0]['name'], data[0]['name']) - self.assertEqual(response.data[1]['name'], data[1]['name']) - self.assertEqual(response.data[2]['name'], data[2]['name']) - - def test_update_virtualmachine(self): - - interface = Interface.objects.create(name='Test Interface 1', virtual_machine=self.virtualmachine1) - ip4_address = IPAddress.objects.create(address=IPNetwork('192.0.2.1/24'), interface=interface) - ip6_address = IPAddress.objects.create(address=IPNetwork('2001:db8::1/64'), interface=interface) - - cluster2 = Cluster.objects.create( - name='Test Cluster 2', - type=ClusterType.objects.first(), - group=ClusterGroup.objects.first() - ) - data = { - 'name': 'Test Virtual Machine X', - 'cluster': cluster2.pk, - 'primary_ip4': ip4_address.pk, - 'primary_ip6': ip6_address.pk, - } - - url = reverse('virtualization-api:virtualmachine-detail', kwargs={'pk': self.virtualmachine1.pk}) - response = self.client.put(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(VirtualMachine.objects.count(), 4) - virtualmachine1 = VirtualMachine.objects.get(pk=response.data['id']) - self.assertEqual(virtualmachine1.name, data['name']) - self.assertEqual(virtualmachine1.cluster.pk, data['cluster']) - self.assertEqual(virtualmachine1.primary_ip4.pk, data['primary_ip4']) - self.assertEqual(virtualmachine1.primary_ip6.pk, data['primary_ip6']) - - def test_delete_virtualmachine(self): - - url = reverse('virtualization-api:virtualmachine-detail', kwargs={'pk': self.virtualmachine1.pk}) - response = self.client.delete(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) - self.assertEqual(VirtualMachine.objects.count(), 3) - def test_config_context_included_by_default_in_list_view(self): - + """ + Check that config context data is included by default in the virtual machines list. + """ + virtualmachine = VirtualMachine.objects.first() url = reverse('virtualization-api:virtualmachine-list') - url = '{}?id={}'.format(url, self.virtualmachine_with_context_data.pk) + url = '{}?id={}'.format(url, virtualmachine.pk) response = self.client.get(url, **self.header) self.assertEqual(response.data['results'][0].get('config_context', {}).get('A'), 1) def test_config_context_excluded(self): - + """ + Check that config context data can be excluded by passing ?exclude=config_context. + """ url = reverse('virtualization-api:virtualmachine-list') + '?exclude=config_context' response = self.client.get(url, **self.header) self.assertFalse('config_context' in response.data['results'][0]) def test_unique_name_per_cluster_constraint(self): - + """ + Check that creating a virtual machine with a duplicate name fails. + """ data = { - 'name': 'Test Virtual Machine 1', - 'cluster': self.cluster1.pk, + 'name': 'Virtual Machine 1', + 'cluster': Cluster.objects.first().pk, } - url = reverse('virtualization-api:virtualmachine-list') response = self.client.post(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) +# TODO: Standardize InterfaceTest (pending #4721) class InterfaceTest(APITestCase): def setUp(self): diff --git a/netbox/virtualization/tests/test_views.py b/netbox/virtualization/tests/test_views.py index e7bb19285..6ff4bfbed 100644 --- a/netbox/virtualization/tests/test_views.py +++ b/netbox/virtualization/tests/test_views.py @@ -187,14 +187,14 @@ class VirtualMachineTestCase(ViewTestCases.PrimaryObjectViewTestCase): class InterfaceTestCase( ViewTestCases.GetObjectViewTestCase, - ViewTestCases.DeviceComponentViewTestCase, + ViewTestCases.EditObjectViewTestCase, + ViewTestCases.DeleteObjectViewTestCase, + ViewTestCases.BulkCreateObjectsViewTestCase, + ViewTestCases.BulkEditObjectsViewTestCase, + ViewTestCases.BulkDeleteObjectsViewTestCase, ): model = Interface - # Disable inapplicable tests - test_list_objects = None - test_import_objects = None - def _get_base_url(self): # Interface belongs to the DCIM app, so we have to override the base URL return 'virtualization:interface_{}'