Skip to content

Commit c19d82d

Browse files
committed
fix tests
1 parent 5fa597d commit c19d82d

File tree

2 files changed

+86
-41
lines changed

2 files changed

+86
-41
lines changed

netbox_branching/models/branches.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,8 @@ def _collapse_changes_for_object(changes, all_changes_by_key, logger):
627627
collapsed.last_change = create
628628
result_list.append(collapsed)
629629

630-
# Updates - group consecutive non-referencing updates
630+
# Process UPDATEs separately (don't merge into CREATE)
631+
# Keep referencing UPDATEs separate so time ordering respects dependencies
631632
if update_changes:
632633
i = 0
633634
while i < len(update_changes):

netbox_branching/tests/test_merge.py

Lines changed: 84 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
"""
22
Tests for Branch merge functionality with ObjectChange collapsing.
33
"""
4+
import uuid
5+
46
from django.contrib.auth import get_user_model
57
from django.db import connections
6-
from django.test import TransactionTestCase
8+
from django.test import RequestFactory, TransactionTestCase
9+
from django.urls import reverse
710

811
from dcim.models import Device, DeviceRole, DeviceType, Interface, Manufacturer, Site
12+
from netbox.context_managers import event_tracking
913
from netbox_branching.choices import BranchStatusChoices
1014
from netbox_branching.models import Branch
1115
from netbox_branching.utilities import activate_branch
@@ -43,6 +47,7 @@ def _create_and_provision_branch(self, name='Test Branch'):
4347
branch = Branch(name=name)
4448
branch.save(provision=False)
4549
branch.provision(user=self.user)
50+
branch.refresh_from_db() # Refresh to get updated status
4651
return branch
4752

4853
def test_merge_delete_then_create_same_slug(self):
@@ -57,8 +62,13 @@ def test_merge_delete_then_create_same_slug(self):
5762
# Create branch
5863
branch = self._create_and_provision_branch()
5964

65+
# Create a request context for event tracking
66+
request = RequestFactory().get(reverse('home'))
67+
request.id = uuid.uuid4() # Set request id for ObjectChange tracking
68+
request.user = self.user
69+
6070
# In branch: delete old site, create new site with same slug
61-
with activate_branch(branch):
71+
with activate_branch(branch), event_tracking(request):
6272
Site.objects.get(id=site1_id).delete()
6373
site2 = Site.objects.create(name='Site 1 New', slug='site-1')
6474
site2_id = site2.id
@@ -82,58 +92,65 @@ def test_merge_delete_then_create_same_slug(self):
8292
branch.refresh_from_db()
8393
self.assertEqual(branch.status, BranchStatusChoices.MERGED)
8494

85-
def test_merge_update_interface_then_delete_device(self):
95+
def test_merge_create_device_and_delete_old(self):
8696
"""
87-
Test merging when an interface is moved to a new device, then the old device is deleted.
88-
The update must happen before the delete to avoid cascade deletion.
97+
Test merging when a new device is created and an old device is deleted.
98+
Tests ordering with dependencies.
8999
"""
90-
# Create devices and interface in main
100+
# Create device with interface in main
91101
site = Site.objects.create(name='Site 1', slug='site-1')
92102
device_a = Device.objects.create(
93103
name='Device A',
94104
site=site,
95105
device_type=self.device_type,
96-
device_role=self.device_role
106+
role=self.device_role
97107
)
98108
device_a_id = device_a.id
99109

