diff --git a/CHANGES.rst b/CHANGES.rst index 6448f35ea..9adb73dc3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,6 +3,12 @@ Release Notes 1.7 (unreleased) ---------------- +- Added keyword 'List Windows' to return a list of all window handles. +- Enabled 'Select Window' to return window handle as well as accept it as locator, and + select new popup window by excluding previous window handles (the strict way) or + by special locator 'new' (the simplified but less strict way) + [divfor] + - Added new keyword 'Wait Until Page Does Not Contain'. [deiga] diff --git a/src/Selenium2Library/keywords/_browsermanagement.py b/src/Selenium2Library/keywords/_browsermanagement.py index 57b673edf..e048d4431 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,11 @@ 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 + window list: select the first window not in given list (See 'List Windows' to get the list) It is also possible to specify the approach Selenium2Library should take to find a window by specifying a locator strategy: @@ -315,7 +323,16 @@ 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 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 5740d38a5..6159542f9 100644 --- a/src/Selenium2Library/locators/windowmanager.py +++ b/src/Selenium2Library/locators/windowmanager.py @@ -24,7 +24,15 @@ def get_window_titles(self, browser): def select(self, browser, locator): assert browser is not None - + if locator 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,21 +61,35 @@ 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 - - try: - self._select_by_name(browser, criteria) - return - except ValueError: pass - + 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_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 def _parse_locator(self, locator): diff --git a/test/acceptance/windows.txt b/test/acceptance/windows.txt index fcee45955..d76a8e8b5 100644 --- a/test/acceptance/windows.txt +++ b/test/acceptance/windows.txt @@ -62,6 +62,40 @@ Get Window Titles After Close Window Close Window ${titles}= Get Window Titles +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 + Select Window main + Title Should Be Click link to show a popup window + *Keywords* Open Popup Window, Select It And Verify [Arguments] ${window_id}