Skip to content

Commit

Permalink
Fixes #15925: Fix rendering of cable traces to circuit terminations
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremystretch committed May 3, 2024
1 parent 39a8307 commit f33d0be
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 3 deletions.
7 changes: 4 additions & 3 deletions netbox/dcim/svg/cables.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def draw_object_terminations(self, terminations, offset_x, width):
nodes_height = 0
nodes = []
# Sort them by name to make renders more readable
for i, term in enumerate(sorted(terminations, key=lambda x: x.name)):
for i, term in enumerate(sorted(terminations, key=lambda x: str(x))):
node = Node(
position=(offset_x + i * width, self.cursor),
width=width,
Expand Down Expand Up @@ -266,7 +266,7 @@ def draw_far_objects(self, obj_list, terminations):
Draw the far-end objects and its terminations and return all created nodes
"""
# Make sure elements are sorted by name for readability
objects = sorted(obj_list, key=lambda x: x.name)
objects = sorted(obj_list, key=lambda x: str(x))
width = self.width / len(objects)

# Max-height of created terminations
Expand Down Expand Up @@ -361,7 +361,8 @@ def render(self):
# Connector (a Cable or WirelessLink)
if links:

parent_object_nodes, far_terminations = self.draw_far_objects(set(end.parent_object for end in far_ends), far_ends)
obj_list = {end.parent_object for end in far_ends}
parent_object_nodes, far_terminations = self.draw_far_objects(obj_list, far_ends)
for cable in links:
# Fill in labels and description with all available data
description = [
Expand Down
63 changes: 63 additions & 0 deletions netbox/dcim/tests/test_cablepaths.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ def test_201_single_path_via_pass_through(self):
)
self.assertEqual(CablePath.objects.count(), 2)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 2
cable2.delete()
path1 = self.assertPathExists(
Expand Down Expand Up @@ -450,6 +453,9 @@ def test_202_single_path_via_pass_through_with_breakouts(self):
)
self.assertEqual(CablePath.objects.count(), 2)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 2
cable2.delete()
path1 = self.assertPathExists(
Expand Down Expand Up @@ -558,6 +564,9 @@ def test_203_multiple_paths_via_pass_through(self):
)
self.assertEqual(CablePath.objects.count(), 4)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 3
cable3.delete()

Expand Down Expand Up @@ -673,6 +682,9 @@ def test_204_multiple_paths_via_pass_through_with_breakouts(self):
)
self.assertEqual(CablePath.objects.count(), 4)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 3
cable3.delete()

Expand Down Expand Up @@ -804,6 +816,9 @@ def test_205_multiple_paths_via_nested_pass_throughs(self):
)
self.assertEqual(CablePath.objects.count(), 4)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 3
cable3.delete()

Expand Down Expand Up @@ -931,6 +946,9 @@ def test_206_multiple_paths_via_multiple_pass_throughs(self):
)
self.assertEqual(CablePath.objects.count(), 4)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 5
cable5.delete()

Expand Down Expand Up @@ -1034,6 +1052,9 @@ def test_207_multiple_paths_via_patched_pass_throughs(self):
)
self.assertEqual(CablePath.objects.count(), 4)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 3
cable3.delete()

Expand Down Expand Up @@ -1093,6 +1114,9 @@ def test_208_unidirectional_split_paths(self):
)
self.assertEqual(CablePath.objects.count(), 3)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 1
cable1.delete()

Expand Down Expand Up @@ -1135,6 +1159,9 @@ def test_209_rearport_without_frontport(self):
)
self.assertEqual(CablePath.objects.count(), 1)

# Test SVG generation
CableTraceSVG(interface1).render()

def test_210_interface_to_circuittermination(self):
"""
[IF1] --C1-- [CT1]
Expand All @@ -1156,6 +1183,9 @@ def test_210_interface_to_circuittermination(self):
)
self.assertEqual(CablePath.objects.count(), 1)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 1
cable1.delete()
self.assertEqual(CablePath.objects.count(), 0)
Expand Down Expand Up @@ -1212,6 +1242,9 @@ def test_211_interface_to_interface_via_circuit(self):
)
self.assertEqual(CablePath.objects.count(), 2)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 2
cable2.delete()
path1 = self.assertPathExists(
Expand Down Expand Up @@ -1277,6 +1310,9 @@ def test_212_interface_to_interface_via_circuit_with_breakouts(self):
)
self.assertEqual(CablePath.objects.count(), 2)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 2
cable2.delete()
path1 = self.assertPathExists(
Expand Down Expand Up @@ -1314,6 +1350,9 @@ def test_213_interface_to_site_via_circuit(self):
)
self.assertEqual(CablePath.objects.count(), 1)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 1
cable1.delete()
self.assertEqual(CablePath.objects.count(), 0)
Expand Down Expand Up @@ -1342,6 +1381,9 @@ def test_214_interface_to_providernetwork_via_circuit(self):
self.assertEqual(CablePath.objects.count(), 1)
self.assertTrue(CablePath.objects.first().is_complete)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 1
cable1.delete()
self.assertEqual(CablePath.objects.count(), 0)
Expand Down Expand Up @@ -1439,6 +1481,9 @@ def test_215_multiple_paths_via_circuit(self):
)
self.assertEqual(CablePath.objects.count(), 4)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cables 3-4
cable3.delete()
cable4.delete()
Expand Down Expand Up @@ -1495,6 +1540,9 @@ def test_216_interface_to_interface_via_multiple_circuits(self):
)
self.assertEqual(CablePath.objects.count(), 2)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 2
cable2.delete()
path1 = self.assertPathExists(
Expand Down Expand Up @@ -1578,6 +1626,9 @@ def test_217_interface_to_interface_via_rear_ports(self):
)
self.assertEqual(CablePath.objects.count(), 2)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 2
cable2.delete()

Expand Down Expand Up @@ -1697,6 +1748,9 @@ def test_218_interfaces_to_interfaces_via_multiposition_rear_ports(self):
)
self.assertEqual(CablePath.objects.count(), 4)

# Test SVG generation
CableTraceSVG(interface1).render()

# Delete cable 3
cable3.delete()

Expand Down Expand Up @@ -1784,6 +1838,9 @@ def test_219_interface_to_interface_duplex_via_multiple_rearports(self):
)
self.assertEqual(CablePath.objects.count(), 2)

# Test SVG generation
CableTraceSVG(interface1).render()

def test_220_interface_to_interface_duplex_via_multiple_front_and_rear_ports(self):
"""
[IF1] --C1-- [FP1] [RP1] --C2-- [RP2] [FP2] --C3-- [IF2]
Expand Down Expand Up @@ -1877,6 +1934,9 @@ def test_220_interface_to_interface_duplex_via_multiple_front_and_rear_ports(sel
)
self.assertEqual(CablePath.objects.count(), 3)

# Test SVG generation
CableTraceSVG(interface1).render()

def test_221_non_symmetric_paths(self):
"""
[IF1] --C1-- [FP1] [RP1] --C2-- [RP2] [FP2] --C3-- -------------------------------------- [IF2]
Expand Down Expand Up @@ -1997,6 +2057,9 @@ def test_221_non_symmetric_paths(self):
)
self.assertEqual(CablePath.objects.count(), 3)

# Test SVG generation
CableTraceSVG(interface1).render()

def test_301_create_path_via_existing_cable(self):
"""
[IF1] --C1-- [FP1] [RP1] --C2-- [RP2] [FP2] --C3-- [IF2]
Expand Down

0 comments on commit f33d0be

Please sign in to comment.