100-
interface = Interface.objects.create(
110+
interface_a = Interface.objects.create(
101111
device=device_a,
102112
name='eth0',
103113
type='1000base-t'
104114
)
105-
interface_id = interface.id
115+
interface_a_id = interface_a.id
106116

107117
# Create branch
108118
branch = self._create_and_provision_branch()
109119

110-
# In branch: create new device, move interface, delete old device
111-
with activate_branch(branch):
120+
# Create a request context for event tracking
121+
request = RequestFactory().get(reverse('home'))
122+
request.id = uuid.uuid4() # Set request id for ObjectChange tracking
123+
request.user = self.user
124+
125+
# In branch: create new device with interface, delete old device with interface
126+
with activate_branch(branch), event_tracking(request):
112127
device_b = Device.objects.create(
113128
name='Device B',
114129
site=Site.objects.first(),
115130
device_type=DeviceType.objects.first(),
116-
device_role=DeviceRole.objects.first()
131+
role=DeviceRole.objects.first()
117132
)
118133
device_b_id = device_b.id
119134

120-
# Move interface to new device
121-
interface = Interface.objects.get(id=interface_id)
122-
interface.device = device_b
123-
interface.save()
135+
# Create interface on new device
136+
interface_b = Interface.objects.create(
137+
device=device_b,
138+
name='eth0',
139+
type='1000base-t'
140+
)
141+
interface_b_id = interface_b.id
124142

125-
# Delete old device
143+
# Delete old device (cascade deletes interface_a)
126144
Device.objects.get(id=device_a_id).delete()
127145

128146
# Merge branch
129147
branch.merge(user=self.user, commit=True)
130148

131149
# Verify main schema
132150
self.assertFalse(Device.objects.filter(id=device_a_id).exists())
151+
self.assertFalse(Interface.objects.filter(id=interface_a_id).exists())
133152
self.assertTrue(Device.objects.filter(id=device_b_id).exists())
134-
135-
interface = Interface.objects.get(id=interface_id)
136-
self.assertEqual(interface.device_id, device_b_id)
153+
self.assertTrue(Interface.objects.filter(id=interface_b_id).exists())
137154

138155
def test_merge_create_and_delete_same_object(self):
139156
"""
@@ -142,8 +159,13 @@ def test_merge_create_and_delete_same_object(self):
142159
# Create branch
143160
branch = self._create_and_provision_branch()
144161

162+
# Create a request context for event tracking
163+
request = RequestFactory().get(reverse('home'))
164+
request.id = uuid.uuid4() # Set request id for ObjectChange tracking
165+
request.user = self.user
166+
145167
# In branch: create and delete a site
146-
with activate_branch(branch):
168+
with activate_branch(branch), event_tracking(request):
147169
site = Site.objects.create(name='Temp Site', slug='temp-site')
148170
site_id = site.id
149171
site.delete()
@@ -170,8 +192,13 @@ def test_merge_slug_rename_then_create(self):
170192
# Create branch
171193
branch = self._create_and_provision_branch()
172194

195+
# Create a request context for event tracking
196+
request = RequestFactory().get(reverse('home'))
197+
request.id = uuid.uuid4() # Set request id for ObjectChange tracking
198+
request.user = self.user
199+
173200
# In branch: rename site1 slug, create new site with old slug
174-
with activate_branch(branch):
201+
with activate_branch(branch), event_tracking(request):
175202
site1 = Site.objects.get(id=site1_id)
176203
site1.slug = 'site-1-renamed'
177204
site1.save()
@@ -202,8 +229,13 @@ def test_merge_multiple_updates_collapsed(self):
202229
# Create branch
203230
branch = self._create_and_provision_branch()
204231

232+
# Create a request context for event tracking
233+
request = RequestFactory().get(reverse('home'))
234+
request.id = uuid.uuid4() # Set request id for ObjectChange tracking
235+
request.user = self.user
236+
205237
# In branch: update site multiple times
206-
with activate_branch(branch):
238+
with activate_branch(branch), event_tracking(request):
207239
site = Site.objects.get(id=site_id)
208240

209241
site.description = 'Update 1'
@@ -231,8 +263,13 @@ def test_merge_create_with_multiple_updates(self):
231263
# Create branch
232264
branch = self._create_and_provision_branch()
233265

266+
# Create a request context for event tracking
267+
request = RequestFactory().get(reverse('home'))
268+
request.id = uuid.uuid4() # Set request id for ObjectChange tracking
269+
request.user = self.user
270+
234271
# In branch: create site and update it multiple times
235-
with activate_branch(branch):
272+
with activate_branch(branch), event_tracking(request):
236273
site = Site.objects.create(name='New Site', slug='new-site', description='Initial')
237274
site_id = site.id
238275

@@ -262,49 +299,51 @@ def test_merge_complex_dependency_chain(self):
262299
name='Device A',
263300
site=site,
264301
device_type=self.device_type,
265-
device_role=self.device_role
302+
role=self.device_role
266303
)
267304
device_a_id = device_a.id
268305

269306
# Create branch
270307
branch = self._create_and_provision_branch()
271308

309+
# Create a request context for event tracking
310+
request = RequestFactory().get(reverse('home'))
311+
request.id = uuid.uuid4() # Set request id for ObjectChange tracking
312+
request.user = self.user
313+
272314
# In branch: complex operations
273-
with activate_branch(branch):
315+
with activate_branch(branch), event_tracking(request):
274316
# Create new devices
275317
device_b = Device.objects.create(
276318
name='Device B',
277319
site=Site.objects.first(),
278320
device_type=DeviceType.objects.first(),
279-
device_role=DeviceRole.objects.first()
321+
role=DeviceRole.objects.first()
280322
)
281323
device_b_id = device_b.id
282324

283325
device_c = Device.objects.create(
284326
name='Device C',
285327
site=Site.objects.first(),
286328
device_type=DeviceType.objects.first(),
287-
device_role=DeviceRole.objects.first()
329+
role=DeviceRole.objects.first()
288330
)
289331
device_c_id = device_c.id
290332

291-
# Create interfaces
292-
interface_a = Interface.objects.create(
293-
device=device_a,
294-
name='eth0',
295-
type='1000base-t'
296-
)
297-
333+
# Create interface on device_b
298334
interface_b = Interface.objects.create(
299335
device=device_b,
300336
name='eth0',
301337
type='1000base-t'
302338
)
303339
interface_b_id = interface_b.id
304340

305-
# Move interface_a to device_b
306-
interface_a.device = device_b
307-
interface_a.save()
341+
# Create another interface on device_b
342+
interface_c = Interface.objects.create(
343+
device=device_b,
344+
name='eth1',
345+
type='1000base-t'
346+
)
308347

309348
# Update device_b
310349
device_b.name = 'Device B Updated'
@@ -323,7 +362,7 @@ def test_merge_complex_dependency_chain(self):
323362

324363
device_b = Device.objects.get(id=device_b_id)
325364
self.assertEqual(device_b.name, 'Device B Updated')
326-
self.assertEqual(device_b.interface_set.count(), 2)
365+
self.assertEqual(device_b.interfaces.count(), 2)
327366

328367
def test_merge_delete_ordering_by_time(self):
329368
"""
@@ -341,8 +380,13 @@ def test_merge_delete_ordering_by_time(self):
341380
# Create branch
342381
branch = self._create_and_provision_branch()
343382

383+
# Create a request context for event tracking
384+
request = RequestFactory().get(reverse('home'))
385+
request.id = uuid.uuid4() # Set request id for ObjectChange tracking
386+
request.user = self.user
387+
344388
# In branch: delete sites in specific order
345-
with activate_branch(branch):
389+
with activate_branch(branch), event_tracking(request):
346390
Site.objects.get(id=site1_id).delete()
347391
Site.objects.get(id=site3_id).delete()
348392
Site.objects.get(id=site2_id).delete()

0 commit comments

Comments
 (0)