1+ from time import sleep
12from unittest .mock import patch
23
34from django .contrib .staticfiles .testing import StaticLiveServerTestCase
5+ from django .test import tag
46from django .urls .base import reverse
57from reversion .models import Version
6- from selenium .common .exceptions import TimeoutException , UnexpectedAlertPresentException
8+ from selenium .common .exceptions import TimeoutException
79from selenium .webdriver .common .by import By
810from selenium .webdriver .support import expected_conditions as EC
911from selenium .webdriver .support .ui import WebDriverWait
1719from openwisp_monitoring .monitoring .configuration import DEFAULT_DASHBOARD_TRAFFIC_CHART
1820from openwisp_monitoring .monitoring .migrations import create_general_metrics
1921from openwisp_utils .admin_theme .dashboard import DASHBOARD_TEMPLATES
20- from openwisp_utils .test_selenium_mixins import (
21- SeleniumTestMixin as BaseSeleniumTestMixin ,
22- )
22+ from openwisp_utils .tests import SeleniumTestMixin as BaseSeleniumTestMixin
2323
2424Device = load_model ('config' , 'Device' )
2525DeviceConnection = load_model ('connection' , 'DeviceConnection' )
@@ -68,13 +68,16 @@ def tearDownClass(cls):
6868 DASHBOARD_TEMPLATES [0 ][1 ] = cls ._dashboard_map_context
6969 DASHBOARD_TEMPLATES [55 ][1 ] = cls ._dashboard_timeseries_context
7070
71- def setUp (self ):
72- self .admin = self ._create_admin (
73- username = self .admin_username , password = self .admin_password
74- )
75- super ().setUp ()
71+ def login (self , username = None , password = None , driver = None ):
72+ super ().login (username , password , driver )
73+ # Workaround for JS logic in chart-utils.js
74+ # which fails to perform a XHR request
75+ # during automated tests, it seems that the
76+ # lack of pause causes the request to fail randomly
77+ sleep (0.5 )
7678
7779
80+ @tag ('selenium_tests' )
7881class TestDeviceConnectionInlineAdmin (
7982 SeleniumTestMixin ,
8083 TestDeviceMonitoringMixin ,
@@ -83,25 +86,6 @@ class TestDeviceConnectionInlineAdmin(
8386):
8487 config_app_label = 'config'
8588
86- def tearDown (self ):
87- # Accept unsaved changes alert to allow other tests to run
88- try :
89- self .web_driver .refresh ()
90- except UnexpectedAlertPresentException :
91- self .web_driver .switch_to_alert ().accept ()
92- else :
93- try :
94- WebDriverWait (self .web_driver , 1 ).until (EC .alert_is_present ())
95- except TimeoutException :
96- pass
97- else :
98- self .web_driver .switch_to_alert ().accept ()
99- self .web_driver .refresh ()
100- WebDriverWait (self .web_driver , 2 ).until (
101- EC .visibility_of_element_located ((By .XPATH , '//*[@id="site-name"]' ))
102- )
103- super ().tearDown ()
104-
10589 def test_restoring_deleted_device (self ):
10690 org = self ._get_org ()
10791 self ._create_credentials (auto_add = True , organization = org )
@@ -128,24 +112,26 @@ def test_restoring_deleted_device(self):
128112 self .open (
129113 reverse (f'admin:{ self .config_app_label } _device_change' , args = [device .id ])
130114 )
131- self .web_driver .find_element (
132- By .XPATH , '//*[@id="device_form"]/div/div[1]/input[1]'
115+ self .hide_loading_overlay ()
116+ self .wait_for (
117+ 'element_to_be_clickable' ,
118+ By .XPATH ,
119+ '//*[@id="device_form"]/div/div[1]/input[1]' ,
133120 ).click ()
134121 try :
135122 WebDriverWait (self .web_driver , 5 ).until (
136123 EC .url_to_be (f'{ self .live_server_url } /admin/config/device/' )
137124 )
138125 except TimeoutException :
139126 self .fail ('Failed saving device' )
140-
141127 # Delete the device
142128 device .deactivate ()
143129 device .config .set_status_deactivated ()
144130 self .open (
145131 reverse (f'admin:{ self .config_app_label } _device_delete' , args = [device .id ])
146132 )
147- self .web_driver . find_element (
148- by = By .CSS_SELECTOR , value = '#content form input[type="submit"]'
133+ self .find_element (
134+ By .CSS_SELECTOR , '#content form input[type="submit"]' , timeout = 5
149135 ).click ()
150136 self .assertEqual (Device .objects .count (), 0 )
151137 self .assertEqual (DeviceConnection .objects .count (), 0 )
@@ -160,7 +146,7 @@ def test_restoring_deleted_device(self):
160146 f'admin:{ self .config_app_label } _device_recover' , args = [version_obj .id ]
161147 )
162148 )
163- self .web_driver . find_element (
149+ self .find_element (
164150 By .XPATH , '//*[@id="device_form"]/div/div[1]/input[1]'
165151 ).click ()
166152 try :
@@ -181,6 +167,7 @@ def test_restoring_deleted_device(self):
181167 self .assertEqual (Chart .objects .filter (id__in = device_chart_ids ).count (), 3 )
182168
183169
170+ @tag ('selenium_tests' )
184171class TestDashboardCharts (
185172 SeleniumTestMixin , TestDeviceMonitoringMixin , StaticLiveServerTestCase
186173):
@@ -195,73 +182,43 @@ def setUp(self):
195182 @patch .dict (DEFAULT_DASHBOARD_TRAFFIC_CHART , {'__all__' : ['wlan0' , 'wlan1' ]})
196183 def test_dashboard_timeseries_charts (self ):
197184 self .login ()
198- try :
199- WebDriverWait (self .web_driver , 5 ).until (
200- EC .visibility_of_element_located (
201- (By .CSS_SELECTOR , '#ow-chart-inner-container' )
202- )
203- )
204- except TimeoutException :
205- self .fail ('Timeseries chart container not found on dashboard' )
206- try :
207- WebDriverWait (self .web_driver , 5 ).until (
208- EC .visibility_of_element_located ((By .CSS_SELECTOR , '#ow-chart-utils' ))
209- )
210- except TimeoutException :
211- self .fail ('Timeseries chart time filter not found on dashboard' )
212-
213- try :
214- WebDriverWait (self .web_driver , 5 ).until (
215- EC .visibility_of_element_located (
216- (By .CSS_SELECTOR , '#ow-chart-fallback' )
217- )
218- )
219- except TimeoutException :
220- self .fail ('Fallback message for charts did not render' )
221- else :
222- self .assertIn (
223- 'Insufficient data for selected time period.' ,
224- self .web_driver .find_element (
225- By .CSS_SELECTOR , '#ow-chart-fallback'
226- ).get_attribute ('innerHTML' ),
227- )
185+ self .wait_for_visibility (
186+ By .CSS_SELECTOR , '#ow-chart-inner-container' , timeout = 5
187+ )
188+ self .wait_for_visibility (By .CSS_SELECTOR , '#ow-chart-utils' , timeout = 5 )
189+ self .wait_for_visibility (By .CSS_SELECTOR , '#ow-chart-fallback' , timeout = 5 )
190+ self .assertIn (
191+ 'Insufficient data for selected time period.' ,
192+ self .find_element (By .CSS_SELECTOR , '#ow-chart-fallback' ).get_attribute (
193+ 'innerHTML'
194+ ),
195+ )
228196 self .create_test_data ()
229197 self .web_driver .refresh ()
230- try :
231- WebDriverWait (self .web_driver , 20 ).until (
232- EC .visibility_of_element_located (
233- (By .CSS_SELECTOR , '#ow-chart-contents' )
234- )
235- )
236- WebDriverWait (self .web_driver , 20 ).until (
237- EC .visibility_of_element_located ((By .CSS_SELECTOR , '#chart-0' ))
238- )
239- WebDriverWait (self .web_driver , 60 ).until (
240- EC .visibility_of_element_located ((By .CSS_SELECTOR , '#chart-1' ))
241- )
242- except TimeoutException :
243- self .fail ('Timeseries charts did not render' )
244-
198+ self .wait_for_visibility (By .CSS_SELECTOR , '#ow-chart-contents' , timeout = 10 )
199+ self .wait_for_visibility (By .CSS_SELECTOR , '#chart-0' , timeout = 10 )
200+ self .wait_for_visibility (By .CSS_SELECTOR , '#chart-1' , timeout = 10 )
245201 self .assertIn (
246202 'General WiFi Clients' ,
247- self .web_driver . find_element (
248- By . CSS_SELECTOR , '#chart-0 > h3 '
249- ). get_attribute ( 'innerHTML' ) ,
203+ self .find_element ( By . CSS_SELECTOR , '#chart-0 > h3' ). get_attribute (
204+ 'innerHTML '
205+ ),
250206 )
251207 self .assertIn (
252208 'General Traffic' ,
253- self .web_driver . find_element (
254- By . CSS_SELECTOR , '#chart-1 > h3 '
255- ). get_attribute ( 'innerHTML' ) ,
209+ self .find_element ( By . CSS_SELECTOR , '#chart-1 > h3' ). get_attribute (
210+ 'innerHTML '
211+ ),
256212 )
257213 self .assertIn (
258214 'Open WiFi session list' ,
259- self .web_driver . find_element (
215+ self .find_element (
260216 By .CSS_SELECTOR , '#chart-0-quick-link-container'
261217 ).get_attribute ('innerHTML' ),
262218 )
263219
264220
221+ @tag ('selenium_tests' )
265222class TestWifiSessionInlineAdmin (
266223 SeleniumTestMixin ,
267224 TestWifiClientSessionMixin ,
@@ -275,12 +232,9 @@ def test_device_wifi_session_inline_change(self):
275232 self .login ()
276233 path = f'admin:{ self .config_app_label } _device_change'
277234 self .open (reverse (path , args = [device .pk ]))
235+ self .hide_loading_overlay ()
278236 # Make sure the wifi session inline doesn't exist
279- WebDriverWait (self .web_driver , 2 ).until (
280- EC .invisibility_of_element_located (
281- (By .CSS_SELECTOR , '#wifisession_set-group' )
282- )
283- )
237+ self .wait_for_invisibility (By .CSS_SELECTOR , '#wifisession_set-group' )
284238 # We are still on the device change page,
285239 # and now we will create new wifi sessions
286240 ws1 = self ._create_wifi_session (device = device )
@@ -289,15 +243,15 @@ def test_device_wifi_session_inline_change(self):
289243 device = device , wifi_client = wc2 , ssid = 'Test Wifi Session'
290244 )
291245 # Now press the 'Save' button on the device change page
292- self .web_driver . find_element (
246+ self .find_element (
293247 By .XPATH , '//*[@id="device_form"]/div/div[1]/input[3]'
294248 ).click ()
295249 # Make sure the wifi session tab now
296250 # exists with the correct wifi sessions
297- wifi_session_inline = self .web_driver . find_element (
298- By . XPATH , '//*[@id="tabs-container"]/ul/li[7]/a'
299- )
300- wifi_session_inline .click ()
251+ self .hide_loading_overlay ()
252+ self . wait_for (
253+ 'element_to_be_clickable' , By . XPATH , '//*[@id="tabs-container"]/ul/li[7]/a'
254+ ) .click ()
301255 wifi_session_inline_form_error = (
302256 'ManagementForm data is missing '
303257 'or has been tampered with. Missing fields: '
@@ -307,26 +261,26 @@ def test_device_wifi_session_inline_change(self):
307261 # were encountered after saving
308262 self .assertNotIn (
309263 wifi_session_inline_form_error ,
310- self .web_driver . find_element (
311- By . CSS_SELECTOR , '#wifisession_set-group '
312- ). get_attribute ( 'innerHTML' ) ,
264+ self .find_element ( By . CSS_SELECTOR , '#wifisession_set-group' ). get_attribute (
265+ 'innerHTML '
266+ ),
313267 )
314268 # Make sure all wifi sessions are present
315269 self .assertIn (
316270 f'{ ws1 .ssid } ' ,
317- self .web_driver . find_element (
318- By . CSS_SELECTOR , '#wifisession_set-group '
319- ). get_attribute ( 'innerHTML' ) ,
271+ self .find_element ( By . CSS_SELECTOR , '#wifisession_set-group' ). get_attribute (
272+ 'innerHTML '
273+ ),
320274 )
321275 self .assertIn (
322276 f'{ ws2 .ssid } ' ,
323- self .web_driver . find_element (
324- By . CSS_SELECTOR , '#wifisession_set-group '
325- ). get_attribute ( 'innerHTML' ) ,
277+ self .find_element ( By . CSS_SELECTOR , '#wifisession_set-group' ). get_attribute (
278+ 'innerHTML '
279+ ),
326280 )
327281 self .assertIn (
328282 'View Full History of WiFi Sessions' ,
329- self .web_driver . find_element (
330- By . CSS_SELECTOR , '#wifisession_set-group '
331- ). get_attribute ( 'innerHTML' ) ,
283+ self .find_element ( By . CSS_SELECTOR , '#wifisession_set-group' ). get_attribute (
284+ 'innerHTML '
285+ ),
332286 )
0 commit comments