From c8a9bc006d7ba784a38655a9a91f0297e0a887a4 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 3 May 2024 08:33:47 -0400 Subject: [PATCH] Fixes #15925: Fix rendering of cable traces to circuit terminations --- netbox/dcim/svg/cables.py | 7 ++-- netbox/dcim/tests/test_cablepaths.py | 63 ++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/netbox/dcim/svg/cables.py b/netbox/dcim/svg/cables.py index 596f0c6bf..82eb9a417 100644 --- a/netbox/dcim/svg/cables.py +++ b/netbox/dcim/svg/cables.py @@ -223,7 +223,7 @@ class CableTraceSVG: 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, @@ -266,7 +266,7 @@ class CableTraceSVG: 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 @@ -361,7 +361,8 @@ class CableTraceSVG: # 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 = [ diff --git a/netbox/dcim/tests/test_cablepaths.py b/netbox/dcim/tests/test_cablepaths.py index a827939f7..66f712ff7 100644 --- a/netbox/dcim/tests/test_cablepaths.py +++ b/netbox/dcim/tests/test_cablepaths.py @@ -394,6 +394,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 2) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 2 cable2.delete() path1 = self.assertPathExists( @@ -450,6 +453,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 2) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 2 cable2.delete() path1 = self.assertPathExists( @@ -558,6 +564,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 4) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 3 cable3.delete() @@ -673,6 +682,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 4) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 3 cable3.delete() @@ -804,6 +816,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 4) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 3 cable3.delete() @@ -931,6 +946,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 4) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 5 cable5.delete() @@ -1034,6 +1052,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 4) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 3 cable3.delete() @@ -1093,6 +1114,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 3) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 1 cable1.delete() @@ -1135,6 +1159,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 1) + # Test SVG generation + CableTraceSVG(interface1).render() + def test_210_interface_to_circuittermination(self): """ [IF1] --C1-- [CT1] @@ -1156,6 +1183,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 1) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 1 cable1.delete() self.assertEqual(CablePath.objects.count(), 0) @@ -1212,6 +1242,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 2) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 2 cable2.delete() path1 = self.assertPathExists( @@ -1277,6 +1310,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 2) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 2 cable2.delete() path1 = self.assertPathExists( @@ -1314,6 +1350,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 1) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 1 cable1.delete() self.assertEqual(CablePath.objects.count(), 0) @@ -1342,6 +1381,9 @@ class CablePathTestCase(TestCase): 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) @@ -1439,6 +1481,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 4) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cables 3-4 cable3.delete() cable4.delete() @@ -1495,6 +1540,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 2) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 2 cable2.delete() path1 = self.assertPathExists( @@ -1578,6 +1626,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 2) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 2 cable2.delete() @@ -1697,6 +1748,9 @@ class CablePathTestCase(TestCase): ) self.assertEqual(CablePath.objects.count(), 4) + # Test SVG generation + CableTraceSVG(interface1).render() + # Delete cable 3 cable3.delete() @@ -1784,6 +1838,9 @@ class CablePathTestCase(TestCase): ) 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] @@ -1877,6 +1934,9 @@ class CablePathTestCase(TestCase): ) 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] @@ -1997,6 +2057,9 @@ class CablePathTestCase(TestCase): ) 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]