Skip to content

Commit 0fa8b29

Browse files
committed
[tests] Add tests
1 parent b5cd494 commit 0fa8b29

File tree

4 files changed

+121311
-41
lines changed

4 files changed

+121311
-41
lines changed

openwisp_monitoring/device/static/monitoring/js/device-map.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,8 +543,29 @@
543543
},
544544
// Added to open popup for a specific location Id in selenium tests
545545
openPopup: function (locationId) {
546-
const nodeData = map?.data?.nodes?.find((n) => n.id === locationId);
547-
loadPopUpContent(nodeData, map);
546+
const index = map?.data?.nodes?.findIndex((n) => n.id === locationId);
547+
const nodeData = map?.data?.nodes?.[index];
548+
if (index === -1 || !nodeData) {
549+
console.error(`Node with ID "${locationId}" not found.`);
550+
return;
551+
}
552+
const option = map.echarts.getOption();
553+
const series = option.series.find(
554+
(s) => s.type === "scatter" || "effectScatter",
555+
);
556+
const seriesIndex = option.series.indexOf(series);
557+
558+
const params = {
559+
componentType: "series",
560+
componentSubType: series.type,
561+
seriesIndex: seriesIndex,
562+
dataIndex: index,
563+
data: {
564+
...series.data[index],
565+
node: nodeData,
566+
},
567+
};
568+
map.echarts.trigger("click", params);
548569
},
549570
});
550571
map.render();

