diff --git a/openwisp_network_topology/static/netjsongraph/js/visualize.js b/openwisp_network_topology/static/netjsongraph/js/visualize.js index 31860110..981554f4 100644 --- a/openwisp_network_topology/static/netjsongraph/js/visualize.js +++ b/openwisp_network_topology/static/netjsongraph/js/visualize.js @@ -20,10 +20,14 @@ django.jQuery(function ($) { body.css('overflow', 'hidden'); inner.css('overflow', 'hidden'); - const closeBtn = document.createElement('button'); - closeBtn.setAttribute('class', 'closeBtn'); - closeBtn.innerHTML = '×'; - overlay.get(0).appendChild(closeBtn); + // Check if close button already exists + const closeBtn = document.querySelector('.closeBtn'); + if (!closeBtn) { + const newcloseBtn = document.createElement('button'); + newcloseBtn.setAttribute('class', 'closeBtn'); + newcloseBtn.innerHTML = '×'; + overlay.get(0).appendChild(newcloseBtn); + } window.graph = window.loadNetJsonGraph('.djnjg-overlay .inner'); diff --git a/openwisp_network_topology/tests/test_selenium.py b/openwisp_network_topology/tests/test_selenium.py index 1fab8de4..5838627e 100644 --- a/openwisp_network_topology/tests/test_selenium.py +++ b/openwisp_network_topology/tests/test_selenium.py @@ -2,6 +2,7 @@ from django.contrib.staticfiles.testing import StaticLiveServerTestCase from django.urls import reverse from selenium import webdriver +from selenium.common.exceptions import ElementClickInterceptedException from selenium.webdriver.common.by import By from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.support import expected_conditions as EC @@ -151,3 +152,20 @@ def test_topology_non_admin_view_graph_visualizer(self): ) topology_graph_element.click() self._assert_topology_graph() + + def test_topology_admin_visualizer_multiple_close_btn_append(self): + path = reverse(f'{self.prefix}_topology_change', args=[self.topology.pk]) + self.login(username=self.admin_username, password=self.admin_password) + self.open(path) + self.web_driver.find_element(By.CSS_SELECTOR, 'input.visualizelink').click() + self._assert_topology_graph() + self.web_driver.find_element(By.CLASS_NAME, 'closeBtn').click() + # Now try to open visualizer + # again and make sure only single + # 'closeBtn' element is present in the DOM + self.web_driver.find_element(By.CSS_SELECTOR, 'input.visualizelink').click() + self._assert_topology_graph() + try: + self.web_driver.find_element(By.CLASS_NAME, 'closeBtn').click() + except ElementClickInterceptedException: + self.fail('Multiple "closeBtn" are present in the visualizer DOM')