|
@@ -1425,6 +1425,18 @@ class RackTestCase(APIViewTestCases.APIViewTestCase):
|
|
|
},
|
|
},
|
|
|
]
|
|
]
|
|
|
|
|
|
|
|
|
|
+ def test_ordering_by_count_without_field(self):
|
|
|
|
|
+ """Ordering by a count left out of the response still sorts by it."""
|
|
|
|
|
+ self.add_permissions('dcim.view_rack')
|
|
|
|
|
+ rack = Rack.objects.get(name='Rack 3')
|
|
|
|
|
+ create_test_device('Device 1', site=rack.site, rack=rack)
|
|
|
|
|
+ response = self.client.get(
|
|
|
|
|
+ f'{self._get_list_url()}?ordering=-device_count,name&fields=id,name', **self.header
|
|
|
|
|
+ )
|
|
|
|
|
+ self.assertHttpStatus(response, status.HTTP_200_OK)
|
|
|
|
|
+ self.assertEqual([row['name'] for row in response.data['results']], ['Rack 3', 'Rack 1', 'Rack 2'])
|
|
|
|
|
+ self.assertNotIn('device_count', response.data['results'][0])
|
|
|
|
|
+
|
|
|
def test_get_rack_elevation(self):
|
|
def test_get_rack_elevation(self):
|
|
|
"""
|
|
"""
|
|
|
GET a single rack elevation.
|
|
GET a single rack elevation.
|
|
@@ -4336,6 +4348,45 @@ class InterfaceTestCase(Mixins.FieldPrefetchMixin, Mixins.ComponentTraceMixin, A
|
|
|
filters.append(f'device_id={device.pk}')
|
|
filters.append(f'device_id={device.pk}')
|
|
|
return [filters[0], '&'.join(filters)]
|
|
return [filters[0], '&'.join(filters)]
|
|
|
|
|
|
|
|
|
|
+ def test_ordering_by_count_annotation(self):
|
|
|
|
|
+ """Ordering by a count annotation sorts the response whether or not it renders the count."""
|
|
|
|
|
+ self.add_permissions('dcim.view_interface', 'extras.view_exporttemplate')
|
|
|
|
|
+ interfaces = {name: Interface.objects.get(name=name) for name in ('Interface 2', 'Interface 3')}
|
|
|
|
|
+ IPAddress.objects.bulk_create((
|
|
|
|
|
+ IPAddress(address='192.0.2.1/24', assigned_object=interfaces['Interface 2']),
|
|
|
|
|
+ IPAddress(address='192.0.2.2/24', assigned_object=interfaces['Interface 2']),
|
|
|
|
|
+ IPAddress(address='192.0.2.3/24', assigned_object=interfaces['Interface 3']),
|
|
|
|
|
+ ))
|
|
|
|
|
+ export_template = ExportTemplate.objects.create(
|
|
|
|
|
+ name='Interfaces', template_code='{% for interface in queryset %}{{ interface.name }},{% endfor %}'
|
|
|
|
|
+ )
|
|
|
|
|
+ export_template.object_types.set([ObjectType.objects.get_for_model(Interface)])
|
|
|
|
|
+ url = f'{self._get_list_url()}?ordering=-count_ipaddresses'
|
|
|
|
|
+
|
|
|
|
|
+ # The count's source isn't a valid ordering field
|
|
|
|
|
+ response = self.client.get(f'{self._get_list_url()}?ordering=-_count_ipaddresses', **self.header)
|
|
|
|
|
+ self.assertHttpStatus(response, status.HTTP_200_OK)
|
|
|
|
|
+ self.assertEqual(
|
|
|
|
|
+ [row['name'] for row in response.data['results']], ['Interface 1', 'Interface 2', 'Interface 3']
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ # Responses without the count annotate it for the ordering alone
|
|
|
|
|
+ for params in ('', '&fields=id,name,count_ipaddresses', '&brief=1', '&fields=id,name', '&export=Interfaces'):
|
|
|
|
|
+ with self.subTest(params=params):
|
|
|
|
|
+ response = self.client.get(url + params, **self.header)
|
|
|
|
|
+ self.assertHttpStatus(response, status.HTTP_200_OK)
|
|
|
|
|
+ if 'export' in params:
|
|
|
|
|
+ self.assertEqual(response.content.decode(), 'Interface 2,Interface 3,Interface 1,')
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.assertEqual(
|
|
|
|
|
+ [row['name'] for row in response.data['results']],
|
|
|
|
|
+ ['Interface 2', 'Interface 3', 'Interface 1'],
|
|
|
|
|
+ )
|
|
|
|
|
+ self.assertEqual(
|
|
|
|
|
+ 'count_ipaddresses' in response.data['results'][0],
|
|
|
|
|
+ params in ('', '&fields=id,name,count_ipaddresses'),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
def test_bulk_delete_child_interfaces(self):
|
|
def test_bulk_delete_child_interfaces(self):
|
|
|
interface1 = Interface.objects.get(name='Interface 1')
|
|
interface1 = Interface.objects.get(name='Interface 1')
|
|
|
device = interface1.device
|
|
device = interface1.device
|