openwisp_monitoring/device/static/monitoring/js/floorplan.js

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,16 @@
2020
const params = new URLSearchParams(fragment);
2121
return params.get("id") !== "dashboard-geo-map";
2222
});
23-
if (indoorMapFragment) {
24-
const params = new URLSearchParams(indoorMapFragment);
25-
const id = params.get("id");
26-
const [locationId, floor] = id.split(":");
23+
24+
const params = new URLSearchParams(indoorMapFragment);
25+
const fragmentId = params.get("id");
26+
const [fragmentLocationId, fragmentFloor] = fragmentId?.split(":") || [];
27+
if (fragmentLocationId && fragmentFloor != null) {
2728
const floorplanUrl = window._owGeoMapConfig.indoorCoordinatesUrl.replace(
2829
"000",
29-
locationId,
30+
fragmentLocationId,
3031
);
31-
openFloorPlan(`${floorplanUrl}`, locationId, floor);
32+
openFloorPlan(`${floorplanUrl}`, fragmentLocationId, fragmentFloor);
3233
}
3334

3435
async function openFloorPlan(url, locId = null, floor = currentFloor) {
@@ -361,8 +362,8 @@
361362
// So we convert py to positive and then project the point to get the corresponding topLeft
362363
// Then unproject the point to get the corresponding latlng on the map
363364
const mapOptions = this.echarts.getOption();
364-
// series[0]: nodes config, series[1]: links config and both are always present
365-
mapOptions.series[0].data.forEach((data, index) => {
365+
const series = mapOptions.series.find((s) => s.type === "scatter");
366+
series.data.forEach((data, index) => {
366367
const node = data.node;
367368
const px = Number(node.coordinates.lng);
368369
const py = -Number(node.coordinates.lat);
@@ -414,11 +415,29 @@
414415
indoorMap.setUtils({
415416
// Added to open popup for a specific location Id in selenium tests
416417
openPopup: function (deviceId) {
417-
const mapOptions = indoorMap.echarts.getOption();
418-
const data = mapOptions.series[0].data.find(
419-
(data) => data.node.device_id === deviceId,
418+
const index = indoorMap?.data?.nodes?.findIndex(
419+
(n) => n.device_id === deviceId,
420420
);
421-
loadPopUpContent(data?.node, indoorMap);
421+
const nodeData = indoorMap?.data?.nodes?.[index];
422+
if (index === -1 || !nodeData) {
423+
console.error(`Node with ID "${deviceId}" not found.`);
424+
return;
425+
}
426+
const option = indoorMap.echarts.getOption();
427+
const series = option.series.find((s) => s.type === "scatter");
428+
const seriesIndex = option.series.indexOf(series);
429+
430+
const params = {
431+
componentType: "series",
432+
componentSubType: series.type,
433+
seriesIndex: seriesIndex,
434+
dataIndex: index,
435+
data: {
436+
...series.data[index],
437+
node: nodeData,
438+
},
439+
};
440+
indoorMap.echarts.trigger("click", params);
422441
},
423442
});
424443
indoorMap.render();

openwisp_monitoring/device/static/monitoring/js/lib/netjsongraph.min.js

Lines changed: 121151 additions & 27 deletions
Large diffs are not rendered by default.

openwisp_monitoring/tests/test_selenium.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from time import sleep
22
from unittest.mock import patch
3+
from urllib.parse import quote_plus
34

45
from django.contrib.auth.models import Permission
56
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
@@ -457,6 +458,50 @@ def test_infinite_scroll_on_popup(self):
457458
table_entries = self.find_elements(By.CSS_SELECTOR, ".map-detail tbody tr")
458459
self.assertEqual(len(table_entries), 20)
459460

461+
def test_url_fragment_actions_on_geo_map(self):
462+
device_location = self._create_object_location()
463+
device = device_location.device
464+
location = device_location.location
465+
self.login()
466+
mapId = "dashboard-geo-map"
467+
468+
with self.subTest("Test setting url fragments on click event of node"):
469+
self.open_popup("_owGeoMap", location.id)
470+
current_hash = self.web_driver.execute_script(
471+
"return window.location.hash;"
472+
)
473+
expected_hash = f"id={mapId}&nodeId={location.id}"
474+
self.assertIn(expected_hash, current_hash)
475+
476+
with self.subTest("Test applying url fragment state on map"):
477+
current_url = self.web_driver.current_url
478+
self.web_driver.switch_to.new_window("tab")
479+
tabs = self.web_driver.window_handles
480+
self.web_driver.switch_to.window(tabs[1])
481+
self.web_driver.get(current_url)
482+
sleep(0.5)
483+
popup = self.find_element(By.CSS_SELECTOR, ".map-detail")
484+
device_link = self.find_element(
485+
By.XPATH, f".//td[@class='col-name']/a[text()='{device.name}']"
486+
)
487+
self.assertTrue(popup.is_displayed())
488+
self.assertTrue(device_link.is_displayed())
489+
self.web_driver.close()
490+
self.web_driver.switch_to.window(tabs[0])
491+
492+
with self.subTest("Test with incorrect node Id"):
493+
incorrect_url = (
494+
f"{self.live_server_url}/admin/#id={mapId}&nodeId=incorrectId"
495+
)
496+
self.web_driver.switch_to.new_window("tab")
497+
tabs = self.web_driver.window_handles
498+
self.web_driver.switch_to.window(tabs[1])
499+
self.web_driver.get(incorrect_url)
500+
sleep(0.5)
501+
self.wait_for_invisibility(By.CSS_SELECTOR, ".map-detail")
502+
self.web_driver.close()
503+
self.web_driver.switch_to.window(tabs[0])
504+
460505
def test_floorplan_overlay(self):
461506
org = self._get_org()
462507
location = self._create_location(type="indoor", organization=org)
@@ -612,6 +657,67 @@ def test_switching_floorplan_in_fullscreen_mode(self):
612657
)
613658
self.assertIsNotNone(canvases)
614659

660+
def test_url_fragment_actions_on_indoor_map(self):
661+
org = self._get_org()
662+
device = self._create_device(organization=org)
663+
location = self._create_location(type="indoor", organization=org)
664+
floorplan = self._create_floorplan(floor=1, location=location)
665+
device_location = self._create_object_location(
666+
content_object=device,
667+
location=location,
668+
floorplan=floorplan,
669+
organization=org,
670+
)
671+
self.login()
672+
self.open_popup("_owGeoMap", location.id)
673+
self.wait_for(
674+
"element_to_be_clickable",
675+
By.CSS_SELECTOR,
676+
".map-detail .floorplan-btn",
677+
timeout=5,
678+
).click()
679+
sleep(0.5)
680+
mapId = "dashboard-geo-map"
681+
indoorMapId = f"{location.id}:{floorplan.floor}"
682+
683+
with self.subTest("Test setting url fragments on click event of node"):
684+
self.open_popup("_owIndoorMap", device.id)
685+
# import ipdb; ipdb.set_trace()
686+
current_hash = self.web_driver.execute_script(
687+
"return window.location.hash;"
688+
)
689+
expected_hash = (
690+
f"#id={mapId}&nodeId={location.id};"
691+
f"id={quote_plus(indoorMapId)}&nodeId={device_location.id}"
692+
)
693+
self.assertIn(expected_hash, current_hash)
694+
695+
with self.subTest("Test applying url fragment state on indoor map"):
696+
current_url = self.web_driver.current_url
697+
self.web_driver.switch_to.new_window("tab")
698+
tabs = self.web_driver.window_handles
699+
self.web_driver.switch_to.window(tabs[1])
700+
self.web_driver.get(current_url)
701+
sleep(0.5)
702+
popup = self.find_element(By.CSS_SELECTOR, ".njg-tooltip-inner")
703+
self.assertTrue(popup.is_displayed())
704+
self.assertIn(device.name, popup.get_attribute("innerHTML"))
705+
self.web_driver.close()
706+
self.web_driver.switch_to.window(tabs[0])
707+
708+
with self.subTest("Test with incorrect node Id"):
709+
incorrect_url = (
710+
f"{self.live_server_url}/admin/#id={indoorMapId}&nodeId=incorrectId"
711+
)
712+
self.web_driver.switch_to.new_window("tab")
713+
tabs = self.web_driver.window_handles
714+
self.web_driver.switch_to.window(tabs[1])
715+
self.web_driver.get(incorrect_url)
716+
sleep(0.5)
717+
self.wait_for_invisibility(By.CSS_SELECTOR, ".njg-tooltip-inner")
718+
self.web_driver.close()
719+
self.web_driver.switch_to.window(tabs[0])
720+
615721
def test_dashboard_map_without_permissions(self):
616722
user = self._create_user(
617723
username="testuser", password="password", is_staff=True, is_superuser=True

0 commit comments

Comments
 (0)