diff --git a/CHANGES.rst b/CHANGES.rst index f2c8e78be..a2292f79e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,6 +3,14 @@ Release Notes 1.7 (unreleased) ---------------- +- Added 'Close Window And Select' to simplify 'Close Window' + 'Select Window'. + Added 'List Windows' to return a list of all current handles. + Enhanced 'Select Window' to select new window by excluding a list of window handles + (the strict way), or by special locator 'new' (the simplified but less strict way) + Enhanced 'Select Window' to accept window handle as locator, and special locator + 'self' to return current window handle. + [divfor] + - Corrected error message in new keyword 'Wait Until Element Is Not Visible' to reflect element being visible instead of not visible. [joepurdy] diff --git a/src/Selenium2Library/keywords/_browsermanagement.py b/src/Selenium2Library/keywords/_browsermanagement.py index 57b673edf..e2740ca93 100644 --- a/src/Selenium2Library/keywords/_browsermanagement.py +++ b/src/Selenium2Library/keywords/_browsermanagement.py @@ -6,6 +6,7 @@ from Selenium2Library.utils import BrowserCache from Selenium2Library.locators import WindowManager from keywordgroup import KeywordGroup +from selenium.common.exceptions import NoSuchWindowException ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) FIREFOX_PROFILE_DIR = os.path.join(ROOT_DIR, 'resources', 'firefoxprofile') @@ -289,8 +290,11 @@ def select_frame(self, locator): self._current_browser().switch_to_frame(element) def select_window(self, locator=None): - """Selects the window found with `locator` as the context of actions. - + """Selects the window matching locator and return previous window handle. + + locator: any of name, title, url, window handle, excluded handle's list, or special words. + return: either current window handle before selecting, or None if no current window. + If the window is found, all subsequent commands use that window, until this keyword is used again. If the window is not found, this keyword fails. @@ -299,7 +303,12 @@ def select_window(self, locator=None): javascript name of the window. If multiple windows with same identifier are found, the first one is selected. - Special locator `main` (default) can be used to select the main window. + There are some special locators for searching target window: + string 'main' (default): select the main window; + string 'self': only return current window handle; + string 'new': select the last-indexed window assuming it is the newest opened window + list of window handle: select the first window not in the list + See 'List Windows' to get window handle list It is also possible to specify the approach Selenium2Library should take to find a window by specifying a locator strategy: @@ -315,7 +324,23 @@ def select_window(self, locator=None): | Title Should Be | Popup Title | | Select Window | | | # Chooses the main window again | """ - self._window_manager.select(self._current_browser(), locator) + try: + return self._current_browser().get_current_window_handle() + except NoSuchWindowException: + pass + finally: + self._window_manager.select(self._current_browser(), locator) + + def close_window_and_select(self, locator=None): + """Closes current window and then switch to the window matching given locator. + See 'Select Window' keyword for same locator requirement + """ + self._current_browser().close() + return self.select_window(locator) + + def list_windows(self): + """Return all current window handles as a list""" + return self._current_browser().get_window_handles() def unselect_frame(self): """Sets the top frame as the current frame.""" diff --git a/src/Selenium2Library/locators/windowmanager.py b/src/Selenium2Library/locators/windowmanager.py index c03fac8eb..9b6259742 100644 --- a/src/Selenium2Library/locators/windowmanager.py +++ b/src/Selenium2Library/locators/windowmanager.py @@ -24,7 +24,14 @@ def get_window_titles(self, browser): def select(self, browser, locator): assert browser is not None - + if isinstance(locator, list): + self._select_by_excludes(browser, locator) + return + if locator.lower() == "self" or locator.lower() == "current": + return + if locator.lower() == "new" or locator.lower() == "popup": + self._select_by_last_index(browser) + return (prefix, criteria) = self._parse_locator(locator) strategy = self._strategies.get(prefix) if strategy is None: @@ -53,20 +60,34 @@ def _select_by_url(self, browser, criteria): def _select_by_default(self, browser, criteria): if criteria is None or len(criteria) == 0 or criteria.lower() == "null": - browser.switch_to_window('') + browser.switch_to_window(browser.get_window_handles()[0]) return + for handle in browser.get_window_handles(): + browser.switch_to_window(handle) + if criteria == handle: + return + for item in browser.get_current_window_info()[2:4]: + if item.strip().lower() == criteria.lower(): + return + raise ValueError("Unable to locate window with handle or name or title or URL '" + criteria + "'") + def _select_by_last_index(self, browser): + handles = browser.get_window_handles() try: - self._select_by_name(browser, criteria) - return - except ValueError: pass - - try: - self._select_by_title(browser, criteria) - return - except ValueError: pass - - raise ValueError("Unable to locate window with name or title '" + criteria + "'") + if handles[-1] == browser.get_current_window_handle(): + raise AssertionError("Unable to get new window from last index. Please use '@{ex}= | List Windows' + new window trigger + 'Select Window | ${ex}'") + except IndexError: + raise AssertionError("No window found") + except NoSuchWindowException: + raise AssertionError("Currently no focus window. where are you making a popup window?") + browser.switch_to_window(handles[-1]) + + def _select_by_excludes(self, browser, excludes): + for handle in browser.get_window_handles(): + if handle not in excludes: + browser.switch_to_window(handle) + return + raise ValueError("Unable to locate new window") # Private diff --git a/test/acceptance/windows.txt b/test/acceptance/windows.txt index 552d3754d..874793834 100644 --- a/test/acceptance/windows.txt +++ b/test/acceptance/windows.txt @@ -41,7 +41,6 @@ Get and Set Window Size Should Be Equal ${returned_width} ${win_width} Should Be Equal ${returned_height} ${win_height} - Get and Set Window Position ${position_x}= Set Variable ${100} ${position_y}= Set Variable ${100} @@ -50,6 +49,39 @@ Get and Set Window Position Should Be Equal ${position_x} ${returned_x} Should Be Equal ${position_y} ${returned_y} +Select Window By Handle + Cannot Be Executed in IE + Click Link my popup + ${parent}= Select Window Original + Title Should Be Original + ${child}= Select Window ${parent} + Title Should Be Click link to show a popup window + Select Window ${child} + Close Window + ${FromWindow}= Select Window ${parent} + Title Should Be Click link to show a popup window + Should Be True ${FromWindow} == None + +Select Popup Window By Excluded List + Cannot Be Executed in IE + @{excluded_handle_list}= List Windows + Click Link my popup + ${parent}= Select Window ${excluded_handle_list} + Title Should Be Original + Close Window + Select Window ${parent} + Title Should Be Click link to show a popup window + +Select Window By Special Locator + Cannot Be Executed in IE + ${start}= Select Window self + Click Link my popup + ${parent}= Select Window new + Title Should Be Original + Should Be True '${start}' == '${parent}' + Close Window And Select main + Title Should Be Click link to show a popup window + *Keywords* Open Popup Window, Select It And Verify