@@ -43,6 +43,7 @@ def test_anything(self):
43
43
ElementClickInterceptedException as ECI_Exception ,
44
44
ElementNotInteractableException as ENI_Exception ,
45
45
MoveTargetOutOfBoundsException ,
46
+ NoSuchWindowException ,
46
47
StaleElementReferenceException ,
47
48
WebDriverException ,
48
49
)
@@ -132,6 +133,7 @@ def __init__(self, *args, **kwargs):
132
133
def open (self , url ):
133
134
""" Navigates the current browser window to the specified page. """
134
135
self .__check_scope ()
136
+ self .__check_browser ()
135
137
if type (url ) is str :
136
138
url = url .strip () # Remove leading and trailing whitespace
137
139
if (type (url ) is not str ) or not self .__looks_like_a_page_url (url ):
@@ -737,11 +739,13 @@ def get_title(self):
737
739
738
740
def get_user_agent (self ):
739
741
self .__check_scope ()
742
+ self .__check_browser ()
740
743
user_agent = self .driver .execute_script ("return navigator.userAgent;" )
741
744
return user_agent
742
745
743
746
def get_locale_code (self ):
744
747
self .__check_scope ()
748
+ self .__check_browser ()
745
749
locale_code = self .driver .execute_script (
746
750
"return navigator.language || navigator.languages[0];"
747
751
)
@@ -2341,10 +2345,12 @@ def open_html_file(self, html_file):
2341
2345
2342
2346
def execute_script (self , script , * args , ** kwargs ):
2343
2347
self .__check_scope ()
2348
+ self .__check_browser ()
2344
2349
return self .driver .execute_script (script , * args , ** kwargs )
2345
2350
2346
2351
def execute_async_script (self , script , timeout = None ):
2347
2352
self .__check_scope ()
2353
+ self .__check_browser ()
2348
2354
if not timeout :
2349
2355
timeout = settings .EXTREME_TIMEOUT
2350
2356
return js_utils .execute_async_script (self .driver , script , timeout )
@@ -2354,6 +2360,7 @@ def safe_execute_script(self, script, *args, **kwargs):
2354
2360
it's important that the jQuery library has been loaded first.
2355
2361
This method will load jQuery if it wasn't already loaded."""
2356
2362
self .__check_scope ()
2363
+ self .__check_browser ()
2357
2364
if not js_utils .is_jquery_activated (self .driver ):
2358
2365
self .activate_jquery ()
2359
2366
return self .driver .execute_script (script , * args , ** kwargs )
@@ -2583,6 +2590,7 @@ def set_content_to_default(self, nested=True):
2583
2590
def open_new_window (self , switch_to = True ):
2584
2591
""" Opens a new browser tab/window and switches to it by default. """
2585
2592
self .__check_scope ()
2593
+ self .__check_browser () # Current window must exist to open a new one
2586
2594
self .driver .execute_script ("window.open('');" )
2587
2595
time .sleep (0.01 )
2588
2596
if switch_to :
@@ -3085,6 +3093,7 @@ def delete_saved_cookies(self, name="cookies.txt"):
3085
3093
3086
3094
def wait_for_ready_state_complete (self , timeout = None ):
3087
3095
self .__check_scope ()
3096
+ self .__check_browser ()
3088
3097
if not timeout :
3089
3098
timeout = settings .EXTREME_TIMEOUT
3090
3099
if self .timeout_multiplier and timeout == settings .EXTREME_TIMEOUT :
@@ -6330,26 +6339,32 @@ def start_tour(self, name=None, interval=0):
6330
6339
6331
6340
def add_css_link (self , css_link ):
6332
6341
self .__check_scope ()
6342
+ self .__check_browser ()
6333
6343
js_utils .add_css_link (self .driver , css_link )
6334
6344
6335
6345
def add_js_link (self , js_link ):
6336
6346
self .__check_scope ()
6347
+ self .__check_browser ()
6337
6348
js_utils .add_js_link (self .driver , js_link )
6338
6349
6339
6350
def add_css_style (self , css_style ):
6340
6351
self .__check_scope ()
6352
+ self .__check_browser ()
6341
6353
js_utils .add_css_style (self .driver , css_style )
6342
6354
6343
6355
def add_js_code_from_link (self , js_link ):
6344
6356
self .__check_scope ()
6357
+ self .__check_browser ()
6345
6358
js_utils .add_js_code_from_link (self .driver , js_link )
6346
6359
6347
6360
def add_js_code (self , js_code ):
6348
6361
self .__check_scope ()
6362
+ self .__check_browser ()
6349
6363
js_utils .add_js_code (self .driver , js_code )
6350
6364
6351
6365
def add_meta_tag (self , http_equiv = None , content = None ):
6352
6366
self .__check_scope ()
6367
+ self .__check_browser ()
6353
6368
js_utils .add_meta_tag (
6354
6369
self .driver , http_equiv = http_equiv , content = content
6355
6370
)
@@ -8121,6 +8136,7 @@ def export_tour(self, name=None, filename="my_tour.js", url=None):
8121
8136
def activate_jquery_confirm (self ):
8122
8137
""" See https://craftpip.github.io/jquery-confirm/ for usage. """
8123
8138
self .__check_scope ()
8139
+ self .__check_browser ()
8124
8140
js_utils .activate_jquery_confirm (self .driver )
8125
8141
self .wait_for_ready_state_complete ()
8126
8142
@@ -8449,6 +8465,7 @@ def get_jqc_form_inputs(self, message, buttons, options=None):
8449
8465
8450
8466
def activate_messenger (self ):
8451
8467
self .__check_scope ()
8468
+ self .__check_browser ()
8452
8469
js_utils .activate_messenger (self .driver )
8453
8470
self .wait_for_ready_state_complete ()
8454
8471
@@ -8462,6 +8479,7 @@ def set_messenger_theme(
8462
8479
max_messages is the limit of concurrent messages to display.
8463
8480
"""
8464
8481
self .__check_scope ()
8482
+ self .__check_browser ()
8465
8483
if not theme :
8466
8484
theme = "default" # "flat"
8467
8485
if not location :
@@ -8489,6 +8507,7 @@ def post_message(self, message, duration=None, pause=True, style="info"):
8489
8507
self.execute_script('Messenger().post("My Message")')
8490
8508
"""
8491
8509
self .__check_scope ()
8510
+ self .__check_browser ()
8492
8511
if style not in ["info" , "success" , "error" ]:
8493
8512
style = "info"
8494
8513
if not duration :
@@ -8524,6 +8543,7 @@ def post_success_message(self, message, duration=None, pause=True):
8524
8543
pause: If True, the program waits until the message completes.
8525
8544
"""
8526
8545
self .__check_scope ()
8546
+ self .__check_browser ()
8527
8547
if not duration :
8528
8548
if not self .message_duration :
8529
8549
duration = settings .DEFAULT_MESSAGE_DURATION
@@ -8547,6 +8567,7 @@ def post_error_message(self, message, duration=None, pause=True):
8547
8567
pause: If True, the program waits until the message completes.
8548
8568
"""
8549
8569
self .__check_scope ()
8570
+ self .__check_browser ()
8550
8571
if not duration :
8551
8572
if not self .message_duration :
8552
8573
duration = settings .DEFAULT_MESSAGE_DURATION
@@ -9753,6 +9774,18 @@ def __check_scope(self):
9753
9774
9754
9775
############
9755
9776
9777
+ def __check_browser (self ):
9778
+ """This method raises an exception if the window was already closed."""
9779
+ active_window = None
9780
+ try :
9781
+ active_window = self .driver .current_window_handle # Fails if None
9782
+ except Exception :
9783
+ pass
9784
+ if not active_window :
9785
+ raise NoSuchWindowException ("Active window was already closed!" )
9786
+
9787
+ ############
9788
+
9756
9789
def __get_exception_message (self ):
9757
9790
"""This method extracts the message from an exception if there
9758
9791
was an exception that occurred during the test, assuming
0 commit comments