Skip to content

Commit 783580b

Browse files
committed
Merge pull request #407 from divfor/Enhance-Select-Window
Enhance select window
2 parents 9336b8c + 2f6a88a commit 783580b

File tree

4 files changed

+104
-16
lines changed

4 files changed

+104
-16
lines changed

CHANGES.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ Release Notes
33

44
1.7 (unreleased)
55
----------------
6+
- Added keyword 'List Windows' to return a list of all window handles.
7+
[divfor]
8+
9+
- Enabled 'Select Window' to return window handle as well as accept it as locator, and
10+
select new popup window by excluding previous window handles (the strict way) or
11+
by special locator 'new' (the simplified but less strict way).
12+
[divfor]
13+
614
- Added new keyword 'Wait Until Page Does Not Contain'.
715
[deiga]
816

src/Selenium2Library/keywords/_browsermanagement.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from Selenium2Library.utils import BrowserCache
77
from Selenium2Library.locators import WindowManager
88
from keywordgroup import KeywordGroup
9+
from selenium.common.exceptions import NoSuchWindowException
910

1011
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
1112
FIREFOX_PROFILE_DIR = os.path.join(ROOT_DIR, 'resources', 'firefoxprofile')
@@ -289,8 +290,11 @@ def select_frame(self, locator):
289290
self._current_browser().switch_to_frame(element)
290291

291292
def select_window(self, locator=None):
292-
"""Selects the window found with `locator` as the context of actions.
293-
293+
"""Selects the window matching locator and return previous window handle.
294+
295+
locator: any of name, title, url, window handle, excluded handle's list, or special words.
296+
return: either current window handle before selecting, or None if no current window.
297+
294298
If the window is found, all subsequent commands use that window, until
295299
this keyword is used again. If the window is not found, this keyword fails.
296300
@@ -299,7 +303,11 @@ def select_window(self, locator=None):
299303
javascript name of the window. If multiple windows with
300304
same identifier are found, the first one is selected.
301305
302-
Special locator `main` (default) can be used to select the main window.
306+
There are some special locators for searching target window:
307+
string 'main' (default): select the main window;
308+
string 'self': only return current window handle;
309+
string 'new': select the last-indexed window assuming it is the newest opened window
310+
window list: select the first window not in given list (See 'List Windows' to get the list)
303311
304312
It is also possible to specify the approach Selenium2Library should take
305313
to find a window by specifying a locator strategy:
@@ -315,7 +323,16 @@ def select_window(self, locator=None):
315323
| Title Should Be | Popup Title |
316324
| Select Window | | | # Chooses the main window again |
317325
"""
318-
self._window_manager.select(self._current_browser(), locator)
326+
try:
327+
return self._current_browser().get_current_window_handle()
328+
except NoSuchWindowException:
329+
pass
330+
finally:
331+
self._window_manager.select(self._current_browser(), locator)
332+
333+
def list_windows(self):
334+
"""Return all current window handles as a list"""
335+
return self._current_browser().get_window_handles()
319336

320337
def unselect_frame(self):
321338
"""Sets the top frame as the current frame."""

src/Selenium2Library/locators/windowmanager.py

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@ def get_window_titles(self, browser):
2424

2525
def select(self, browser, locator):
2626
assert browser is not None
27-
27+
if locator is not None:
28+
if isinstance(locator, list):
29+
self._select_by_excludes(browser, locator)
30+
return
31+
if locator.lower() == "self" or locator.lower() == "current":
32+
return
33+
if locator.lower() == "new" or locator.lower() == "popup":
34+
self._select_by_last_index(browser)
35+
return
2836
(prefix, criteria) = self._parse_locator(locator)
2937
strategy = self._strategies.get(prefix)
3038
if strategy is None:
@@ -53,21 +61,42 @@ def _select_by_url(self, browser, criteria):
5361

5462
def _select_by_default(self, browser, criteria):
5563
if criteria is None or len(criteria) == 0 or criteria.lower() == "null":
56-
browser.switch_to_window('')
64+
handles = browser.get_window_handles()
65+
browser.switch_to_window(handles[0])
5766
return
58-
5967
try:
60-
self._select_by_name(browser, criteria)
61-
return
62-
except ValueError: pass
63-
68+
starting_handle = browser.get_current_window_handle()
69+
except NoSuchWindowException:
70+
starting_handle = None
71+
for handle in browser.get_window_handles():
72+
browser.switch_to_window(handle)
73+
if criteria == handle:
74+
return
75+
for item in browser.get_current_window_info()[2:4]:
76+
if item.strip().lower() == criteria.lower():
77+
return
78+
if starting_handle:
79+
browser.switch_to_window(starting_handle)
80+
raise ValueError("Unable to locate window with handle or name or title or URL '" + criteria + "'")
81+
82+
def _select_by_last_index(self, browser):
83+
handles = browser.get_window_handles()
6484
try:
65-
self._select_by_title(browser, criteria)
66-
return
67-
except ValueError: pass
68-
69-
raise ValueError("Unable to locate window with name or title '" + criteria + "'")
85+
if handles[-1] == browser.get_current_window_handle():
86+
raise AssertionError("No new window at last index. Please use '@{ex}= | List Windows' + new window trigger + 'Select Window | ${ex}' to find it.")
87+
except IndexError:
88+
raise AssertionError("No window found")
89+
except NoSuchWindowException:
90+
raise AssertionError("Currently no focus window. where are you making a popup window?")
91+
browser.switch_to_window(handles[-1])
7092

93+
def _select_by_excludes(self, browser, excludes):
94+
for handle in browser.get_window_handles():
95+
if handle not in excludes:
96+
browser.switch_to_window(handle)
97+
return
98+
raise ValueError("Unable to locate new window")
99+
71100
# Private
72101

73102
def _parse_locator(self, locator):

test/acceptance/windows.txt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,40 @@ Get Window Titles After Close Window
6262
Close Window
6363
${titles}= Get Window Titles
6464

65+
Select Window By Handle
66+
Cannot Be Executed in IE
67+
Click Link my popup
68+
${parent}= Select Window Original
69+
Title Should Be Original
70+
${child}= Select Window ${parent}
71+
Title Should Be Click link to show a popup window
72+
Select Window ${child}
73+
Close Window
74+
${FromWindow}= Select Window ${parent}
75+
Title Should Be Click link to show a popup window
76+
Should Be True ${FromWindow} == None
77+
78+
Select Popup Window By Excluded List
79+
Cannot Be Executed in IE
80+
@{excluded_handle_list}= List Windows
81+
Click Link my popup
82+
${parent}= Select Window ${excluded_handle_list}
83+
Title Should Be Original
84+
Close Window
85+
Select Window ${parent}
86+
Title Should Be Click link to show a popup window
87+
88+
Select Window By Special Locator
89+
Cannot Be Executed in IE
90+
${start}= Select Window self
91+
Click Link my popup
92+
${parent}= Select Window new
93+
Title Should Be Original
94+
Should Be True '${start}' == '${parent}'
95+
Close Window
96+
Select Window main
97+
Title Should Be Click link to show a popup window
98+
6599
*Keywords*
66100
Open Popup Window, Select It And Verify
67101
[Arguments] ${window_id}

0 commit comments

Comments
 (0)