Skip to content

Commit aaea8dc

Browse files
pekkaklarckaaltat
authored andcommitted
Window manager cleanup (robotframework#955)
* Make WindowManage ContextAwere Clean up getting window information. Also removed strange and totally undocumented Selenium 1 backwards compatibility code related to unnamed windows in Get Window Names.
1 parent 2b57040 commit aaea8dc

File tree

5 files changed

+190
-274
lines changed

5 files changed

+190
-274
lines changed

src/SeleniumLibrary/keywords/browsermanagement.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class BrowserManagementKeywords(LibraryComponent):
5454

5555
def __init__(self, ctx):
5656
LibraryComponent.__init__(self, ctx)
57-
self._window_manager = WindowManager()
57+
self._window_manager = WindowManager(ctx)
5858

5959
@keyword
6060
def close_all_browsers(self):
@@ -247,23 +247,20 @@ def close_window(self):
247247
@keyword
248248
def get_window_identifiers(self):
249249
"""Returns and logs id attributes of all known browser windows."""
250-
return self._log_list(self._window_manager.get_window_ids(self.browser))
250+
ids = [info.id for info in self._window_manager.get_window_infos()]
251+
return self._log_list(ids)
251252

252253
@keyword
253254
def get_window_names(self):
254255
"""Returns and logs names of all known browser windows."""
255-
values = self._window_manager.get_window_names(self.browser)
256-
# for backward compatibility, since Selenium 1 would always
257-
# return this constant value for the main window
258-
if len(values) and values[0] == 'undefined':
259-
values[0] = 'selenium_main_app_window'
260-
261-
return self._log_list(values)
256+
names = [info.name for info in self._window_manager.get_window_infos()]
257+
return self._log_list(names)
262258

263259
@keyword
264260
def get_window_titles(self):
265261
"""Returns and logs titles of all known browser windows."""
266-
return self._log_list(self._window_manager.get_window_titles(self.browser))
262+
titles = [info.title for info in self._window_manager.get_window_infos()]
263+
return self._log_list(titles)
267264

268265
@keyword
269266
def maximize_browser_window(self):
@@ -389,7 +386,7 @@ def select_window(self, locator=None):
389386
except NoSuchWindowException:
390387
pass
391388
finally:
392-
self._window_manager.select(self.browser, locator)
389+
self._window_manager.select(locator)
393390

394391
@keyword
395392
def list_windows(self):
@@ -412,9 +409,8 @@ def get_location(self):
412409
@keyword
413410
def get_locations(self):
414411
"""Returns and logs URLs of all known browser windows."""
415-
return self._log_list(
416-
[window_info[4] for window_info in
417-
self._window_manager._get_window_infos(self.browser)])
412+
urls = [info.url for info in self._window_manager.get_window_infos()]
413+
return self._log_list(urls)
418414

419415
@keyword
420416
def get_source(self):

src/SeleniumLibrary/locators/windowmanager.py

Lines changed: 37 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -14,47 +14,58 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17-
from selenium.common.exceptions import NoSuchWindowException
18-
from selenium.common.exceptions import WebDriverException
17+
from collections import namedtuple
1918

19+
from selenium.common.exceptions import (NoSuchWindowException,
20+
WebDriverException)
2021

21-
class WindowManager(object):
22+
from SeleniumLibrary.base import ContextAware
2223

23-
def __init__(self):
24+
25+
WindowInfo = namedtuple('WindowInfo', 'handle, id, name, title, url')
26+
27+
28+
class WindowManager(ContextAware):
29+
30+
def __init__(self, ctx):
2431
self._strategies = {
2532
'title': self._select_by_title,
2633
'name': self._select_by_name,
2734
'url': self._select_by_url,
2835
None: self._select_by_default
2936
}
37+
ContextAware.__init__(self, ctx)
3038

31-
def get_window_ids(self, browser):
32-
return [ window_info[1] for window_info in self._get_window_infos(browser) ]
33-
34-
def get_window_names(self, browser):
35-
return [ window_info[2] for window_info in self._get_window_infos(browser) ]
36-
37-
def get_window_titles(self, browser):
38-
return [ window_info[3] for window_info in self._get_window_infos(browser) ]
39+
def get_window_infos(self):
40+
infos = []
41+
try:
42+
starting_handle = self.browser.current_window_handle
43+
except NoSuchWindowException:
44+
starting_handle = None
45+
try:
46+
for handle in self.browser.window_handles:
47+
self.browser.switch_to.window(handle)
48+
infos.append(self._get_current_window_info(self.browser))
49+
finally:
50+
if starting_handle:
51+
self.browser.switch_to.window(starting_handle)
52+
return infos
3953

40-
def select(self, browser, locator):
41-
assert browser is not None
54+
def select(self, locator):
4255
if locator is not None:
4356
if isinstance(locator, list):
44-
self._select_by_excludes(browser, locator)
57+
self._select_by_excludes(self.browser, locator)
4558
return
4659
if locator.lower() == "self" or locator.lower() == "current":
4760
return
4861
if locator.lower() == "new" or locator.lower() == "popup":
49-
self._select_by_last_index(browser)
62+
self._select_by_last_index(self.browser)
5063
return
5164
(prefix, criteria) = self._parse_locator(locator)
5265
strategy = self._strategies.get(prefix)
5366
if strategy is None:
5467
raise ValueError("Window locator with prefix '" + prefix + "' is not supported")
55-
return strategy(browser, criteria)
56-
57-
# Strategy routines, private
68+
return strategy(self.browser, criteria)
5869

5970
def _select_by_title(self, browser, criteria):
6071
self._select_matching(
@@ -112,8 +123,6 @@ def _select_by_excludes(self, browser, excludes):
112123
return
113124
raise ValueError("Unable to locate new window")
114125

115-
# Private
116-
117126
def _parse_locator(self, locator):
118127
prefix = None
119128
criteria = locator
@@ -127,21 +136,6 @@ def _parse_locator(self, locator):
127136
criteria = ''
128137
return (prefix, criteria)
129138

130-
def _get_window_infos(self, browser):
131-
window_infos = []
132-
try:
133-
starting_handle = browser.current_window_handle
134-
except NoSuchWindowException:
135-
starting_handle = None
136-
try:
137-
for handle in browser.window_handles:
138-
browser.switch_to.window(handle)
139-
window_infos.append(self._get_current_window_info(browser))
140-
finally:
141-
if starting_handle:
142-
browser.switch_to.window(starting_handle)
143-
return window_infos
144-
145139
def _select_matching(self, browser, matcher, error):
146140
try:
147141
starting_handle = browser.current_window_handle
@@ -157,18 +151,13 @@ def _select_matching(self, browser, matcher, error):
157151

158152
def _get_current_window_info(self, browser):
159153
try:
160-
id_, name = browser.execute_script("return [ window.id, window.name ];")
154+
id, name = browser.execute_script("return [ window.id, window.name ];")
161155
except WebDriverException:
162156
# The webdriver implementation doesn't support Javascript so we
163157
# can't get window id or name this way.
164-
id_ = None
165-
name = ''
166-
167-
title = browser.title
168-
url = browser.current_url
169-
170-
id_ = id_ if id_ is not None else 'undefined'
171-
name, title, url = (
172-
att if att else 'undefined' for att in (name, title, url)
173-
)
174-
return browser.current_window_handle, id_, name, title, url
158+
id = name = None
159+
return WindowInfo(browser.current_window_handle,
160+
id if id is not None else 'undefined',
161+
name or 'undefined',
162+
browser.title or 'undefined',
163+
browser.current_url or 'undefined')

test/acceptance/windows.robot

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ Get Locations
3838
Lists Should Be Equal ${urls} ${expected_urls}
3939

4040
Get Window Names
41-
${exp_names}= Create List selenium_main_app_window myName
41+
${exp_names}= Create List undefined myName
42+
Click Link my popup
4243
Wait Until New Window Is Open
4344
${names}= Get Window Names
4445
Should Be Equal ${names} ${exp_names}

test/unit/keywords/test_windowmananger_window_info.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def mock_window_info(self, driver, id_, name, title, url):
1717
driver.current_url = url
1818

1919
def test_window_info_values_are_strings(self):
20-
manager = WindowManager()
20+
manager = WindowManager(None)
2121
driver = mock()
2222
self.mock_window_info(driver, 'id', 'name', 'title', 'url')
2323
driver.current_window_handle = HANDLE
@@ -26,7 +26,7 @@ def test_window_info_values_are_strings(self):
2626
unstub()
2727

2828
def test_window_info_values_are_none(self):
29-
manager = WindowManager()
29+
manager = WindowManager(None)
3030
driver = mock()
3131
self.mock_window_info(driver, None, None, None, None)
3232
driver.current_window_handle = HANDLE
@@ -37,7 +37,7 @@ def test_window_info_values_are_none(self):
3737
unstub()
3838

3939
def test_window_info_values_are_empty_strings(self):
40-
manager = WindowManager()
40+
manager = WindowManager(None)
4141
driver = mock()
4242
self.mock_window_info(driver, '', '', '', '')
4343
driver.current_window_handle = HANDLE
@@ -48,7 +48,7 @@ def test_window_info_values_are_empty_strings(self):
4848
unstub()
4949

5050
def test_window_id_is_bool(self):
51-
manager = WindowManager()
51+
manager = WindowManager(None)
5252
driver = mock()
5353
self.mock_window_info(driver, True, '', '', '')
5454
driver.current_window_handle = HANDLE
@@ -60,7 +60,7 @@ def test_window_id_is_bool(self):
6060
unstub()
6161

6262
def test_window_id_is_web_element(self):
63-
manager = WindowManager()
63+
manager = WindowManager(None)
6464
driver = mock()
6565
elem = mock()
6666
self.mock_window_info(driver, *[elem, '', '', ''])
@@ -70,7 +70,7 @@ def test_window_id_is_web_element(self):
7070
unstub()
7171

7272
def test_window_id_is_container(self):
73-
manager = WindowManager()
73+
manager = WindowManager(None)
7474
driver = mock()
7575
self.mock_window_info(driver, *[['1'], '', '', ''])
7676
driver.current_window_handle = HANDLE
@@ -83,7 +83,7 @@ def test_window_id_is_container(self):
8383
unstub()
8484

8585
def test_window_id_is_empty_container(self):
86-
manager = WindowManager()
86+
manager = WindowManager(None)
8787
driver = mock()
8888
self.mock_window_info(driver, *[[], '', '', ''])
8989
driver.current_window_handle = HANDLE
@@ -95,7 +95,7 @@ def test_window_id_is_empty_container(self):
9595
unstub()
9696

9797
def test_no_javascript_support(self):
98-
manager = WindowManager()
98+
manager = WindowManager(None)
9999
driver = mock()
100100
elem = mock()
101101
when(driver).execute_script(SCRIPT).thenRaise(WebDriverException)

0 commit comments

Comments
 (0)