Merge pull request #4080 from netbox-community/4077-view-tests

Closes #4077: Add tests for bulk edit/delete views
This commit is contained in:
Jeremy Stretch 2020-02-03 14:32:56 -05:00 committed by GitHub
commit 91929aae1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 643 additions and 149 deletions

View File

@ -36,6 +36,15 @@ class ProviderTestCase(StandardTestCases.Views):
"Provider 6,provider-6", "Provider 6,provider-6",
) )
cls.bulk_edit_data = {
'asn': 65009,
'account': '5678',
'portal_url': 'http://example.com/portal2',
'noc_contact': 'noc2@example.com',
'admin_contact': 'admin2@example.com',
'comments': 'New comments',
}
class CircuitTypeTestCase(StandardTestCases.Views): class CircuitTypeTestCase(StandardTestCases.Views):
model = CircuitType model = CircuitType
@ -43,6 +52,7 @@ class CircuitTypeTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -73,23 +83,29 @@ class CircuitTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
provider = Provider(name='Provider 1', slug='provider-1', asn=65001) providers = (
provider.save() Provider(name='Provider 1', slug='provider-1', asn=65001),
Provider(name='Provider 2', slug='provider-2', asn=65002),
)
Provider.objects.bulk_create(providers)
circuittype = CircuitType(name='Circuit Type 1', slug='circuit-type-1') circuittypes = (
circuittype.save() CircuitType(name='Circuit Type 1', slug='circuit-type-1'),
CircuitType(name='Circuit Type 2', slug='circuit-type-2'),
)
CircuitType.objects.bulk_create(circuittypes)
Circuit.objects.bulk_create([ Circuit.objects.bulk_create([
Circuit(cid='Circuit 1', provider=provider, type=circuittype), Circuit(cid='Circuit 1', provider=providers[0], type=circuittypes[0]),
Circuit(cid='Circuit 2', provider=provider, type=circuittype), Circuit(cid='Circuit 2', provider=providers[0], type=circuittypes[0]),
Circuit(cid='Circuit 3', provider=provider, type=circuittype), Circuit(cid='Circuit 3', provider=providers[0], type=circuittypes[0]),
]) ])
cls.form_data = { cls.form_data = {
'cid': 'Circuit X', 'cid': 'Circuit X',
'provider': provider.pk, 'provider': providers[1].pk,
'type': circuittype.pk, 'type': circuittypes[1].pk,
'status': CircuitStatusChoices.STATUS_ACTIVE, 'status': CircuitStatusChoices.STATUS_DECOMMISSIONED,
'tenant': None, 'tenant': None,
'install_date': datetime.date(2020, 1, 1), 'install_date': datetime.date(2020, 1, 1),
'commit_rate': 1000, 'commit_rate': 1000,
@ -104,3 +120,14 @@ class CircuitTestCase(StandardTestCases.Views):
"Circuit 5,Provider 1,Circuit Type 1", "Circuit 5,Provider 1,Circuit Type 1",
"Circuit 6,Provider 1,Circuit Type 1", "Circuit 6,Provider 1,Circuit Type 1",
) )
cls.bulk_edit_data = {
'provider': providers[1].pk,
'type': circuittypes[1].pk,
'status': CircuitStatusChoices.STATUS_DECOMMISSIONED,
'tenant': None,
'commit_rate': 2000,
'description': 'New description',
'comments': 'New comments',
}

View File

