1
+ from time import sleep
1
2
from unittest .mock import patch
2
3
3
4
from django .contrib .staticfiles .testing import StaticLiveServerTestCase
5
+ from django .test import tag
4
6
from django .urls .base import reverse
5
7
from reversion .models import Version
6
- from selenium .common .exceptions import TimeoutException , UnexpectedAlertPresentException
8
+ from selenium .common .exceptions import TimeoutException
7
9
from selenium .webdriver .common .by import By
8
10
from selenium .webdriver .support import expected_conditions as EC
9
11
from selenium .webdriver .support .ui import WebDriverWait
17
19
from openwisp_monitoring .monitoring .configuration import DEFAULT_DASHBOARD_TRAFFIC_CHART
18
20
from openwisp_monitoring .monitoring .migrations import create_general_metrics
19
21
from 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
23
23
24
24
Device = load_model ('config' , 'Device' )
25
25
DeviceConnection = load_model ('connection' , 'DeviceConnection' )
@@ -68,13 +68,16 @@ def tearDownClass(cls):
68
68
DASHBOARD_TEMPLATES [0 ][1 ] = cls ._dashboard_map_context
69
69
DASHBOARD_TEMPLATES [55 ][1 ] = cls ._dashboard_timeseries_context
70
70
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 )
76
78
77
79
80
+ @tag ('selenium_tests' )
78
81
class TestDeviceConnectionInlineAdmin (
79
82
SeleniumTestMixin ,
80
83
TestDeviceMonitoringMixin ,
@@ -83,25 +86,6 @@ class TestDeviceConnectionInlineAdmin(
83
86
):
84
87
config_app_label = 'config'
85
88
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
-
105
89
def test_restoring_deleted_device (self ):
106
90
org = self ._get_org ()
107
91
self ._create_credentials (auto_add = True , organization = org )
@@ -128,24 +112,26 @@ def test_restoring_deleted_device(self):
128
112
self .open (
129
113
reverse (f'admin:{ self .config_app_label } _device_change' , args = [device .id ])
130
114
)
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]' ,
133
120
).click ()
134
121
try :
135
122
WebDriverWait (self .web_driver , 5 ).until (
136
123
EC .url_to_be (f'{ self .live_server_url } /admin/config/device/' )
137
124
)
138
125
except TimeoutException :
139
126
self .fail ('Failed saving device' )
140
-
141
127
# Delete the device
142
128
device .deactivate ()
143
129
device .config .set_status_deactivated ()
144
130
self .open (
145
131
reverse (f'admin:{ self .config_app_label } _device_delete' , args = [device .id ])
146
132
)
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
149
135
).click ()
150
136
self .assertEqual (Device .objects .count (), 0 )
151
137
self .assertEqual (DeviceConnection .objects .count (), 0 )
@@ -160,7 +146,7 @@ def test_restoring_deleted_device(self):
160
146
f'admin:{ self .config_app_label } _device_recover' , args = [version_obj .id ]
161
147
)
162
148
)
163
- self .web_driver . find_element (
149
+ self .find_element (
164
150
By .XPATH , '//*[@id="device_form"]/div/div[1]/input[1]'
165
151
).click ()
166
152
try :
@@ -181,6 +167,7 @@ def test_restoring_deleted_device(self):
181
167
self .assertEqual (Chart .objects .filter (id__in = device_chart_ids ).count (), 3 )
182
168
183
169
170
+ @tag ('selenium_tests' )
184
171
class TestDashboardCharts (
185
172
SeleniumTestMixin , TestDeviceMonitoringMixin , StaticLiveServerTestCase
186
173
):
@@ -195,73 +182,43 @@ def setUp(self):
195
182
@patch .dict (DEFAULT_DASHBOARD_TRAFFIC_CHART , {'__all__' : ['wlan0' , 'wlan1' ]})
196
183
def test_dashboard_timeseries_charts (self ):
197
184
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
+ )
228
196
self .create_test_data ()
229
197
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 )
245
201
self .assertIn (
246
202
'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
+ ),
250
206
)
251
207
self .assertIn (
252
208
'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
+ ),
256
212
)
257
213
self .assertIn (
258
214
'Open WiFi session list' ,
259
- self .web_driver . find_element (
215
+ self .find_element (
260
216
By .CSS_SELECTOR , '#chart-0-quick-link-container'
261
217
).get_attribute ('innerHTML' ),
262
218
)
263
219
264
220
221
+ @tag ('selenium_tests' )
265
222
class TestWifiSessionInlineAdmin (
266
223
SeleniumTestMixin ,
267
224
TestWifiClientSessionMixin ,
@@ -275,12 +232,9 @@ def test_device_wifi_session_inline_change(self):
275
232
self .login ()
276
233
path = f'admin:{ self .config_app_label } _device_change'
277
234
self .open (reverse (path , args = [device .pk ]))
235
+ self .hide_loading_overlay ()
278
236
# 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' )
284
238
# We are still on the device change page,
285
239
# and now we will create new wifi sessions
286
240
ws1 = self ._create_wifi_session (device = device )
@@ -289,15 +243,15 @@ def test_device_wifi_session_inline_change(self):
289
243
device = device , wifi_client = wc2 , ssid = 'Test Wifi Session'
290
244
)
291
245
# Now press the 'Save' button on the device change page
292
- self .web_driver . find_element (
246
+ self .find_element (
293
247
By .XPATH , '//*[@id="device_form"]/div/div[1]/input[3]'
294
248
).click ()
295
249
# Make sure the wifi session tab now
296
250
# 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 ()
301
255
wifi_session_inline_form_error = (
302
256
'ManagementForm data is missing '
303
257
'or has been tampered with. Missing fields: '
@@ -307,26 +261,26 @@ def test_device_wifi_session_inline_change(self):
307
261
# were encountered after saving
308
262
self .assertNotIn (
309
263
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
+ ),
313
267
)
314
268
# Make sure all wifi sessions are present
315
269
self .assertIn (
316
270
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
+ ),
320
274
)
321
275
self .assertIn (
322
276
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
+ ),
326
280
)
327
281
self .assertIn (
328
282
'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
+ ),
332
286
)
0 commit comments