Skip to content

Commit fbaf569

Browse files
committed
Merge branch 'spaces-in-locator-prefixes' of https://github.com/ombre42/robotframework-selenium2library into ombre42-spaces-in-locator-prefixes
Conflicts: CHANGES.rst
2 parents 990209e + a7f1d0d commit fbaf569

File tree

5 files changed

+49
-9
lines changed

5 files changed

+49
-9
lines changed

CHANGES.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ Release Notes
2323

2424
- Fixed issue where a non-string assigned to window.id caused
2525
'Select Window' and 'Get Window *' keywords to fail.
26+
[ombre42]
27+
28+
- Allow using key attributes (default strategy) when the locator contains
29+
a '=' by using the prefix 'default='. Also make locator prefixes
30+
space-insensitive.
31+
[ombre42]
2632

2733
A big thank you to [eweitz] and [HelioGuilherme66] for getting the
2834
continuous integration builds to go green by fixing internal tests.

src/Selenium2Library/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ class Selenium2Library(
6060
| jquery | Click Element `|` jquery=div.my_class | Matches by jQuery/sizzle selector |
6161
| sizzle | Click Element `|` sizzle=div.my_class | Matches by jQuery/sizzle selector |
6262
| 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
6371
6472
Table related keywords, such as `Table Should Contain`, work differently.
6573
By default, when a table locator value is provided, it will search for

src/Selenium2Library/keywords/_element.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,11 +436,11 @@ def press_key(self, locator, key):
436436
"""Simulates user pressing key on element identified by `locator`.
437437
438438
`key` is either a single character, or a numerical ASCII code of the key
439-
lead by '\\'.
439+
lead by '\\'. In test data, '\\' must be escaped, so use '\\\\'.
440440
441441
Examples:
442442
| Press Key | text_field | q |
443-
| Press Key | login_button | \\13 | # ASCII code for enter key |
443+
| Press Key | login_button | \\\\13 | # ASCII code for enter key |
444444
"""
445445
if key.startswith('\\') and len(key) > 1:
446446
key = self._map_ascii_key_code_to_key(int(key[1:]))

src/Selenium2Library/locators/elementfinder.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
from Selenium2Library import utils
22
from robot.api import logger
3+
from robot.utils import NormalizedDict
4+
35

46
class ElementFinder(object):
57

68
def __init__(self):
7-
self._strategies = {
9+
strategies = {
810
'identifier': self._find_by_identifier,
911
'id': self._find_by_id,
1012
'name': self._find_by_name,
@@ -16,14 +18,16 @@ def __init__(self):
1618
'jquery': self._find_by_sizzle_selector,
1719
'sizzle': self._find_by_sizzle_selector,
1820
'tag': self._find_by_tag_name,
19-
None: self._find_by_default
21+
'default': self._find_by_default
2022
}
23+
self._strategies = NormalizedDict(initial=strategies, caseless=True, spaceless=True)
2124

2225
def find(self, browser, locator, tag=None):
2326
assert browser is not None
2427
assert locator is not None and len(locator) > 0
2528

2629
(prefix, criteria) = self._parse_locator(locator)
30+
prefix = 'default' if prefix is None else prefix
2731
strategy = self._strategies.get(prefix)
2832
if strategy is None:
2933
raise ValueError("Element locator with prefix '" + prefix + "' is not supported")
@@ -187,7 +191,7 @@ def _parse_locator(self, locator):
187191
if not locator.startswith('//'):
188192
locator_parts = locator.partition('=')
189193
if len(locator_parts[1]) > 0:
190-
prefix = locator_parts[0].strip().lower()
194+
prefix = locator_parts[0]
191195
criteria = locator_parts[2].strip()
192196
return (prefix, criteria)
193197

test/unit/locators/test_elementfinder.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22
import os
33
from Selenium2Library.locators import ElementFinder
44
from mockito import *
5+
from robot.utils.asserts import assert_raises_with_msg
56

67
class ElementFinderTests(unittest.TestCase):
78

89
def test_find_with_invalid_prefix(self):
910
finder = ElementFinder()
1011
browser = mock()
11-
try:
12-
self.assertRaises(ValueError, finder.find, browser, "something=test1")
13-
except ValueError as e:
14-
self.assertEqual(e.message, "Element locator with prefix 'something' is not supported")
12+
assert_raises_with_msg(ValueError, "Element locator with prefix 'something' is not supported",
13+
finder.find, browser, "something=test1")
14+
assert_raises_with_msg(ValueError, "Element locator with prefix ' by ID ' is not supported",
15+
finder.find, browser, " by ID =test1")
1516

1617
def test_find_with_null_browser(self):
1718
finder = ElementFinder()
@@ -36,6 +37,22 @@ def test_find_with_no_tag(self):
3637
finder.find(browser, "test1")
3738
verify(browser).find_elements_by_xpath("//*[(@id='test1' or @name='test1')]")
3839

40+
def test_find_with_explicit_default_strategy(self):
41+
finder = ElementFinder()
42+
browser = mock()
43+
finder.find(browser, "default=test1")
44+
verify(browser).find_elements_by_xpath("//*[(@id='test1' or @name='test1')]")
45+
46+
def test_find_with_explicit_default_strategy_and_equals(self):
47+
finder = ElementFinder()
48+
browser = mock()
49+
when(browser).get_current_url().thenReturn("http://localhost/mypage.html")
50+
finder.find(browser, "default=page.do?foo=bar", tag='a')
51+
verify(browser).find_elements_by_xpath(
52+
"//a[(@id='page.do?foo=bar' or @name='page.do?foo=bar' or @href='page.do?foo=bar' or " +
53+
"normalize-space(descendant-or-self::text())='page.do?foo=bar' or " +
54+
"@href='http://localhost/page.do?foo=bar')]")
55+
3956
def test_find_with_tag(self):
4057
finder = ElementFinder()
4158
browser = mock()
@@ -285,6 +302,7 @@ def test_find_with_sloppy_prefix(self):
285302

286303
elements = self._make_mock_elements('div', 'a', 'span', 'a')
287304
when(browser).find_elements_by_id("test1").thenReturn(elements)
305+
when(browser).find_elements_by_partial_link_text("test1").thenReturn(elements)
288306

289307
result = finder.find(browser, "ID=test1")
290308
self.assertEqual(result, elements)
@@ -294,6 +312,10 @@ def test_find_with_sloppy_prefix(self):
294312
self.assertEqual(result, elements)
295313
result = finder.find(browser, " id =test1")
296314
self.assertEqual(result, elements)
315+
result = finder.find(browser, " partiallink =test1")
316+
self.assertEqual(result, elements)
317+
result = finder.find(browser, " p art iallin k =test1")
318+
self.assertEqual(result, elements)
297319

298320
def test_find_with_sloppy_criteria(self):
299321
finder = ElementFinder()

0 commit comments

Comments
 (0)