@ -19,6 +19,7 @@ class RegionTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -52,20 +53,24 @@ class SiteTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
region = Region(name='Region 1', slug='region-1') regions = (
region.save() Region(name='Region 1', slug='region-1'),
Region(name='Region 2', slug='region-2'),
)
for region in regions:
region.save()
Site.objects.bulk_create([ Site.objects.bulk_create([
Site(name='Site 1', slug='site-1', region=region), Site(name='Site 1', slug='site-1', region=regions[0]),
Site(name='Site 2', slug='site-2', region=region), Site(name='Site 2', slug='site-2', region=regions[0]),
Site(name='Site 3', slug='site-3', region=region), Site(name='Site 3', slug='site-3', region=regions[0]),
]) ])
cls.form_data = { cls.form_data = {
'name': 'Site X', 'name': 'Site X',
'slug': 'site-x', 'slug': 'site-x',
'status': SiteStatusChoices.STATUS_PLANNED, 'status': SiteStatusChoices.STATUS_PLANNED,
'region': region.pk, 'region': regions[1].pk,
'tenant': None, 'tenant': None,
'facility': 'Facility X', 'facility': 'Facility X',
'asn': 65001, 'asn': 65001,
@ -89,6 +94,15 @@ class SiteTestCase(StandardTestCases.Views):
"Site 6,site-6", "Site 6,site-6",
) )
cls.bulk_edit_data = {
'status': SiteStatusChoices.STATUS_PLANNED,
'region': regions[1].pk,
'tenant': None,
'asn': 65009,
'time_zone': pytz.timezone('US/Eastern'),
'description': 'New description',
}
class RackGroupTestCase(StandardTestCases.Views): class RackGroupTestCase(StandardTestCases.Views):
model = RackGroup model = RackGroup
@ -96,6 +110,7 @@ class RackGroupTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -129,6 +144,7 @@ class RackRoleTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -159,32 +175,40 @@ class RackReservationTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_create_object = None # TODO: Fix URL name for view test_create_object = None
# TODO: Fix URL name for view
test_import_objects = None test_import_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
user = User.objects.create_user(username='testuser2') user2 = User.objects.create_user(username='testuser2')
user3 = User.objects.create_user(username='testuser3')
site = Site(name='Site 1', slug='site-1') site = Site.objects.create(name='Site 1', slug='site-1')
site.save()
rack = Rack(name='Rack 1', site=site) rack = Rack(name='Rack 1', site=site)
rack.save() rack.save()
RackReservation.objects.bulk_create([ RackReservation.objects.bulk_create([
RackReservation(rack=rack, user=user, units=[1, 2, 3], description='Reservation 1'), RackReservation(rack=rack, user=user2, units=[1, 2, 3], description='Reservation 1'),
RackReservation(rack=rack, user=user, units=[4, 5, 6], description='Reservation 2'), RackReservation(rack=rack, user=user2, units=[4, 5, 6], description='Reservation 2'),
RackReservation(rack=rack, user=user, units=[7, 8, 9], description='Reservation 3'), RackReservation(rack=rack, user=user2, units=[7, 8, 9], description='Reservation 3'),
]) ])
cls.form_data = { cls.form_data = {
'rack': rack.pk, 'rack': rack.pk,
'units': [10, 11, 12], 'units': [10, 11, 12],
'user': user.pk, 'user': user3.pk,
'tenant': None, 'tenant': None,
'description': 'New reservation', 'description': 'Rack reservation',
}
cls.bulk_edit_data = {
'user': user3.pk,
'tenant': None,
'description': 'New description',
} }
@ -194,24 +218,38 @@ class RackTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
site = Site.objects.create(name='Site 1', slug='site-1') sites = (
rackgroup = RackGroup.objects.create(name='Rack Group 1', slug='rack-group-1', site=site) Site(name='Site 1', slug='site-1'),
rackrole = RackRole.objects.create(name='Rack Role 1', slug='rack-role-1') Site(name='Site 2', slug='site-2'),
)
Site.objects.bulk_create(sites)
Rack.objects.bulk_create([ rackgroups = (
Rack(name='Rack 1', site=site), RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0]),
Rack(name='Rack 2', site=site), RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1])
Rack(name='Rack 3', site=site), )
]) RackGroup.objects.bulk_create(rackgroups)
rackroles = (
RackRole(name='Rack Role 1', slug='rack-role-1'),
RackRole(name='Rack Role 2', slug='rack-role-2'),
)
RackRole.objects.bulk_create(rackroles)
Rack.objects.bulk_create((
Rack(name='Rack 1', site=sites[0]),
Rack(name='Rack 2', site=sites[0]),
Rack(name='Rack 3', site=sites[0]),
))
cls.form_data = { cls.form_data = {
'name': 'Rack X', 'name': 'Rack X',
'facility_id': 'Facility X', 'facility_id': 'Facility X',
'site': site.pk, 'site': sites[1].pk,
'group': rackgroup.pk, 'group': rackgroups[1].pk,
'tenant': None, 'tenant': None,
'status': RackStatusChoices.STATUS_PLANNED, 'status': RackStatusChoices.STATUS_PLANNED,
'role': rackrole.pk, 'role': rackroles[1].pk,
'serial': '123456', 'serial': '123456',
'asset_tag': 'ABCDEF', 'asset_tag': 'ABCDEF',
'type': RackTypeChoices.TYPE_CABINET, 'type': RackTypeChoices.TYPE_CABINET,
@ -232,6 +270,23 @@ class RackTestCase(StandardTestCases.Views):
"Site 1,Rack 6,19,42", "Site 1,Rack 6,19,42",
) )
cls.bulk_edit_data = {
'site': sites[1].pk,
'group': rackgroups[1].pk,
'tenant': None,
'status': RackStatusChoices.STATUS_DEPRECATED,
'role': rackroles[1].pk,
'serial': '654321',
'type': RackTypeChoices.TYPE_4POST,
'width': RackWidthChoices.WIDTH_23IN,
'u_height': 49,
'desc_units': True,
'outer_width': 30,
'outer_depth': 30,
'outer_unit': RackDimensionUnitChoices.UNIT_INCH,
'comments': 'New comments',
}
class ManufacturerTestCase(StandardTestCases.Views): class ManufacturerTestCase(StandardTestCases.Views):
model = Manufacturer model = Manufacturer
@ -239,6 +294,7 @@ class ManufacturerTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -268,17 +324,20 @@ class DeviceTypeTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1') manufacturers = (
manufacturer.save() Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
Manufacturer(name='Manufacturer 2', slug='manufacturer-2')
)
Manufacturer.objects.bulk_create(manufacturers)
DeviceType.objects.bulk_create([ DeviceType.objects.bulk_create([
DeviceType(model='Device Type 1', slug='device-type-1', manufacturer=manufacturer), DeviceType(model='Device Type 1', slug='device-type-1', manufacturer=manufacturers[0]),
DeviceType(model='Device Type 2', slug='device-type-2', manufacturer=manufacturer), DeviceType(model='Device Type 2', slug='device-type-2', manufacturer=manufacturers[0]),
DeviceType(model='Device Type 3', slug='device-type-3', manufacturer=manufacturer), DeviceType(model='Device Type 3', slug='device-type-3', manufacturer=manufacturers[0]),
]) ])
cls.form_data = { cls.form_data = {
'manufacturer': manufacturer.pk, 'manufacturer': manufacturers[1].pk,
'model': 'Device Type X', 'model': 'Device Type X',
'slug': 'device-type-x', 'slug': 'device-type-x',
'part_number': '123ABC', 'part_number': '123ABC',
@ -289,6 +348,12 @@ class DeviceTypeTestCase(StandardTestCases.Views):
'tags': 'Alpha,Bravo,Charlie', 'tags': 'Alpha,Bravo,Charlie',
} }
cls.bulk_edit_data = {
'manufacturer': manufacturers[1].pk,
'u_height': 3,
'is_full_depth': False,
}
def test_import_objects(self): def test_import_objects(self):
""" """
Custom import test for YAML-based imports (versus CSV) Custom import test for YAML-based imports (versus CSV)
@ -451,6 +516,7 @@ class DeviceRoleTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -483,6 +549,7 @@ class PlatformTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -517,29 +584,54 @@ class DeviceTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
site = Site.objects.create(name='Site 1', slug='site-1') sites = (
rack = Rack.objects.create(name='Rack 1', site=site) 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') manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer)
devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') devicetypes = (
platform = Platform.objects.create(name='Platform 1', slug='platform-1') DeviceType(model='Device Type 1', slug='device-type-1', manufacturer=manufacturer),
DeviceType(model='Device Type 2', slug='device-type-2', manufacturer=manufacturer),
)
DeviceType.objects.bulk_create(devicetypes)
deviceroles = (
DeviceRole(name='Device Role 1', slug='device-role-1'),
DeviceRole(name='Device Role 2', slug='device-role-2'),
)
DeviceRole.objects.bulk_create(deviceroles)
platforms = (
Platform(name='Platform 1', slug='platform-1'),
Platform(name='Platform 2', slug='platform-2'),
)
Platform.objects.bulk_create(platforms)
Device.objects.bulk_create([ Device.objects.bulk_create([
Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole), Device(name='Device 1', site=sites[0], rack=racks[0], device_type=devicetypes[0], device_role=deviceroles[0], platform=platforms[0]),
Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole), Device(name='Device 2', site=sites[0], rack=racks[0], device_type=devicetypes[0], device_role=deviceroles[0], platform=platforms[0]),
Device(name='Device 3', site=site, device_type=devicetype, device_role=devicerole), Device(name='Device 3', site=sites[0], rack=racks[0], device_type=devicetypes[0], device_role=deviceroles[0], platform=platforms[0]),
]) ])
cls.form_data = { cls.form_data = {
'device_type': devicetype.pk, 'device_type': devicetypes[1].pk,
'device_role': devicerole.pk, 'device_role': deviceroles[1].pk,
'tenant': None, 'tenant': None,
'platform': platform.pk, 'platform': platforms[1].pk,
'name': 'Device X', 'name': 'Device X',
'serial': '123456', 'serial': '123456',
'asset_tag': 'ABCDEF', 'asset_tag': 'ABCDEF',
'site': site.pk, 'site': sites[1].pk,
'rack': rack.pk, 'rack': racks[1].pk,
'position': 1, 'position': 1,
'face': DeviceFaceChoices.FACE_FRONT, 'face': DeviceFaceChoices.FACE_FRONT,
'status': DeviceStatusChoices.STATUS_PLANNED, 'status': DeviceStatusChoices.STATUS_PLANNED,
@ -561,6 +653,15 @@ class DeviceTestCase(StandardTestCases.Views):
"Device Role 1,Manufacturer 1,Device Type 1,Active,Site 1,Device 6", "Device Role 1,Manufacturer 1,Device Type 1,Active,Site 1,Device 6",
) )
cls.bulk_edit_data = {
'device_type': devicetypes[1].pk,
'device_role': deviceroles[1].pk,
'tenant': None,
'platform': platforms[1].pk,
'serial': '123456',
'status': DeviceStatusChoices.STATUS_DECOMMISSIONING,
}
# TODO: Convert to StandardTestCases.Views # TODO: Convert to StandardTestCases.Views
class ConsolePortTestCase(TestCase): class ConsolePortTestCase(TestCase):
@ -1071,28 +1172,28 @@ class CableTestCase(StandardTestCases.Views):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer) devicetype = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer)
devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
device1 = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
device1.save() devices = (
device2 = Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole) Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole),
device2.save() Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole),
device3 = Device(name='Device 3', site=site, device_type=devicetype, device_role=devicerole) Device(name='Device 3', site=site, device_type=devicetype, device_role=devicerole),
device3.save() Device(name='Device 4', site=site, device_type=devicetype, device_role=devicerole),
device4 = Device(name='Device 4', site=site, device_type=devicetype, device_role=devicerole) )
device4.save() Device.objects.bulk_create(devices)
interfaces = ( interfaces = (
Interface(device=device1, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[0], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device1, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[0], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device1, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[0], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device2, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[1], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device2, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[1], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device2, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[1], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device3, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[2], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device3, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[2], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device3, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[2], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device4, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[3], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device4, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[3], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=device4, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED), Interface(device=devices[3], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
) )
Interface.objects.bulk_create(interfaces) Interface.objects.bulk_create(interfaces)
@ -1109,7 +1210,7 @@ class CableTestCase(StandardTestCases.Views):
'termination_b_id': interfaces[3].pk, 'termination_b_id': interfaces[3].pk,
'type': CableTypeChoices.TYPE_CAT6, 'type': CableTypeChoices.TYPE_CAT6,
'status': CableStatusChoices.STATUS_PLANNED, 'status': CableStatusChoices.STATUS_PLANNED,
'label': 'New cable', 'label': 'Label',
'color': 'c0c0c0', 'color': 'c0c0c0',
'length': 100, 'length': 100,
'length_unit': CableLengthUnitChoices.UNIT_FOOT, 'length_unit': CableLengthUnitChoices.UNIT_FOOT,
@ -1122,6 +1223,15 @@ class CableTestCase(StandardTestCases.Views):
"Device 3,interface,Interface 3,Device 4,interface,Interface 3", "Device 3,interface,Interface 3,Device 4,interface,Interface 3",
) )
cls.bulk_edit_data = {
'type': CableTypeChoices.TYPE_CAT5E,
'status': CableStatusChoices.STATUS_CONNECTED,
'label': 'New label',
'color': '00ff00',
'length': 50,
'length_unit': CableLengthUnitChoices.UNIT_METER,
}
class VirtualChassisTestCase(StandardTestCases.Views): class VirtualChassisTestCase(StandardTestCases.Views):
model = VirtualChassis model = VirtualChassis
@ -1129,6 +1239,8 @@ class VirtualChassisTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_import_objects = None test_import_objects = None
test_bulk_edit_objects = None
test_bulk_delete_objects = None
# TODO: Requires special form handling # TODO: Requires special form handling
test_create_object = None test_create_object = None
@ -1173,3 +1285,114 @@ class VirtualChassisTestCase(StandardTestCases.Views):
Device.objects.filter(pk=device4.pk).update(virtual_chassis=vc2, vc_position=2) Device.objects.filter(pk=device4.pk).update(virtual_chassis=vc2, vc_position=2)
vc3 = VirtualChassis.objects.create(master=device5, domain='test-domain-3') vc3 = VirtualChassis.objects.create(master=device5, domain='test-domain-3')
Device.objects.filter(pk=device6.pk).update(virtual_chassis=vc3, vc_position=2) Device.objects.filter(pk=device6.pk).update(virtual_chassis=vc3, vc_position=2)
class PowerPanelTestCase(StandardTestCases.Views):
model = PowerPanel
# Disable inapplicable tests
test_bulk_edit_objects = None
@classmethod
def setUpTestData(cls):
sites = (
Site(name='Site 1', slug='site-1'),
Site(name='Site 2', slug='site-2'),
)
Site.objects.bulk_create(sites)
rackgroups = (
RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0]),
RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1]),
)
RackGroup.objects.bulk_create(rackgroups)
PowerPanel.objects.bulk_create((
PowerPanel(site=sites[0], rack_group=rackgroups[0], name='Power Panel 1'),
PowerPanel(site=sites[0], rack_group=rackgroups[0], name='Power Panel 2'),
PowerPanel(site=sites[0], rack_group=rackgroups[0], name='Power Panel 3'),
))
cls.form_data = {
'site': sites[1].pk,
'rack_group': rackgroups[1].pk,
'name': 'Power Panel X',
}
cls.csv_data = (
"site,rack_group_name,name",
"Site 1,Rack Group 1,Power Panel 4",
"Site 1,Rack Group 1,Power Panel 5",
"Site 1,Rack Group 1,Power Panel 6",
)
class PowerFeedTestCase(StandardTestCases.Views):
model = PowerFeed
# TODO: Re-enable this test once #4079 is fixed
test_bulk_edit_objects = None
@classmethod
def setUpTestData(cls):
site = Site.objects.create(name='Site 1', slug='site-1')
powerpanels = (
PowerPanel(site=site, name='Power Panel 1'),
PowerPanel(site=site, name='Power Panel 2'),
)
PowerPanel.objects.bulk_create(powerpanels)
racks = (
Rack(site=site, name='Rack 1'),
Rack(site=site, name='Rack 2'),
)
Rack.objects.bulk_create(racks)
PowerFeed.objects.bulk_create((
PowerFeed(name='Power Feed 1', power_panel=powerpanels[0], rack=racks[0]),
PowerFeed(name='Power Feed 2', power_panel=powerpanels[0], rack=racks[0]),
PowerFeed(name='Power Feed 3', power_panel=powerpanels[0], rack=racks[0]),
))
cls.form_data = {
'name': 'Power Feed X',
'power_panel': powerpanels[1].pk,
'rack': racks[1].pk,
'status': PowerFeedStatusChoices.STATUS_PLANNED,
'type': PowerFeedTypeChoices.TYPE_REDUNDANT,
'supply': PowerFeedSupplyChoices.SUPPLY_DC,
'phase': PowerFeedPhaseChoices.PHASE_3PHASE,
'voltage': 100,
'amperage': 100,
'max_utilization': 50,
'comments': 'New comments',
'tags': 'Alpha,Bravo,Charlie',
# Connection
'cable': None,
'connected_endpoint': None,
'connection_status': None,
}
cls.csv_data = (
"site,panel_name,name,voltage,amperage,max_utilization",
"Site 1,Power Panel 1,Power Feed 4,120,20,80",
"Site 1,Power Panel 1,Power Feed 5,120,20,80",
"Site 1,Power Panel 1,Power Feed 6,120,20,80",
)
cls.bulk_edit_data = {
'power_panel': powerpanels[1].pk,
'rack': racks[1].pk,
'status': PowerFeedStatusChoices.STATUS_PLANNED,
'type': PowerFeedTypeChoices.TYPE_REDUNDANT,
'supply': PowerFeedSupplyChoices.SUPPLY_DC,
'phase': PowerFeedPhaseChoices.PHASE_3PHASE,
'voltage': 100,
'amperage': 100,
'max_utilization': 50,
'comments': 'New comments',
}

