11"""
2- BaseCase gathers SeleniumBase libraries into a single file for easy calling.
2+ The BaseCase class is the main gateway for using The SeleniumBase Framework.
3+ It inherits Python's unittest.TestCase class, and runs with Pytest or Nose.
4+ All tests using BaseCase automatically launch WebDriver browsers for tests.
5+
36Usage:
47
58 from seleniumbase import BaseCase
69 class MyTestClass(BaseCase):
7- test_anything(self):
10+ def test_anything(self):
811 # Write your code here. Example:
912 self.open("https://github.com/")
1013 self.update_text("input.header-search-input", "SeleniumBase\n ")
1114 self.click('a[href="/seleniumbase/SeleniumBase"]')
1215 self.assert_element("div.repository-content")
1316 ....
1417
15- The methods here expand and improve existing WebDriver commands.
16- Improvements include making WebDriver more robust and more reliable .
17- Page elements are given enough time to load before taking action on them.
18+ SeleniumBase methods expand and improve on existing WebDriver commands.
19+ Improvements include making WebDriver more robust, reliable, and flexible .
20+ Page elements are given enough time to load before WebDriver acts on them.
1821Code becomes greatly simplified and easier to maintain.
1922"""
2023
@@ -74,7 +77,8 @@ def __init__(self, *args, **kwargs):
7477 self ._page_check_count = 0
7578 self ._page_check_failures = []
7679 self ._html_report_extra = []
77- self ._extra_drivers = []
80+ self ._default_driver = None
81+ self ._drivers_list = []
7882
7983 def open (self , url ):
8084 self .driver .get (url )
@@ -612,8 +616,8 @@ def find_visible_elements(self, selector, by=By.CSS_SELECTOR):
612616 by = By .LINK_TEXT
613617 return page_actions .find_visible_elements (self .driver , selector , by )
614618
615- def is_element_in_frame (self , selector , by = By .CSS_SELECTOR ):
616- """ Returns True if the selector's element is located in an iFrame .
619+ def is_element_in_an_iframe (self , selector , by = By .CSS_SELECTOR ):
620+ """ Returns True if the selector's element is located in an iframe .
617621 Otherwise returns False. """
618622 selector , by = self ._recalculate_selector (selector , by )
619623 if self .is_element_present (selector , by = by ):
@@ -636,10 +640,11 @@ def is_element_in_frame(self, selector, by=By.CSS_SELECTOR):
636640 self .switch_to_default_content ()
637641 return False
638642
639- def enter_frame_of_element (self , selector , by = By .CSS_SELECTOR ):
640- """ Returns the frame name of the selector's element if in an iFrame.
641- Also enters the iFrame if the element was inside an iFrame.
642- If the element is not in an iFrame, returns None. """
643+ def switch_to_frame_of_element (self , selector , by = By .CSS_SELECTOR ):
644+ """ Set driver control to the iframe of the element (assuming the
645+ element is in a single-nested iframe) and returns the iframe name.
646+ If element is not in an iframe, returns None, and nothing happens.
647+ May not work if multiple iframes are nested within each other. """
643648 selector , by = self ._recalculate_selector (selector , by )
644649 if self .is_element_present (selector , by = by ):
645650 return None
@@ -1420,54 +1425,90 @@ def wait_for_and_switch_to_alert(self, timeout=settings.LARGE_TIMEOUT):
14201425 return page_actions .wait_for_and_switch_to_alert (self .driver , timeout )
14211426
14221427 def switch_to_frame (self , frame , timeout = settings .SMALL_TIMEOUT ):
1428+ """ Sets driver control to the specified browser frame. """
14231429 if self .timeout_multiplier and timeout == settings .SMALL_TIMEOUT :
14241430 timeout = self ._get_new_timeout (timeout )
14251431 page_actions .switch_to_frame (self .driver , frame , timeout )
14261432
1433+ def switch_to_default_content (self ):
1434+ """ Brings driver control outside the current iframe.
1435+ (If driver control is inside an iframe, the driver control
1436+ will be set to one level above the current frame. If the driver
1437+ control is not currenly in an iframe, nothing will happen.) """
1438+ self .driver .switch_to .default_content ()
1439+
1440+ def open_new_window (self , switch_to = True ):
1441+ """ Opens a new browser tab/window and switches to it by default. """
1442+ self .driver .execute_script ("window.open('');" )
1443+ time .sleep (0.01 )
1444+ if switch_to :
1445+ self .switch_to_window (len (self .driver .window_handles ) - 1 )
1446+
14271447 def switch_to_window (self , window , timeout = settings .SMALL_TIMEOUT ):
14281448 if self .timeout_multiplier and timeout == settings .SMALL_TIMEOUT :
14291449 timeout = self ._get_new_timeout (timeout )
14301450 page_actions .switch_to_window (self .driver , window , timeout )
14311451
1432- def switch_to_default_content (self ):
1433- self .driver . switch_to . default_content ( )
1452+ def switch_to_default_window (self ):
1453+ self .switch_to_window ( 0 )
14341454
14351455 def save_screenshot (self , name , folder = None ):
14361456 return page_actions .save_screenshot (self .driver , name , folder )
14371457
14381458 def get_new_driver (self , browser = None , headless = None ,
1439- servername = None , port = None ,
1440- proxy_string = None ):
1459+ servername = None , port = None , proxy = None , switch_to = True ):
14411460 """ This method spins up an extra browser for tests that require
14421461 more than one. The first browser is already provided by tests
1443- that import base_case.BaseCase from seleniumbase. """
1462+ that import base_case.BaseCase from seleniumbase. If parameters
1463+ aren't specified, the method uses the same as the default driver.
1464+ @Params
1465+ browser - the browser to use. (Ex: "chrome", "firefox")
1466+ headless - the option to run webdriver in headless mode
1467+ servername - if using a Selenium Grid, set the host address here
1468+ port - if using a Selenium Grid, set the host port here
1469+ proxy - if using a proxy server, specify the "host:port" combo here
1470+ switch_to - the option to switch to the new driver (default = True)
1471+ """
14441472 if browser is None :
14451473 browser = self .browser
1474+ browser_name = browser
14461475 if headless is None :
14471476 headless = self .headless
14481477 if servername is None :
14491478 servername = self .servername
14501479 if port is None :
14511480 port = self .port
1452- if proxy_string is None :
1453- proxy_string = self .proxy_string
14541481 use_grid = False
14551482 if servername != "localhost" :
1456- # Use Selenium Grid (Use --server= 127.0.0.1 for localhost Grid)
1483+ # Use Selenium Grid (Use " 127.0.0.1" for localhost Grid)
14571484 use_grid = True
1485+ proxy_string = proxy
1486+ if proxy_string is None :
1487+ proxy_string = self .proxy_string
14581488 valid_browsers = constants .ValidBrowsers .valid_browsers
1459- if browser not in valid_browsers :
1489+ if browser_name not in valid_browsers :
14601490 raise Exception ("Browser: {%s} is not a valid browser option. "
14611491 "Valid options = {%s}" % (browser , valid_browsers ))
1462- new_driver = browser_launcher .get_driver (browser ,
1463- headless ,
1464- use_grid ,
1465- servername ,
1466- port ,
1467- proxy_string )
1468- self ._extra_drivers .append (new_driver )
1492+ new_driver = browser_launcher .get_driver (browser_name = browser_name ,
1493+ headless = headless ,
1494+ use_grid = use_grid ,
1495+ servername = servername ,
1496+ port = port ,
1497+ proxy_string = proxy_string )
1498+ self ._drivers_list .append (new_driver )
1499+ if switch_to :
1500+ self .driver = new_driver
14691501 return new_driver
14701502
1503+ def switch_to_driver (self , driver ):
1504+ """ Sets self.driver to the specified driver.
1505+ You may need this if using self.get_new_driver() in your code. """
1506+ self .driver = driver
1507+
1508+ def switch_to_default_driver (self ):
1509+ """ Sets self.driver to the default/original driver. """
1510+ self .driver = self ._default_driver
1511+
14711512 ############
14721513
14731514 def _get_new_timeout (self , timeout ):
@@ -1846,6 +1887,16 @@ def setUp(self):
18461887 self .servername ,
18471888 self .port ,
18481889 self .proxy_string )
1890+ self ._default_driver = self .driver
1891+ self ._drivers_list .append (self .driver )
1892+ if self .headless :
1893+ # Make sure the invisible browser window is big enough
1894+ try :
1895+ self .set_window_size (1920 , 1200 )
1896+ except Exception :
1897+ # This shouldn't fail, but in case it does, get safely through
1898+ # setUp() so that WebDrivers can get closed during tearDown().
1899+ pass
18491900
18501901 def __insert_test_result (self , state , err ):
18511902 data_payload = TestcaseDataPayload ()
@@ -1880,6 +1931,19 @@ def _add_pytest_html_extra(self):
18801931 except Exception :
18811932 pass
18821933
1934+ def _quit_all_drivers (self ):
1935+ # Close all open browser windows
1936+ self ._drivers_list .reverse () # Last In, First Out
1937+ for driver in self ._drivers_list :
1938+ try :
1939+ driver .quit ()
1940+ except AttributeError :
1941+ pass
1942+ except Exception :
1943+ pass
1944+ self .driver = None
1945+ self ._drivers_list = []
1946+
18831947 def tearDown (self ):
18841948 """
18851949 Be careful if a subclass of BaseCase overrides setUp()
@@ -1939,20 +2003,8 @@ def tearDown(self):
19392003 if self .with_page_source :
19402004 log_helper .log_page_source (
19412005 test_logpath , self .driver )
1942- try :
1943- # Finally close the browser
1944- if self ._extra_drivers :
1945- for extra_driver in self ._extra_drivers :
1946- try :
1947- extra_driver .quit ()
1948- except Exception :
1949- pass # Extra driver was already quit
1950- self .driver .quit ()
1951- except AttributeError :
1952- pass
1953- except Exception :
1954- pass
1955- self .driver = None
2006+ # (Pytest) Finally close all open browser windows
2007+ self ._quit_all_drivers ()
19562008 if self .headless :
19572009 if self .headless_active :
19582010 self .display .stop ()
@@ -1990,18 +2042,5 @@ def tearDown(self):
19902042 data_payload .logURL = index_file
19912043 self .testcase_manager .update_testcase_log_url (data_payload )
19922044 else :
1993- # Using Nosetests
1994- try :
1995- # Finally close the browser
1996- if self ._extra_drivers :
1997- for extra_driver in self ._extra_drivers :
1998- try :
1999- extra_driver .quit ()
2000- except Exception :
2001- pass # Extra driver was already quit
2002- self .driver .quit ()
2003- except AttributeError :
2004- pass
2005- except Exception :
2006- pass
2007- self .driver = None
2045+ # (Nosetests) Finally close all open browser windows
2046+ self ._quit_all_drivers ()
0 commit comments