@@ -55,6 +55,7 @@ def test_anything(self):
5555from seleniumbase .fixtures import js_utils
5656from seleniumbase .fixtures import page_actions
5757from seleniumbase .fixtures import page_utils
58+ from seleniumbase .fixtures import shared_utils
5859from seleniumbase .fixtures import xpath_to_css
5960logging .getLogger ("requests" ).setLevel (logging .ERROR )
6061logging .getLogger ("urllib3" ).setLevel (logging .ERROR )
@@ -976,14 +977,15 @@ def find_visible_elements(self, selector, by=By.CSS_SELECTOR, limit=0):
976977 def click_visible_elements (self , selector , by = By .CSS_SELECTOR , limit = 0 ):
977978 """ Finds all matching page elements and clicks visible ones in order.
978979 If a click reloads or opens a new page, the clicking will stop.
980+ If no matching elements appear, an Exception will be raised.
981+ If "limit" is set and > 0, will only click that many elements.
982+ Also clicks elements that become visible from previous clicks.
979983 Works best for actions such as clicking all checkboxes on a page.
980- Example: self.click_visible_elements('input[type="checkbox"]')
981- If "limit" is set and > 0, will only click that many elements. """
982- elements = []
983- try :
984- elements = self .find_visible_elements (selector , by = by )
985- except Exception :
986- elements = self .find_elements (selector , by = by )
984+ Example: self.click_visible_elements('input[type="checkbox"]') """
985+ selector , by = self .__recalculate_selector (selector , by )
986+ self .wait_for_element_present (
987+ selector , by = by , timeout = settings .SMALL_TIMEOUT )
988+ elements = self .find_elements (selector , by = by )
987989 click_count = 0
988990 for element in elements :
989991 if limit and limit > 0 and click_count >= limit :
@@ -1661,7 +1663,17 @@ def wait_for_angularjs(self, timeout=None, **kwargs):
16611663 js_utils .wait_for_angularjs (self .driver , timeout , ** kwargs )
16621664
16631665 def sleep (self , seconds ):
1664- time .sleep (seconds )
1666+ if not sb_config .time_limit :
1667+ time .sleep (seconds )
1668+ else :
1669+ start_ms = time .time () * 1000.0
1670+ stop_ms = start_ms + (seconds * 1000.0 )
1671+ for x in range (int (seconds * 5 )):
1672+ shared_utils .check_if_time_limit_exceeded ()
1673+ now_ms = time .time () * 1000.0
1674+ if now_ms >= stop_ms :
1675+ break
1676+ time .sleep (0.2 )
16651677
16661678 def activate_jquery (self ):
16671679 """ If "jQuery is not defined", use this method to activate it for use.
@@ -2455,6 +2467,22 @@ def jquery_update_text(self, selector, new_value, by=By.CSS_SELECTOR,
24552467 element .send_keys ('\n ' )
24562468 self .__demo_mode_pause_if_active ()
24572469
2470+ def set_time_limit (self , time_limit ):
2471+ if time_limit :
2472+ try :
2473+ sb_config .time_limit = float (time_limit )
2474+ except Exception :
2475+ sb_config .time_limit = None
2476+ else :
2477+ sb_config .time_limit = None
2478+ if sb_config .time_limit and sb_config .time_limit > 0 :
2479+ sb_config .time_limit_ms = int (sb_config .time_limit * 1000.0 )
2480+ self .time_limit = sb_config .time_limit
2481+ else :
2482+ self .time_limit = None
2483+ sb_config .time_limit = None
2484+ sb_config .time_limit_ms = None
2485+
24582486 ############
24592487
24602488 def add_css_link (self , css_link ):
@@ -3237,6 +3265,7 @@ def wait_for_link_text_present(self, link_text, timeout=None):
32373265 start_ms = time .time () * 1000.0
32383266 stop_ms = start_ms + (timeout * 1000.0 )
32393267 for x in range (int (timeout * 5 )):
3268+ shared_utils .check_if_time_limit_exceeded ()
32403269 try :
32413270 if not self .is_link_text_present (link_text ):
32423271 raise Exception (
@@ -3257,6 +3286,7 @@ def wait_for_partial_link_text_present(self, link_text, timeout=None):
32573286 start_ms = time .time () * 1000.0
32583287 stop_ms = start_ms + (timeout * 1000.0 )
32593288 for x in range (int (timeout * 5 )):
3289+ shared_utils .check_if_time_limit_exceeded ()
32603290 try :
32613291 if not self .is_partial_link_text_present (link_text ):
32623292 raise Exception (
@@ -4145,6 +4175,7 @@ def setUp(self, masterqa_mode=False):
41454175 self .demo_mode = sb_config .demo_mode
41464176 self .demo_sleep = sb_config .demo_sleep
41474177 self .highlights = sb_config .highlights
4178+ self .time_limit = sb_config .time_limit
41484179 self .environment = sb_config .environment
41494180 self .env = self .environment # Add a shortened version
41504181 self .with_selenium = sb_config .with_selenium # Should be True
@@ -4242,15 +4273,27 @@ def setUp(self, masterqa_mode=False):
42424273 # pyvirtualdisplay might not be necessary anymore because
42434274 # Chrome and Firefox now have built-in headless displays
42444275 pass
4276+ else :
4277+ # (Nosetests / Not Pytest)
4278+ pass # Setup performed in plugins
42454279
42464280 # Verify that SeleniumBase is installed successfully
42474281 if not hasattr (self , "browser" ):
42484282 raise Exception ("""SeleniumBase plugins DID NOT load!\n \n """
42494283 """*** Please REINSTALL SeleniumBase using: >\n """
42504284 """ >>> "pip install -r requirements.txt"\n """
42514285 """ >>> "python setup.py install" """ )
4286+
4287+ # Configure the test time limit (if used)
4288+ self .set_time_limit (self .time_limit )
4289+
4290+ # Set the start time for the test (in ms)
4291+ sb_config .start_time_ms = int (time .time () * 1000.0 )
4292+
4293+ # Parse the settings file
42524294 if self .settings_file :
42534295 settings_parser .set_settings (self .settings_file )
4296+
42544297 # Mobile Emulator device metrics: CSS Width, CSS Height, & Pixel-Ratio
42554298 if self .device_metrics :
42564299 metrics_string = self .device_metrics
0 commit comments