1+ import ipdb
12from django .contrib .staticfiles .testing import StaticLiveServerTestCase
23from django .test import tag
34from django .urls .base import reverse
4- from selenium .common .exceptions import (
5- StaleElementReferenceException ,
6- TimeoutException ,
7- UnexpectedAlertPresentException ,
8- )
5+ from selenium .common .exceptions import TimeoutException
96from selenium .webdriver .common .action_chains import ActionChains
107from selenium .webdriver .common .alert import Alert
118from selenium .webdriver .common .by import By
@@ -117,9 +114,10 @@ def test_device_preview_keyboard_shortcuts(self):
117114 def test_unsaved_changes (self ):
118115 self .login ()
119116 device = self ._create_config (organization = self ._get_org ()).device
120- self .open (reverse ('admin:config_device_change' , args = [device .id ]))
117+ path = reverse ('admin:config_device_change' , args = [device .id ])
118+ self .open (path )
121119 with self .subTest ('Alert should not be displayed without any change' ):
122- self .web_driver . refresh ( )
120+ self .open ( path )
123121 try :
124122 WebDriverWait (self .web_driver , 1 ).until (EC .alert_is_present ())
125123 except TimeoutException :
@@ -143,8 +141,7 @@ def test_unsaved_changes(self):
143141 print (entry )
144142 self .fail ('Timed out wating for unsaved changes alert' )
145143 else :
146- alert = Alert (self .web_driver )
147- alert .accept ()
144+ self .web_driver .switch_to .alert .accept ()
148145
149146 def test_multiple_organization_templates (self ):
150147 shared_required_template = self ._create_template (
@@ -176,7 +173,6 @@ def test_multiple_organization_templates(self):
176173 reverse ('admin:config_device_change' , args = [org1_device .id ])
177174 + '#config-group'
178175 )
179- wait = WebDriverWait (self .web_driver , 2 )
180176 # org2 templates should not be visible
181177 self .wait_for_invisibility (
182178 By .XPATH , f'//*[@value="{ org2_required_template .id } "]'
@@ -253,16 +249,27 @@ def test_force_delete_device_with_deactivating_config(self):
253249
254250 self .login ()
255251 self .open (reverse ('admin:config_device_change' , args = [device .id ]))
256- self .find_elements (by = By .CSS_SELECTOR , value = 'input.deletelink[type="submit"]' )[
257- - 1
258- ].click ()
252+ # The webpage has two "submit-row" sections, each containing a "Deactivate"
253+ # button. The first (top) "Deactivate" button is hidden, causing
254+ # `wait_for_visibility` to fail. To avoid this issue, we use
255+ # `wait_for='presence'` instead, ensuring we locat the elements regardless
256+ # of visibility. We then select the last (visible) button and click it.
257+ self .find_elements (
258+ by = By .CSS_SELECTOR ,
259+ value = 'input.deletelink[type="submit"]' ,
260+ wait_for = 'presence' ,
261+ )[- 1 ].click ()
259262 device .refresh_from_db ()
260263 config .refresh_from_db ()
261264 self .assertEqual (device .is_deactivated (), True )
262265 self .assertEqual (config .is_deactivating (), True )
263266
264267 self .open (reverse ('admin:config_device_change' , args = [device .id ]))
265- self .find_elements (by = By .CSS_SELECTOR , value = 'a.deletelink' )[- 1 ].click ()
268+ # Use `presence` instead of `visibility` for `wait_for`,
269+ # as the same issue described above applies here.
270+ self .find_elements (
271+ by = By .CSS_SELECTOR , value = 'a.deletelink' , wait_for = 'presence'
272+ )[- 1 ].click ()
266273 self .wait_for_visibility (
267274 By .CSS_SELECTOR , '#deactivating-warning .messagelist .warning p'
268275 )
@@ -306,6 +313,7 @@ def test_force_delete_multiple_devices_with_deactivating_config(self):
306313 self .assertEqual (Device .objects .count (), 0 )
307314
308315
316+ @tag ('selenium_tests' )
309317class TestVpnAdmin (
310318 SeleniumTestMixin ,
311319 CreateConfigTemplateMixin ,
@@ -317,10 +325,8 @@ def test_vpn_edit(self):
317325 device , vpn , template = self ._create_wireguard_vpn_template ()
318326 self .open (reverse ('admin:config_vpn_change' , args = [vpn .id ]))
319327 with self .subTest ('Ca and Cert should not be visible' ):
320- el = self .find_element (by = By .CLASS_NAME , value = 'field-ca' )
321- self .assertFalse (el .is_displayed ())
322- el = self .find_element (by = By .CLASS_NAME , value = 'field-cert' )
323- self .assertFalse (el .is_displayed ())
328+ self .wait_for_invisibility (by = By .CLASS_NAME , value = 'field-ca' )
329+ self .wait_for_invisibility (by = By .CLASS_NAME , value = 'field-cert' )
324330
325331 with self .subTest ('PrivateKey is shown in configuration preview' ):
326332 self .find_element (by = By .CSS_SELECTOR , value = '.previewlink' ).click ()
@@ -335,7 +341,5 @@ def test_vpn_edit(self):
335341 with self .subTest ('Changing VPN backend should hide webhook and authtoken' ):
336342 backend = Select (self .find_element (by = By .ID , value = 'id_backend' ))
337343 backend .select_by_visible_text ('OpenVPN' )
338- el = self .find_element (by = By .CLASS_NAME , value = 'field-webhook_endpoint' )
339- self .assertFalse (el .is_displayed ())
340- el = self .find_element (by = By .CLASS_NAME , value = 'field-auth_token' )
341- self .assertFalse (el .is_displayed ())
344+ self .wait_for_invisibility (by = By .CLASS_NAME , value = 'field-webhook_endpoint' )
345+ self .wait_for_invisibility (by = By .CLASS_NAME , value = 'field-auth_token' )
0 commit comments