View File

@ -318,7 +318,7 @@ urlpatterns = [
# Power feeds # Power feeds
path(r'power-feeds/', views.PowerFeedListView.as_view(), name='powerfeed_list'), path(r'power-feeds/', views.PowerFeedListView.as_view(), name='powerfeed_list'),
path(r'power-feeds/add/', views.PowerFeedEditView.as_view(), name='powerfeed_add'), path(r'power-feeds/add/', views.PowerFeedCreateView.as_view(), name='powerfeed_add'),
path(r'power-feeds/import/', views.PowerFeedBulkImportView.as_view(), name='powerfeed_import'), path(r'power-feeds/import/', views.PowerFeedBulkImportView.as_view(), name='powerfeed_import'),
path(r'power-feeds/edit/', views.PowerFeedBulkEditView.as_view(), name='powerfeed_bulk_edit'), path(r'power-feeds/edit/', views.PowerFeedBulkEditView.as_view(), name='powerfeed_bulk_edit'),
path(r'power-feeds/delete/', views.PowerFeedBulkDeleteView.as_view(), name='powerfeed_bulk_delete'), path(r'power-feeds/delete/', views.PowerFeedBulkDeleteView.as_view(), name='powerfeed_bulk_delete'),

View File

@ -33,6 +33,10 @@ class TagTestCase(StandardTestCases.Views):
'comments': 'Some comments', 'comments': 'Some comments',
} }
cls.bulk_edit_data = {
'color': '00ff00',
}
class ConfigContextTestCase(StandardTestCases.Views): class ConfigContextTestCase(StandardTestCases.Views):
model = ConfigContext model = ConfigContext
@ -53,7 +57,7 @@ class ConfigContextTestCase(StandardTestCases.Views):
for i in range(1, 4): for i in range(1, 4):
configcontext = ConfigContext( configcontext = ConfigContext(
name='Config Context {}'.format(i), name='Config Context {}'.format(i),
data='{{"foo": {}}}'.format(i) data={'foo': i}
) )
configcontext.save() configcontext.save()
configcontext.sites.add(site) configcontext.sites.add(site)
@ -73,7 +77,14 @@ class ConfigContextTestCase(StandardTestCases.Views):
'data': '{"foo": 123}', 'data': '{"foo": 123}',
} }
cls.bulk_edit_data = {
'weight': 300,
'is_active': False,
'description': 'New description',
}
# TODO: Convert to StandardTestCases.Views
class ObjectChangeTestCase(TestCase): class ObjectChangeTestCase(TestCase):
user_permissions = ( user_permissions = (
'extras.view_objectchange', 'extras.view_objectchange',

View File

@ -85,10 +85,9 @@ class TagBulkEditView(PermissionRequiredMixin, BulkEditView):
).order_by( ).order_by(
'name' 'name'
) )
# filter = filters.ProviderFilter
table = TagTable table = TagTable
form = forms.TagBulkEditForm form = forms.TagBulkEditForm
default_return_url = 'circuits:provider_list' default_return_url = 'extras:tag_list'
class TagBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class TagBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):

