forked from robotframework/SeleniumLibrary
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwindow.py
More file actions
291 lines (233 loc) · 12.3 KB
/
window.py
File metadata and controls
291 lines (233 loc) · 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# Copyright 2008-2011 Nokia Networks
# Copyright 2011-2016 Ryan Tomac, Ed Manlove and contributors
# Copyright 2016- Robot Framework Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import time
from SeleniumLibrary.utils import is_truthy, is_falsy, timestr_to_secs
from selenium.common.exceptions import NoSuchWindowException
from SeleniumLibrary.base import keyword, LibraryComponent
from SeleniumLibrary.locators import WindowManager
from SeleniumLibrary.utils import plural_or_not, is_string
class WindowKeywords(LibraryComponent):
def __init__(self, ctx):
LibraryComponent.__init__(self, ctx)
self._window_manager = WindowManager(ctx)
@keyword
def select_window(self, locator='MAIN', timeout=None):
"""DEPRECATED in SeleniumLibrary 4.0. , use `Switch Window` instead."""
return self.switch_window(locator, timeout)
@keyword
def switch_window(self, locator='MAIN', timeout=None, browser='CURRENT'):
"""Switches to browser window matching ``locator``.
If the window is found, all subsequent commands use the selected
window, until this keyword is used again. If the window is not
found, this keyword fails. The previous window handle is returned,
and can be used to return back to it later.
Notice that alerts should be handled with
`Handle Alert` or other alert related keywords.
The ``locator`` can be specified using different strategies somewhat
similarly as when `locating elements` on pages.
- By default the ``locator`` is matched against window handle, name,
title, and URL. Matching is done in that order and the the first
matching window is selected.
- The ``locator`` can specify an explicit strategy by using format
``strategy:value`` (recommended) or ``strategy=value``. Supported
strategies are ``name``, ``title`` and ``url``, which match windows
using name, title, and URL, respectively. Additionally, ``default``
can be used to explicitly use the default strategy explained above.
- If the ``locator`` is ``NEW`` (case-insensitive), the latest
opened window is selected. It is an error if this is the same
as the current window.
- If the ``locator`` is ``MAIN`` (default, case-insensitive),
the main window is selected.
- If the ``locator`` is ``CURRENT`` (case-insensitive), nothing is
done. This effectively just returns the current window handle.
- If the ``locator`` is not a string, it is expected to be a list
of window handles _to exclude_. Such a list of excluded windows
can be get from `Get Window Handles` prior to doing an action that
opens a new window.
The ``timeout`` is used to specify how long keyword will poll to select
the new window. The ``timeout`` is new in SeleniumLibrary 3.2.
Example:
| `Click Link` | popup1 | | # Open new window |
| `Switch Window` | example | | # Select window using default strategy |
| `Title Should Be` | Pop-up 1 | |
| `Click Button` | popup2 | | # Open another window |
| ${handle} = | `Switch Window` | NEW | # Select latest opened window |
| `Title Should Be` | Pop-up 2 | |
| `Switch Window` | ${handle} | | # Select window using handle |
| `Title Should Be` | Pop-up 1 | |
| `Switch Window` | MAIN | | # Select the main window |
| `Title Should Be` | Main | |
| ${excludes} = | `Get Window Handles` | | # Get list of current windows |
| `Click Link` | popup3 | | # Open one more window |
| `Switch Window` | ${excludes} | | # Select window using excludes |
| `Title Should Be` | Pop-up 3 | |
The ``browser`` argument allows with ``index_or_alias`` to implicitly switch to
a specific browser when switching to a window. See `Switch Browser`
- If the ``browser`` is ``CURRENT`` (case-insensitive), no other browser is
selected.
*NOTE:*
- The ``strategy:value`` syntax is only supported by SeleniumLibrary
3.0 and newer.
- Prior to SeleniumLibrary 3.0 matching windows by name, title
and URL was case-insensitive.
- Earlier versions supported aliases ``None``, ``null`` and the
empty string for selecting the main window, and alias ``self``
for selecting the current window. Support for these aliases were
removed in SeleniumLibrary 3.2.
"""
epoch = time.time()
timeout = epoch if is_falsy(timeout) else timestr_to_secs(timeout) + epoch
try:
return self.driver.current_window_handle
except NoSuchWindowException:
pass
finally:
if not is_string(browser) or not browser.upper() == 'CURRENT':
self.drivers.switch(browser)
self._window_manager.select(locator, timeout)
@keyword
def close_window(self):
"""Closes currently opened and selected browser window/tab. """
self.driver.close()
@keyword
def get_window_handles(self, browser='CURRENT'):
"""Returns all child window handles of the selected browser as a list.
Can be used as a list of windows to exclude with `Select Window`.
How to select the ``browser`` scope of this keyword, see `Get Locations`.
Prior to SeleniumLibrary 3.0, this keyword was named `List Windows`.
"""
return self._window_manager.get_window_handles(browser)
@keyword
def get_window_identifiers(self, browser='CURRENT'):
"""Returns and logs id attributes of all windows of the selected browser.
How to select the ``browser`` scope of this keyword, see `Get Locations`."""
ids = [info.id for info in self._window_manager.get_window_infos(browser)]
return self._log_list(ids)
@keyword
def get_window_names(self, browser='CURRENT'):
"""Returns and logs names of all windows of the selected browser.
How to select the ``browser`` scope of this keyword, see `Get Locations`."""
names = [info.name for info in self._window_manager.get_window_infos(browser)]
return self._log_list(names)
@keyword
def get_window_titles(self, browser='CURRENT'):
"""Returns and logs titles of all windows of the selected browser.
How to select the ``browser`` scope of this keyword, see `Get Locations`."""
titles = [info.title for info in self._window_manager.get_window_infos(browser)]
return self._log_list(titles)
@keyword
def get_locations(self, browser='CURRENT'):
"""Returns and logs URLs of all windows of the selected browser.
*Browser Scope:*
The ``browser`` argument specifies the browser that shall return
its windows information.
- ``browser`` can be ``index_or_alias`` like in `Switch Browser`.
- If ``browser`` is ``CURRENT`` (default, case-insensitive)
the currently active browser is selected.
- If ``browser`` is ``ALL`` (case-insensitive)
the window information of all windows of all opened browsers are returned."""
urls = [info.url for info in self._window_manager.get_window_infos(browser)]
return self._log_list(urls)
@keyword
def maximize_browser_window(self):
"""Maximizes current browser window."""
self.driver.maximize_window()
@keyword
def get_window_size(self, inner=False):
"""Returns current window width and height as integers.
See also `Set Window Size`.
If ``inner`` parameter is set to True, keyword returns
HTML DOM window.innerWidth and window.innerHeight properties.
See `Boolean arguments` for more details how to set boolean
arguments. The ``inner`` is new in SeleniumLibrary 4.0.
Example:
| ${width} | ${height}= | `Get Window Size` | |
| ${width} | ${height}= | `Get Window Size` | True |
"""
if is_truthy(inner):
inner_width = int(self.driver.execute_script("return window.innerWidth;"))
inner_height = int(self.driver.execute_script("return window.innerHeight;"))
return inner_width, inner_height
size = self.driver.get_window_size()
return size['width'], size['height']
@keyword
def set_window_size(self, width, height, inner=False):
"""Sets current windows size to given ``width`` and ``height``.
Values can be given using strings containing numbers or by using
actual numbers. See also `Get Window Size`.
Browsers have a limit how small they can be set. Trying to set them
smaller will cause the actual size to be bigger than the requested
size.
If ``inner`` parameter is set to True, keyword sets the necessary
window width and height to have the desired HTML DOM window.innerWidth
and window.innerHeight The ``inner`` is new in SeleniumLibrary 4.0.
See `Boolean arguments` for more details how to set boolean
arguments.
This ``inner`` argument does not support Frames. If a frame is selected,
switch to default before running this.
Example:
| `Set Window Size` | 800 | 600 | |
| `Set Window Size` | 800 | 600 | True |
"""
width, height = int(width), int(height)
if is_falsy(inner):
return self.driver.set_window_size(width, height)
self.driver.set_window_size(width, height)
inner_width = int(self.driver.execute_script("return window.innerWidth;"))
inner_height = int(self.driver.execute_script("return window.innerHeight;"))
self.info('window.innerWidth is %s and window.innerHeight is %s' % (inner_width, inner_height))
width_offset = width - inner_width
height_offset = height - inner_height
window_width = width + width_offset
window_height = height + height_offset
self.info('Setting window size to %s %s' % (window_width, window_height))
self.driver.set_window_size(window_width, window_height)
result_width = int(self.driver.execute_script("return window.innerWidth;"))
result_height = int(self.driver.execute_script("return window.innerHeight;"))
if result_width != width or result_height != height:
raise AssertionError("Keyword failed setting correct window size.")
@keyword
def get_window_position(self):
"""Returns current window position.
Position is relative to the top left corner of the screen. Returned
values are integers. See also `Set Window Position`.
Example:
| ${x} | ${y}= | `Get Window Position` |
"""
position = self.driver.get_window_position()
return position['x'], position['y']
@keyword
def set_window_position(self, x, y):
"""Sets window position using ``x`` and ``y`` coordinates.
The position is relative to the top left corner of the screen,
but some browsers exclude possible task bar set by the operating
system from the calculation. The actual position may thus be
different with different browsers.
Values can be given using strings containing numbers or by using
actual numbers. See also `Get Window Position`.
Example:
| `Set Window Position` | 100 | 200 |
"""
self.driver.set_window_position(int(x), int(y))
def _log_list(self, items, what='item'):
msg = [
'Altogether %s %s%s.'
% (len(items), what, plural_or_not(items))
]
for index, item in enumerate(items):
msg.append('%s: %s' % (index + 1, item))
self.info('\n'.join(msg))
return items