Skip to content

Commit 1e4d418

Browse files
committed
Merge branch 'master' into run-on-failure-flag
2 parents 81a673e + 0636b6d commit 1e4d418

21 files changed

+280
-65
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.project
22
.pydevproject
3+
.idea
34
test/results
45
*.pyc
56
*.orig

BUILD.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ tests with Robot Framework. This includes:
3737
`resources/testserver`
3838
- A collection of simple html files under 'resources/html' directory
3939
- Start-up scripts for executing the tests
40+
- A copy of statuschecker.py for checking logged messages after the
41+
execution, which requires the tests to run with log level DEBUG
4042

4143
To run unit and acceptance tests, run::
4244

CHANGES.rst

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,50 @@
11
Release Notes
22
=============
33

4-
1.6 (unreleased)
5-
----------------
4+
1.6
5+
---
6+
- Added examples to 'Execute Javascript' and 'Execute Async Javascript'
7+
keyword documentation.
8+
[ombre42]
9+
610
- Added instructions to README.rst on how to manually install Selenium2Library.
711
[pekkaklarck]
812

913
- Fixed issue where the browser failed to properly register if 'Open Browser'
1014
did not complete.
1115
[Mika Batsman][elizaleong][emanlove]
1216

17+
- Added support for negative indices for rows and columns in table-related
18+
keywords.
19+
[eweitz]
20+
21+
- Added strategy for locating elements by partial link text with locator
22+
prefix 'partial link'.
23+
[lina1]
24+
25+
- Added new keyword 'Clear Element Text' for clearing the text of text entry
26+
elements.
27+
[emanlove]
28+
29+
- Added new keyword 'Locator Should Match X Times' for validating number of
30+
times a given locator appears.
31+
[emanlove]
32+
33+
- Fixed issue where 'Select Window’ with url strategy fails to locate window
34+
[laulaz]
35+
36+
- Fixed issue where a non-string assigned to window.id caused
37+
'Select Window' and 'Get Window *' keywords to fail.
38+
[ombre42]
39+
40+
- Allow using key attributes (default strategy) when the locator contains
41+
a '=' by using the prefix 'default='. Also make locator prefixes
42+
space-insensitive.
43+
[ombre42]
44+
45+
A big thank you to [eweitz] and [HelioGuilherme66] for getting the
46+
continuous integration builds to go green by fixing internal tests.
47+
1348
1.5
1449
---
1550
- Copy Desired Capabilities before modifying to prevent affecting future

README.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ It is modeled after (and forked from) the SeleniumLibrary_ library,
1919
but re-implemented to use Selenium 2 and WebDriver technologies.
2020

2121
- More information about this library can be found on the Wiki_ and in the `Keyword Documentation`_.
22-
- Installation information is found in the `INSTALL.rst` file.
23-
- Developer information is found in `BUILD.rst` file.
22+
- Installation information is found in the `INSTALL.rst`_ file.
23+
- Developer information is found in `BUILD.rst`_ file.
2424

2525

2626
Installation
@@ -141,5 +141,7 @@ The `user group for Robot Framework`_ is the best place to get help. Consider in
141141
.. _SeleniumLibrary: http://code.google.com/p/robotframework-seleniumlibrary/
142142
.. _Wiki: https://github.com/rtomac/robotframework-selenium2library/wiki
143143
.. _Keyword Documentation: http://rtomac.github.com/robotframework-selenium2library/doc/Selenium2Library.html
144+
.. _INSTALL.rst: https://github.com/rtomac/robotframework-selenium2library/blob/master/INSTALL.rst
145+
.. _BUILD.rst: https://github.com/rtomac/robotframework-selenium2library/blob/master/BUILD.rst
144146
.. _Robot Framework User Guide: http://code.google.com/p/robotframework/wiki/UserGuide
145147
.. _user group for Robot Framework: http://groups.google.com/group/robotframework-users