View File

@ -1392,5 +1392,5 @@ class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
class Meta: class Meta:
nullable_fields = [ nullable_fields = [
'site', 'tenant', 'role', 'description', 'description',
] ]

View File

@ -36,6 +36,12 @@ class VRFTestCase(StandardTestCases.Views):
"VRF 6", "VRF 6",
) )
cls.bulk_edit_data = {
'tenant': None,
'enforce_unique': False,
'description': 'New description',
}
class RIRTestCase(StandardTestCases.Views): class RIRTestCase(StandardTestCases.Views):
model = RIR model = RIR
@ -43,6 +49,7 @@ class RIRTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -73,18 +80,22 @@ class AggregateTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
rir = RIR.objects.create(name='RIR 1', slug='rir-1') rirs = (
RIR(name='RIR 1', slug='rir-1'),
RIR(name='RIR 2', slug='rir-2'),
)
RIR.objects.bulk_create(rirs)
Aggregate.objects.bulk_create([ Aggregate.objects.bulk_create([
Aggregate(family=4, prefix=IPNetwork('10.1.0.0/16'), rir=rir), Aggregate(family=4, prefix=IPNetwork('10.1.0.0/16'), rir=rirs[0]),
Aggregate(family=4, prefix=IPNetwork('10.2.0.0/16'), rir=rir), Aggregate(family=4, prefix=IPNetwork('10.2.0.0/16'), rir=rirs[0]),
Aggregate(family=4, prefix=IPNetwork('10.3.0.0/16'), rir=rir), Aggregate(family=4, prefix=IPNetwork('10.3.0.0/16'), rir=rirs[0]),
]) ])
cls.form_data = { cls.form_data = {
'family': 4, 'family': 4,
'prefix': IPNetwork('10.99.0.0/16'), 'prefix': IPNetwork('10.99.0.0/16'),
'rir': rir.pk, 'rir': rirs[1].pk,
'date_added': datetime.date(2020, 1, 1), 'date_added': datetime.date(2020, 1, 1),
'description': 'A new aggregate', 'description': 'A new aggregate',
'tags': 'Alpha,Bravo,Charlie', 'tags': 'Alpha,Bravo,Charlie',
@ -97,6 +108,12 @@ class AggregateTestCase(StandardTestCases.Views):
"10.6.0.0/16,RIR 1", "10.6.0.0/16,RIR 1",
) )
cls.bulk_edit_data = {
'rir': rirs[1].pk,
'date_added': datetime.date(2020, 1, 1),
'description': 'New description',
}
class RoleTestCase(StandardTestCases.Views): class RoleTestCase(StandardTestCases.Views):
model = Role model = Role
@ -104,6 +121,7 @@ class RoleTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -135,25 +153,37 @@ class PrefixTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
site = Site.objects.create(name='Site 1', slug='site-1') sites = (
vrf = VRF.objects.create(name='VRF 1', rd='65000:1') Site(name='Site 1', slug='site-1'),
role = Role.objects.create(name='Role 1', slug='role-1') Site(name='Site 2', slug='site-2'),
# vlan = VLAN.objects.create(vid=123, name='VLAN 123') )
Site.objects.bulk_create(sites)
vrfs = (
VRF(name='VRF 1', rd='65000:1'),
VRF(name='VRF 2', rd='65000:2'),
)
VRF.objects.bulk_create(vrfs)
roles = (
Role(name='Role 1', slug='role-1'),
Role(name='Role 2', slug='role-2'),
)
Prefix.objects.bulk_create([ Prefix.objects.bulk_create([
Prefix(family=4, prefix=IPNetwork('10.1.0.0/16'), site=site), Prefix(family=4, prefix=IPNetwork('10.1.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]),
Prefix(family=4, prefix=IPNetwork('10.2.0.0/16'), site=site), Prefix(family=4, prefix=IPNetwork('10.2.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]),
Prefix(family=4, prefix=IPNetwork('10.3.0.0/16'), site=site), Prefix(family=4, prefix=IPNetwork('10.3.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]),
]) ])
cls.form_data = { cls.form_data = {
'prefix': IPNetwork('192.0.2.0/24'), 'prefix': IPNetwork('192.0.2.0/24'),
'site': site.pk, 'site': sites[1].pk,
'vrf': vrf.pk, 'vrf': vrfs[1].pk,
'tenant': None, 'tenant': None,
'vlan': None, 'vlan': None,
'status': PrefixStatusChoices.STATUS_RESERVED, 'status': PrefixStatusChoices.STATUS_RESERVED,
'role': role.pk, 'role': roles[1].pk,
'is_pool': True, 'is_pool': True,
'description': 'A new prefix', 'description': 'A new prefix',
'tags': 'Alpha,Bravo,Charlie', 'tags': 'Alpha,Bravo,Charlie',
@ -166,6 +196,16 @@ class PrefixTestCase(StandardTestCases.Views):
"10.6.0.0/16,Active", "10.6.0.0/16,Active",
) )
cls.bulk_edit_data = {
'site': sites[1].pk,
'vrf': vrfs[1].pk,
'tenant': None,
'status': PrefixStatusChoices.STATUS_RESERVED,
'role': roles[1].pk,
'is_pool': False,
'description': 'New description',
}
class IPAddressTestCase(StandardTestCases.Views): class IPAddressTestCase(StandardTestCases.Views):
model = IPAddress model = IPAddress
@ -173,16 +213,19 @@ class IPAddressTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
vrf = VRF.objects.create(name='VRF 1', rd='65000:1') vrfs = (
VRF(name='VRF 1', rd='65000:1'),
VRF(name='VRF 2', rd='65000:2'),
)
IPAddress.objects.bulk_create([ IPAddress.objects.bulk_create([
IPAddress(family=4, address=IPNetwork('192.0.2.1/24'), vrf=vrf), IPAddress(family=4, address=IPNetwork('192.0.2.1/24'), vrf=vrfs[0]),
IPAddress(family=4, address=IPNetwork('192.0.2.2/24'), vrf=vrf), IPAddress(family=4, address=IPNetwork('192.0.2.2/24'), vrf=vrfs[0]),
IPAddress(family=4, address=IPNetwork('192.0.2.3/24'), vrf=vrf), IPAddress(family=4, address=IPNetwork('192.0.2.3/24'), vrf=vrfs[0]),
]) ])
cls.form_data = { cls.form_data = {
'vrf': vrf.pk, 'vrf': vrfs[1].pk,
'address': IPNetwork('192.0.2.99/24'), 'address': IPNetwork('192.0.2.99/24'),
'tenant': None, 'tenant': None,
'status': IPAddressStatusChoices.STATUS_RESERVED, 'status': IPAddressStatusChoices.STATUS_RESERVED,
@ -201,6 +244,15 @@ class IPAddressTestCase(StandardTestCases.Views):
"192.0.2.6/24,Active", "192.0.2.6/24,Active",
) )
cls.bulk_edit_data = {
'vrf': vrfs[1].pk,
'tenant': None,
'status': IPAddressStatusChoices.STATUS_RESERVED,
'role': IPAddressRoleChoices.ROLE_ANYCAST,
'dns_name': 'example',
'description': 'New description',
}
class VLANGroupTestCase(StandardTestCases.Views): class VLANGroupTestCase(StandardTestCases.Views):
model = VLANGroup model = VLANGroup
@ -208,6 +260,7 @@ class VLANGroupTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -240,24 +293,38 @@ class VLANTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
site = Site.objects.create(name='Site 1', slug='site-1') sites = (
vlangroup = VLANGroup.objects.create(name='VLAN Group 1', slug='vlan-group-1', site=site) Site(name='Site 1', slug='site-1'),
role = Role.objects.create(name='Role 1', slug='role-1') Site(name='Site 2', slug='site-2'),
)
Site.objects.bulk_create(sites)
vlangroups = (
VLANGroup(name='VLAN Group 1', slug='vlan-group-1', site=sites[0]),
VLANGroup(name='VLAN Group 2', slug='vlan-group-2', site=sites[1]),
)
VLANGroup.objects.bulk_create(vlangroups)
roles = (
Role(name='Role 1', slug='role-1'),
Role(name='Role 2', slug='role-2'),
)
Role.objects.bulk_create(roles)
VLAN.objects.bulk_create([ VLAN.objects.bulk_create([
VLAN(group=vlangroup, vid=101, name='VLAN101'), VLAN(group=vlangroups[0], vid=101, name='VLAN101', site=sites[0], role=roles[0]),
VLAN(group=vlangroup, vid=102, name='VLAN102'), VLAN(group=vlangroups[0], vid=102, name='VLAN102', site=sites[0], role=roles[0]),
VLAN(group=vlangroup, vid=103, name='VLAN103'), VLAN(group=vlangroups[0], vid=103, name='VLAN103', site=sites[0], role=roles[0]),
]) ])
cls.form_data = { cls.form_data = {
'site': site.pk, 'site': sites[1].pk,
'group': vlangroup.pk, 'group': vlangroups[1].pk,
'vid': 999, 'vid': 999,
'name': 'VLAN999', 'name': 'VLAN999',
'tenant': None, 'tenant': None,
'status': VLANStatusChoices.STATUS_RESERVED, 'status': VLANStatusChoices.STATUS_RESERVED,
'role': role.pk, 'role': roles[1].pk,
'description': 'A new VLAN', 'description': 'A new VLAN',
'tags': 'Alpha,Bravo,Charlie', 'tags': 'Alpha,Bravo,Charlie',
} }
@ -269,6 +336,15 @@ class VLANTestCase(StandardTestCases.Views):
"106,VLAN106,Active", "106,VLAN106,Active",
) )
cls.bulk_edit_data = {
'site': sites[1].pk,
'group': vlangroups[1].pk,
'tenant': None,
'status': VLANStatusChoices.STATUS_RESERVED,
'role': roles[1].pk,
'description': 'New description',
}
class ServiceTestCase(StandardTestCases.Views): class ServiceTestCase(StandardTestCases.Views):
model = Service model = Service
@ -304,3 +380,9 @@ class ServiceTestCase(StandardTestCases.Views):
'description': 'A new service', 'description': 'A new service',
'tags': 'Alpha,Bravo,Charlie', 'tags': 'Alpha,Bravo,Charlie',
} }
cls.bulk_edit_data = {
'protocol': ServiceProtocolChoices.PROTOCOL_UDP,
'port': 888,
'description': 'New description',
}

View File

@ -14,6 +14,7 @@ class SecretRoleTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -56,21 +57,38 @@ class SecretTestCase(StandardTestCases.Views):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1') devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1')
devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
device = Device.objects.create(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
secretrole = SecretRole.objects.create(name='Secret Role 1', slug='secret-role-1')
Secret.objects.bulk_create([ devices = (
Secret(device=device, role=secretrole, name='Secret 1', ciphertext=b'1234567890'), Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole),
Secret(device=device, role=secretrole, name='Secret 2', ciphertext=b'1234567890'), Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole),
Secret(device=device, role=secretrole, name='Secret 3', ciphertext=b'1234567890'), Device(name='Device 3', site=site, device_type=devicetype, device_role=devicerole),
]) )
Device.objects.bulk_create(devices)
secretroles = (
SecretRole(name='Secret Role 1', slug='secret-role-1'),
SecretRole(name='Secret Role 2', slug='secret-role-2'),
)
SecretRole.objects.bulk_create(secretroles)
# Create one secret per device to allow bulk-editing of names (which must be unique per device/role)
Secret.objects.bulk_create((
Secret(device=devices[0], role=secretroles[0], name='Secret 1', ciphertext=b'1234567890'),
Secret(device=devices[1], role=secretroles[0], name='Secret 2', ciphertext=b'1234567890'),
Secret(device=devices[2], role=secretroles[0], name='Secret 3', ciphertext=b'1234567890'),
))
cls.form_data = { cls.form_data = {
'device': device.pk, 'device': devices[1].pk,
'role': secretrole.pk, 'role': secretroles[1].pk,
'name': 'Secret X', 'name': 'Secret X',
} }
cls.bulk_edit_data = {
'role': secretroles[1].pk,
'name': 'New name',
}
def setUp(self): def setUp(self):
super().setUp() super().setUp()

View File

@ -8,6 +8,7 @@ class TenantGroupTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -37,18 +38,22 @@ class TenantTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
tenantgroup = TenantGroup.objects.create(name='Tenant Group 1', slug='tenant-group-1') tenantgroups = (
TenantGroup(name='Tenant Group 1', slug='tenant-group-1'),
TenantGroup(name='Tenant Group 2', slug='tenant-group-2'),
)
TenantGroup.objects.bulk_create(tenantgroups)
Tenant.objects.bulk_create([ Tenant.objects.bulk_create([
Tenant(name='Tenant 1', slug='tenant-1', group=tenantgroup), Tenant(name='Tenant 1', slug='tenant-1', group=tenantgroups[0]),
Tenant(name='Tenant 2', slug='tenant-2', group=tenantgroup), Tenant(name='Tenant 2', slug='tenant-2', group=tenantgroups[0]),
Tenant(name='Tenant 3', slug='tenant-3', group=tenantgroup), Tenant(name='Tenant 3', slug='tenant-3', group=tenantgroups[0]),
]) ])
cls.form_data = { cls.form_data = {
'name': 'Tenant X', 'name': 'Tenant X',
'slug': 'tenant-x', 'slug': 'tenant-x',
'group': tenantgroup.pk, 'group': tenantgroups[1].pk,
'description': 'A new tenant', 'description': 'A new tenant',
'comments': 'Some comments', 'comments': 'Some comments',
'tags': 'Alpha,Bravo,Charlie', 'tags': 'Alpha,Bravo,Charlie',
@ -60,3 +65,7 @@ class TenantTestCase(StandardTestCases.Views):
"Tenant 5,tenant-5", "Tenant 5,tenant-5",
"Tenant 6,tenant-6", "Tenant 6,tenant-6",
) )
cls.bulk_edit_data = {
'group': tenantgroups[1].pk,
}

View File

@ -85,8 +85,15 @@ class StandardTestCases:
- Import multiple new objects - Import multiple new objects
""" """
model = None model = None
# Data to be sent when creating/editing individual objects
form_data = {} form_data = {}
csv_data = {}
# CSV lines used for bulk import of new objects
csv_data = ()
# Form data to be used when editing multiple objects at once
bulk_edit_data = {}
maxDiff = None maxDiff = None
@ -107,7 +114,7 @@ class StandardTestCases:
self.model._meta.model_name self.model._meta.model_name
) )
if action in ('list', 'add', 'import'): if action in ('list', 'add', 'import', 'bulk_edit', 'bulk_delete'):
return reverse(url_format.format(action)) return reverse(url_format.format(action))
elif action in ('get', 'edit', 'delete'): elif action in ('get', 'edit', 'delete'):
@ -253,3 +260,66 @@ class StandardTestCases:
self.assertHttpStatus(response, 200) self.assertHttpStatus(response, 200)
self.assertEqual(self.model.objects.count(), initial_count + len(self.csv_data) - 1) self.assertEqual(self.model.objects.count(), initial_count + len(self.csv_data) - 1)
@override_settings(EXEMPT_VIEW_PERMISSIONS=[])
def test_bulk_edit_objects(self):
pk_list = self.model.objects.values_list('pk', flat=True)
request = {
'path': self._get_url('bulk_edit'),
'data': {
'pk': pk_list,
'_apply': True, # Form button
},
'follow': False, # Do not follow 302 redirects
}
# Append the form data to the request
request['data'].update(post_data(self.bulk_edit_data))
# Attempt to make the request without required permissions
with disable_warnings('django.request'):
self.assertHttpStatus(self.client.post(**request), 403)
# Assign the required permission and submit again
self.add_permissions(
'{}.change_{}'.format(self.model._meta.app_label, self.model._meta.model_name)
)
response = self.client.post(**request)
self.assertHttpStatus(response, 302)
bulk_edit_fields = self.bulk_edit_data.keys()
for i, instance in enumerate(self.model.objects.filter(pk__in=pk_list)):
self.assertDictEqual(
model_to_dict(instance, fields=bulk_edit_fields),
self.bulk_edit_data,
msg="Instance {} failed to validate after bulk edit: {}".format(i, instance)
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=[])
def test_bulk_delete_objects(self):
pk_list = self.model.objects.values_list('pk', flat=True)
request = {
'path': self._get_url('bulk_delete'),
'data': {
'pk': pk_list,
'confirm': True,
'_confirm': True, # Form button
},
'follow': False, # Do not follow 302 redirects
}
# Attempt to make the request without required permissions
with disable_warnings('django.request'):
self.assertHttpStatus(self.client.post(**request), 403)
# Assign the required permission and submit again
self.add_permissions(
'{}.delete_{}'.format(self.model._meta.app_label, self.model._meta.model_name)
)
response = self.client.post(**request)
self.assertHttpStatus(response, 302)
# Check that all objects were deleted
self.assertEqual(self.model.objects.count(), 0)

