From 9a80a3c3c918466e17f17478f46dacb23d70cd47 Mon Sep 17 00:00:00 2001 From: divfor Date: Fri, 22 May 2015 21:47:44 +0800 Subject: [PATCH 01/10] add code changes --- .../locators/windowmanager.py | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/Selenium2Library/locators/windowmanager.py b/src/Selenium2Library/locators/windowmanager.py index 5740d38a5..97f48f74c 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,21 +60,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): From c2089a40b494b2534d8217a2cbd2bab50b4d614b Mon Sep 17 00:00:00 2001 From: divfor Date: Fri, 22 May 2015 21:53:31 +0800 Subject: [PATCH 02/10] add code changes --- .../keywords/_browsermanagement.py | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Selenium2Library/keywords/_browsermanagement.py b/src/Selenium2Library/keywords/_browsermanagement.py index 57b673edf..f53ce76cf 100644 --- a/src/Selenium2Library/keywords/_browsermanagement.py +++ b/src/Selenium2Library/keywords/_browsermanagement.py @@ -289,8 +289,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 +302,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 +322,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 list_windows(self): + """Return all current window handles as a list""" + return self._current_browser().get_window_handles() + + 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 unselect_frame(self): """Sets the top frame as the current frame.""" From 60a3c262b4509eb9b520f3aa6fed7f20c46b6dd4 Mon Sep 17 00:00:00 2001 From: divfor Date: Fri, 22 May 2015 21:58:09 +0800 Subject: [PATCH 03/10] Update CHANGES.rst --- CHANGES.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 12faafcce..7fb9adf3d 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] + - Fixed ‘NoSuchWindowException' issue. Running keyword 'Select Window' after 'Close Window' will trigger this issue if locator has prefix 'name=','title=' or 'url='. Also fixed same issue for keywords 'Get Window Ids', 'Get Window Titles' and 'Get Window Names'. From d51327c6b1d2105b8e0398d77f0daffe08fd7a6e Mon Sep 17 00:00:00 2001 From: divfor Date: Fri, 22 May 2015 22:12:52 +0800 Subject: [PATCH 04/10] Update CHANGES.rst --- CHANGES.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 7fb9adf3d..ea70204eb 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,12 +3,11 @@ 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. +- Added keyword 'Close Window And Select' to simplify 'Close Window' + 'Select Window'. +- Added keyword 'List Windows' to return a list of all window handles. +- Enhanced 'Select Window' to return window handle, accept window handle as locator, + and select new window by excluding a list of window handles (the strict way), or + by special locator 'new' (the simplified but less strict way) [divfor] - Fixed ‘NoSuchWindowException' issue. Running keyword 'Select Window' after 'Close Window' From 67c62b142d9a59717c4938484ff8e4abe49aba30 Mon Sep 17 00:00:00 2001 From: divfor Date: Sat, 23 May 2015 21:00:37 +0800 Subject: [PATCH 05/10] add test cases for enhancing select window --- test/acceptance/windows.txt | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/acceptance/windows.txt b/test/acceptance/windows.txt index fcee45955..d6977c965 100644 --- a/test/acceptance/windows.txt +++ b/test/acceptance/windows.txt @@ -62,6 +62,39 @@ 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 And Select main + Title Should Be Click link to show a popup window + *Keywords* Open Popup Window, Select It And Verify [Arguments] ${window_id} From aeeacfa5c6cf506d89360e320359212314bdd195 Mon Sep 17 00:00:00 2001 From: divfor Date: Sat, 23 May 2015 21:54:05 +0800 Subject: [PATCH 06/10] minor fix --- src/Selenium2Library/keywords/_browsermanagement.py | 1 + src/Selenium2Library/locators/windowmanager.py | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Selenium2Library/keywords/_browsermanagement.py b/src/Selenium2Library/keywords/_browsermanagement.py index f53ce76cf..aac427bd0 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') diff --git a/src/Selenium2Library/locators/windowmanager.py b/src/Selenium2Library/locators/windowmanager.py index 97f48f74c..75ca8954a 100644 --- a/src/Selenium2Library/locators/windowmanager.py +++ b/src/Selenium2Library/locators/windowmanager.py @@ -27,11 +27,12 @@ def select(self, browser, locator): 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 + if locator is not None: + 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: From b66a01b90bcbd5058cb8c7f241a591f9a36b81c2 Mon Sep 17 00:00:00 2001 From: divfor Date: Sun, 24 May 2015 08:52:43 +0800 Subject: [PATCH 07/10] update changelog --- CHANGES.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index ea70204eb..d64118d43 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,10 +3,9 @@ Release Notes 1.7 (unreleased) ---------------- -- Added keyword 'Close Window And Select' to simplify 'Close Window' + 'Select Window'. - Added keyword 'List Windows' to return a list of all window handles. -- Enhanced 'Select Window' to return window handle, accept window handle as locator, - and select new window by excluding a list of window handles (the strict way), or +- 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] From f51c451081312d4df18d768dc7c278f8237059be Mon Sep 17 00:00:00 2001 From: divfor Date: Sun, 24 May 2015 08:54:13 +0800 Subject: [PATCH 08/10] remove close window and select --- src/Selenium2Library/keywords/_browsermanagement.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Selenium2Library/keywords/_browsermanagement.py b/src/Selenium2Library/keywords/_browsermanagement.py index aac427bd0..e048d4431 100644 --- a/src/Selenium2Library/keywords/_browsermanagement.py +++ b/src/Selenium2Library/keywords/_browsermanagement.py @@ -334,13 +334,6 @@ def list_windows(self): """Return all current window handles as a list""" return self._current_browser().get_window_handles() - 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 unselect_frame(self): """Sets the top frame as the current frame.""" self._current_browser().switch_to_default_content() From 589731169738660813430122694a28d736ffc626 Mon Sep 17 00:00:00 2001 From: divfor Date: Sun, 24 May 2015 09:00:15 +0800 Subject: [PATCH 09/10] update test cases --- test/acceptance/windows.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/acceptance/windows.txt b/test/acceptance/windows.txt index d6977c965..d76a8e8b5 100644 --- a/test/acceptance/windows.txt +++ b/test/acceptance/windows.txt @@ -92,7 +92,8 @@ Select Window By Special Locator ${parent}= Select Window new Title Should Be Original Should Be True '${start}' == '${parent}' - Close Window And Select main + Close Window + Select Window main Title Should Be Click link to show a popup window *Keywords* From 5cf78a365555ffaeef9d276d16ce4ea286e2a240 Mon Sep 17 00:00:00 2001 From: divfor Date: Sun, 24 May 2015 09:12:33 +0800 Subject: [PATCH 10/10] minor fix - skip None locator --- src/Selenium2Library/locators/windowmanager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Selenium2Library/locators/windowmanager.py b/src/Selenium2Library/locators/windowmanager.py index 75ca8954a..6159542f9 100644 --- a/src/Selenium2Library/locators/windowmanager.py +++ b/src/Selenium2Library/locators/windowmanager.py @@ -24,10 +24,10 @@ 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 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":