src/Selenium2Library/__init__.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ class Selenium2Library(
2828
Selenium2Library runs tests in a real browser instance. It should work in
2929
most modern browsers and can be used with both Python and Jython interpreters.
3030
31-
*Before running tests*
31+
= Before running tests =
3232
3333
Prior to running test cases using Selenium2Library, Selenium2Library must be
3434
imported into your Robot test suite (see `importing` section), and the
3535
`Open Browser` keyword must be used to open a browser to the desired location.
3636
37-
*Locating elements*
37+
= Locating elements =
3838
3939
All keywords in Selenium2Library that need to find an element on the page
4040
take an argument, `locator`. By default, when a locator value is provided,
@@ -55,10 +55,19 @@ class Selenium2Library(
5555
| xpath | Click Element `|` xpath=//div[@id='my_element'] | Matches with arbitrary XPath expression |
5656
| dom | Click Element `|` dom=document.images[56] | Matches with arbitrary DOM express |
5757
| link | Click Element `|` link=My Link | Matches anchor elements by their link text |
58+
| partial link | Click Element `|` partial link=y Lin | Matches anchor elements by their partial link text |
5859
| css | Click Element `|` css=div.my_class | Matches by CSS selector |
5960
| jquery | Click Element `|` jquery=div.my_class | Matches by jQuery/sizzle selector |
6061
| sizzle | Click Element `|` sizzle=div.my_class | Matches by jQuery/sizzle selector |
6162
| tag | Click Element `|` tag=div | Matches by HTML tag name |
63+
| default* | Click Link `|` default=page?a=b | Matches key attributes with value after first '=' |
64+
* Explicitly specifying the default strategy is only necessary if locating
65+
elements by matching key attributes is desired and an attribute value
66+
contains a '='. The following would fail because it appears as if _page?a_
67+
is the specified lookup strategy:
68+
| Click Link page?a=b
69+
This can be fixed by changing the locator to:
70+
| Click Link default=page?a=b
6271
6372
Table related keywords, such as `Table Should Contain`, work differently.
6473
By default, when a table locator value is provided, it will search for
@@ -72,12 +81,13 @@ class Selenium2Library(
7281
| css | Table Should Contain `|` css=table.my_class `|` text | Matches by @id or @name attribute |
7382
| xpath | Table Should Contain `|` xpath=//table/[@name="my_table"] `|` text | Matches by @id or @name attribute |
7483
75-
*Timeouts*
84+
= Timeouts =
7685
7786
There are several `Wait ...` keywords that take timeout as an
7887
argument. All of these timeout arguments are optional. The timeout
7988
used by all of them can be set globally using the
80-
`Set Selenium Timeout` keyword.
89+
`Set Selenium Timeout` keyword. The same timeout also applies to
90+
`Execute Async Javascript`.
8191
8292
All timeouts can be given as numbers considered seconds (e.g. 0.5 or 42)
8393
or in Robot Framework's time syntax (e.g. '1.5 seconds' or '1 min 30 s').

src/Selenium2Library/keywords/_browsermanagement.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ def log_source(self, loglevel='INFO'):
341341
"""Logs and returns the entire html source of the current page or frame.
342342
343343
The `loglevel` argument defines the used log level. Valid log levels are
344-
`WARN`, `INFO` (default), `DEBUG`, `TRACE` and `NONE` (no logging).
344+
WARN, INFO (default), DEBUG, and NONE (no logging).
345345
"""
346346
source = self.get_source()
347347
self._log(source, loglevel.upper())
@@ -418,7 +418,7 @@ def set_selenium_timeout(self, seconds):
418418
There are several `Wait ...` keywords that take timeout as an
419419
argument. All of these timeout arguments are optional. The timeout
420420
used by all of them can be set globally using this keyword.
421-
See `introduction` for more information about timeouts.
421+
See `Timeouts` for more information about timeouts.
422422
423423
The previous timeout value is returned by this keyword and can
424424
be used to set the old value back later. The default timeout

src/Selenium2Library/keywords/_element.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ def page_should_contain(self, text, loglevel='INFO'):
7373
7474
If this keyword fails, it automatically logs the page source
7575
using the log level specified with the optional `loglevel` argument.
76-
Giving `NONE` as level disables logging.
76+
Valid log levels are DEBUG, INFO (default), WARN, and NONE. If the
77+
log level is NONE or below the current active log level the source
78+
will not be logged.
7779
"""
7880
if not self._page_contains(text):
7981
self.log_source(loglevel)
@@ -93,6 +95,24 @@ def page_should_contain_element(self, locator, message='', loglevel='INFO'):
9395
"""
9496
self._page_should_contain_element(locator, None, message, loglevel)
9597

98+
def locator_should_match_x_times(self, locator, expected_locator_count, message='', loglevel='INFO'):
99+
"""Verifies that the page contains the given number of elements located by the given `locator`.
100+
101+
See `introduction` for details about locating elements.
102+
103+
See `Page Should Contain Element` for explanation about `message` and
104+
`loglevel` arguments.
105+
"""
106+
actual_locator_count = len(self._element_find(locator, False, False))
107+
if int(actual_locator_count) != int(expected_locator_count):
108+
if not message:
109+
message = "Locator %s should have matched %s times but matched %s times"\
110+
%(locator, expected_locator_count, actual_locator_count)
111+
self.log_source(loglevel)
112+
raise AssertionError(message)
113+
self._info("Current page contains %s elements matching '%s'."
114+
% (actual_locator_count, locator))
115+
96116
def page_should_not_contain(self, text, loglevel='INFO'):
97117
"""Verifies the current page does not contain `text`.
98118
@@ -248,6 +268,14 @@ def get_text(self, locator):
248268
"""
249269
return self._get_text(locator)
250270

271+
def clear_element_text(self, locator):
272+
"""Clears the text value of text entry element identified by `locator`.
273+
274+
See `introduction` for details about locating elements.
275+
"""
276+
element = self._element_find(locator, True, True)
277+
element.clear()
278+
251279
def get_vertical_position(self, locator):
252280
"""Returns vertical position of element identified by `locator`.
253281
@@ -416,11 +444,11 @@ def press_key(self, locator, key):
416444
"""Simulates user pressing key on element identified by `locator`.
417445
418446
`key` is either a single character, or a numerical ASCII code of the key
419-
lead by '\\'.
447+
lead by '\\'. In test data, '\\' must be escaped, so use '\\\\'.
420448
421449
Examples:
422450
| Press Key | text_field | q |
423-
| Press Key | login_button | \\13 | # ASCII code for enter key |
451+
| Press Key | login_button | \\\\13 | # ASCII code for enter key |
424452
"""
425453
if key.startswith('\\') and len(key) > 1:
426454
key = self._map_ascii_key_code_to_key(int(key[1:]))

src/Selenium2Library/keywords/_javascript.py

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -68,24 +68,29 @@ def confirm_action(self):
6868
def execute_javascript(self, *code):
6969
"""Executes the given JavaScript code.
7070
71-
`code` may contain multiple lines of code but must contain a
72-
return statement (with the value to be returned) at the end.
73-
74-
`code` may be divided into multiple cells in the test data. In that
75-
case, the parts are catenated together without adding spaces.
71+
`code` may contain multiple lines of code and may be divided into
72+
multiple cells in the test data. In that case, the parts are
73+
catenated together without adding spaces.
7674
7775
If `code` is an absolute path to an existing file, the JavaScript
7876
to execute will be read from that file. Forward slashes work as
7977
a path separator on all operating systems.
8078
81-
Note that, by default, the code will be executed in the context of the
82-
Selenium object itself, so `this` will refer to the Selenium object.
83-
Use `window` to refer to the window of your application, e.g.
84-
`window.document.getElementById('foo')`.
79+
The JavaScript executes in the context of the currently selected
80+
frame or window as the body of an anonymous function. Use _window_ to
81+
refer to the window of your application and _document_ to refer to the
82+
document object of the current frame or window, e.g.
83+
_document.getElementById('foo')_.
84+
85+
This keyword returns None unless there is a return statement in the
86+
JavaScript. Return values are converted to the appropriate type in
87+
Python, including WebElements.
8588
86-
Example:
87-
| Execute JavaScript | window.my_js_function('arg1', 'arg2') |
88-
| Execute JavaScript | ${CURDIR}/js_to_execute.js |
89+
Examples:
90+
| Execute JavaScript | window.my_js_function('arg1', 'arg2') | |
91+
| Execute JavaScript | ${CURDIR}/js_to_execute.js | |
92+
| ${sum}= | Execute JavaScript | return 1 + 1; |
93+
| Should Be Equal | ${sum} | ${2} |
8994
"""
9095
js = self._get_javascript_to_execute(''.join(code))
9196
self._info("Executing JavaScript:\n%s" % js)
@@ -94,24 +99,22 @@ def execute_javascript(self, *code):
9499
def execute_async_javascript(self, *code):
95100
"""Executes asynchronous JavaScript code.
96101
97-
`code` may contain multiple lines of code but must contain a
98-
return statement (with the value to be returned) at the end.
102+
Similar to `Execute Javascript` except that scripts executed with
103+
this keyword must explicitly signal they are finished by invoking the
104+
provided callback. This callback is always injected into the executed
105+
function as the last argument.
99106
100-
`code` may be divided into multiple cells in the test data. In that
101-
case, the parts are catenated together without adding spaces.
107+
Scripts must complete within the script timeout or this keyword will
108+
fail. See the `Timeouts` section for more information.
102109
103-
If `code` is an absolute path to an existing file, the JavaScript
104-
to execute will be read from that file. Forward slashes work as
105-
a path separator on all operating systems.
106-
107-
Note that, by default, the code will be executed in the context of the
108-
Selenium object itself, so `this` will refer to the Selenium object.
109-
Use `window` to refer to the window of your application, e.g.
110-
`window.document.getElementById('foo')`.
111-
112-
Example:
113-
| Execute Async JavaScript | window.my_js_function('arg1', 'arg2') |
114-
| Execute Async JavaScript | ${CURDIR}/js_to_execute.js |
110+
Examples:
111+
| Execute Async JavaScript | var callback = arguments[arguments.length - 1]; | window.setTimeout(callback, 2000); |
112+
| Execute Async JavaScript | ${CURDIR}/async_js_to_execute.js | |
113+
| ${retval}= | Execute Async JavaScript | |
114+
| ... | var callback = arguments[arguments.length - 1]; | |
115+
| ... | function answer(){callback("text");}; | |
116+
| ... | window.setTimeout(answer, 2000); | |
117+
| Should Be Equal | ${retval} | text |
115118
"""
116119
js = self._get_javascript_to_execute(''.join(code))
117120
self._info("Executing Asynchronous JavaScript:\n%s" % js)

src/Selenium2Library/keywords/_tableelement.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ def get_table_cell(self, table_locator, row, column, loglevel='INFO'):
2020
to get rows counting from the end (end: -1). Cell content from header
2121
or footer rows can be obtained with this keyword. To understand how
2222
tables are identified, please take a look at the `introduction`.
23+
24+
See `Page Should Contain` for explanation about `loglevel` argument.
2325
"""
2426
row = int(row)
2527
row_index = row
@@ -56,6 +58,8 @@ def table_cell_should_contain(self, table_locator, row, column, expected, loglev
5658
5759
To understand how tables are identified, please take a look at
5860
the `introduction`.
61+
62+
See `Page Should Contain` for explanation about `loglevel` argument.
5963
"""
6064
message = ("Cell in table '%s' in row #%s and column #%s "
6165
"should have contained text '%s'."

src/Selenium2Library/keywords/_waiting.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ class _WaitingKeywords(KeywordGroup):
99
def wait_for_condition(self, condition, timeout=None, error=None):
1010
"""Waits until the given `condition` is true or `timeout` expires.
1111
12-
`code` may contain multiple lines of code but must contain a
13-
return statement (with the value to be returned) at the end
14-
1512
The `condition` can be arbitrary JavaScript expression but must contain a
1613
return statement (with the value to be returned) at the end.
1714
See `Execute JavaScript` for information about accessing the

0 commit comments

Comments
 (0)