View File

@ -4,11 +4,10 @@ from copy import deepcopy
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError from django.core.exceptions import FieldDoesNotExist, ValidationError
from django.db import transaction, IntegrityError from django.db import transaction, IntegrityError
from django.db.models import Count, ManyToManyField, ProtectedError from django.db.models import Count, ManyToManyField, ProtectedError
from django.db.models.query import QuerySet from django.forms import Form, ModelMultipleChoiceField, MultipleHiddenInput, Textarea
from django.forms import CharField, Form, ModelMultipleChoiceField, MultipleHiddenInput, Textarea
from django.http import HttpResponse, HttpResponseServerError from django.http import HttpResponse, HttpResponseServerError
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.template import loader from django.template import loader
@ -651,7 +650,7 @@ class BulkEditView(GetReturnURLMixin, View):
custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else [] custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else []
standard_fields = [ standard_fields = [
field for field in form.fields if field not in custom_fields + ['pk', 'add_tags', 'remove_tags'] field for field in form.fields if field not in custom_fields + ['pk']
] ]
nullified_fields = request.POST.getlist('_nullify') nullified_fields = request.POST.getlist('_nullify')
@ -665,7 +664,12 @@ class BulkEditView(GetReturnURLMixin, View):
# Update standard fields. If a field is listed in _nullify, delete its value. # Update standard fields. If a field is listed in _nullify, delete its value.
for name in standard_fields: for name in standard_fields:
model_field = model._meta.get_field(name) try:
model_field = model._meta.get_field(name)
except FieldDoesNotExist:
# The form field is used to modify a field rather than set its value directly,
# so we skip it.
continue
# Handle nullification # Handle nullification
if name in form.nullable_fields and name in nullified_fields: if name in form.nullable_fields and name in nullified_fields:

View File

@ -10,6 +10,7 @@ class ClusterGroupTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -39,6 +40,7 @@ class ClusterTypeTestCase(StandardTestCases.Views):
# Disable inapplicable tests # Disable inapplicable tests
test_get_object = None test_get_object = None
test_delete_object = None test_delete_object = None
test_bulk_edit_objects = None
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -68,22 +70,36 @@ class ClusterTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
site = Site.objects.create(name='Site 1', slug='site-1') sites = (
clustergroup = ClusterGroup.objects.create(name='Cluster Group 1', slug='cluster-group-1') Site(name='Site 1', slug='site-1'),
clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') Site(name='Site 2', slug='site-2'),
)
Site.objects.bulk_create(sites)
clustergroups = (
ClusterGroup(name='Cluster Group 1', slug='cluster-group-1'),
ClusterGroup(name='Cluster Group 2', slug='cluster-group-2'),
)
ClusterGroup.objects.bulk_create(clustergroups)
clustertypes = (
ClusterType(name='Cluster Type 1', slug='cluster-type-1'),
ClusterType(name='Cluster Type 2', slug='cluster-type-2'),
)
ClusterType.objects.bulk_create(clustertypes)
Cluster.objects.bulk_create([ Cluster.objects.bulk_create([
Cluster(name='Cluster 1', group=clustergroup, type=clustertype), Cluster(name='Cluster 1', group=clustergroups[0], type=clustertypes[0], site=sites[0]),
Cluster(name='Cluster 2', group=clustergroup, type=clustertype), Cluster(name='Cluster 2', group=clustergroups[0], type=clustertypes[0], site=sites[0]),
Cluster(name='Cluster 3', group=clustergroup, type=clustertype), Cluster(name='Cluster 3', group=clustergroups[0], type=clustertypes[0], site=sites[0]),
]) ])
cls.form_data = { cls.form_data = {
'name': 'Cluster X', 'name': 'Cluster X',
'group': clustergroup.pk, 'group': clustergroups[1].pk,
'type': clustertype.pk, 'type': clustertypes[1].pk,
'tenant': None, 'tenant': None,
'site': site.pk, 'site': sites[1].pk,
'comments': 'Some comments', 'comments': 'Some comments',
'tags': 'Alpha,Bravo,Charlie', 'tags': 'Alpha,Bravo,Charlie',
} }
@ -95,6 +111,14 @@ class ClusterTestCase(StandardTestCases.Views):
"Cluster 6,Cluster Type 1", "Cluster 6,Cluster Type 1",
) )
cls.bulk_edit_data = {
'group': clustergroups[1].pk,
'type': clustertypes[1].pk,
'tenant': None,
'site': sites[1].pk,
'comments': 'New comments',
}
class VirtualMachineTestCase(StandardTestCases.Views): class VirtualMachineTestCase(StandardTestCases.Views):
model = VirtualMachine model = VirtualMachine
@ -102,24 +126,39 @@ class VirtualMachineTestCase(StandardTestCases.Views):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') deviceroles = (
platform = Platform.objects.create(name='Platform 1', slug='platform-1') DeviceRole(name='Device Role 1', slug='device-role-1'),
DeviceRole(name='Device Role 2', slug='device-role-2'),
)
DeviceRole.objects.bulk_create(deviceroles)
platforms = (
Platform(name='Platform 1', slug='platform-1'),
Platform(name='Platform 2', slug='platform-2'),
)
Platform.objects.bulk_create(platforms)
clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
cluster = Cluster.objects.create(name='Cluster 1', type=clustertype)
clusters = (
Cluster(name='Cluster 1', type=clustertype),
Cluster(name='Cluster 2', type=clustertype),
)
Cluster.objects.bulk_create(clusters)
VirtualMachine.objects.bulk_create([ VirtualMachine.objects.bulk_create([
VirtualMachine(name='Virtual Machine 1', cluster=cluster), VirtualMachine(name='Virtual Machine 1', cluster=clusters[0], role=deviceroles[0], platform=platforms[0]),
VirtualMachine(name='Virtual Machine 2', cluster=cluster), VirtualMachine(name='Virtual Machine 2', cluster=clusters[0], role=deviceroles[0], platform=platforms[0]),
VirtualMachine(name='Virtual Machine 3', cluster=cluster), VirtualMachine(name='Virtual Machine 3', cluster=clusters[0], role=deviceroles[0], platform=platforms[0]),
]) ])
cls.form_data = { cls.form_data = {
'cluster': cluster.pk, 'cluster': clusters[1].pk,
'tenant': None, 'tenant': None,
'platform': None, 'platform': platforms[1].pk,
'name': 'Virtual Machine X', 'name': 'Virtual Machine X',
'status': VirtualMachineStatusChoices.STATUS_STAGED, 'status': VirtualMachineStatusChoices.STATUS_STAGED,
'role': devicerole.pk, 'role': deviceroles[1].pk,
'primary_ip4': None, 'primary_ip4': None,
'primary_ip6': None, 'primary_ip6': None,
'vcpus': 4, 'vcpus': 4,
@ -136,3 +175,15 @@ class VirtualMachineTestCase(StandardTestCases.Views):
"Virtual Machine 5,Cluster 1", "Virtual Machine 5,Cluster 1",
"Virtual Machine 6,Cluster 1", "Virtual Machine 6,Cluster 1",
) )
cls.bulk_edit_data = {
'cluster': clusters[1].pk,
'tenant': None,
'platform': platforms[1].pk,
'status': VirtualMachineStatusChoices.STATUS_STAGED,
'role': deviceroles[1].pk,
'vcpus': 8,
'memory': 65535,
'disk': 8000,
'comments': 'New comments',
}