Skip to content

Commit

Permalink
Initial implementation of get_attribute acting as a shim
Browse files Browse the repository at this point in the history
  • Loading branch information
AutomatedTester committed Aug 9, 2016
1 parent 8f773cf commit 941ddb9
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 19 deletions.
1 change: 1 addition & 0 deletions py/selenium/webdriver/remote/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class Command(object):
GET_ELEMENT_SIZE = "getElementSize"
GET_ELEMENT_RECT = "getElementRect"
GET_ELEMENT_ATTRIBUTE = "getElementAttribute"
GET_ELEMENT_PROPERTY = "getElementProperty"
GET_ELEMENT_VALUE_OF_CSS_PROPERTY = "getElementValueOfCssProperty"
ELEMENT_EQUALS = "elementEquals"
SCREENSHOT = "screenshot"
Expand Down
2 changes: 2 additions & 0 deletions py/selenium/webdriver/remote/remote_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ def __init__(self, remote_server_addr, keep_alive=False, resolve_ip=True):
('GET', '/session/$sessionId/element/$id/rect'),
Command.GET_ELEMENT_ATTRIBUTE:
('GET', '/session/$sessionId/element/$id/attribute/$name'),
Command.GET_ELEMENT_PROPERTY:
('GET', '/session/$sessionId/element/$id/property/$name'),
Command.ELEMENT_EQUALS:
('GET', '/session/$sessionId/element/$id/equals/$other'),
Command.GET_ALL_COOKIES: ('GET', '/session/$sessionId/cookie'),
Expand Down
2 changes: 1 addition & 1 deletion py/selenium/webdriver/remote/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def create_web_element(self, element_id):
"""
Creates a web element with the specified element_id.
"""
return WebElement(self, element_id, w3c=self.w3c)
return WebElement(self, element_id, capabilities=self.capabilities)

def _unwrap_value(self, value):
if isinstance(value, dict) and ('ELEMENT' in value or 'element-6066-11e4-a52e-4f735466cecf' in value):
Expand Down
57 changes: 51 additions & 6 deletions py/selenium/webdriver/remote/webelement.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,16 @@ class WebElement(object):
``StaleElementReferenceException`` is thrown, and all future calls to this
instance will fail."""

def __init__(self, parent, id_, w3c=False):
boolean_attributes = ['default', 'typemustmatch', 'checked', 'defer', 'async', 'muted',
'reversed', 'required', 'controls', 'ismap', 'disabled', 'novalidate',
'readonly', 'allowfullscreen', 'selected', 'formnovalidate',
'multiple', 'autofocus', 'open', 'loop', 'autoplay']

def __init__(self, parent, id_, capabilities):
self._parent = parent
self._id = id_
self._w3c = w3c
self.capabilities = capabilities
self._w3c = "specificationLevel" in self.capabilities

def __repr__(self):
return '<{0.__module__}.{0.__name__} (session="{1}", element="{2}")>'.format(
Expand Down Expand Up @@ -86,6 +92,24 @@ def clear(self):
"""Clears the text if it's a text entry element."""
self._execute(Command.CLEAR_ELEMENT)

def get_property(self, name):
"""
Gets the given property of the element.
:Args:
- name - Name of the property to retrieve.
Example::
# Check if the "active" CSS class is applied to an element.
text_length = target_element.get_property("text_length")
"""
try:
return self._execute(Command.GET_ELEMENT_PROPERTY, {"name": name})["value"]
except WebDriverException:
# if we hit an end point that doesnt understand getElementProperty lets fake it
self.parent.execute_script('return arguments[0][arguments[1]]', self, name)

This comment has been minimized.

Copy link
@lukeis

lukeis Nov 13, 2016

Member

@AutomatedTester missing a 'return' statement here for the fallback


def get_attribute(self, name):
"""Gets the given attribute or property of the element.
Expand All @@ -108,12 +132,33 @@ def get_attribute(self, name):
is_active = "active" in target_element.get_attribute("class")
"""
resp = self._execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name})

attributeValue = ''
if resp['value'] is None:
attributeValue = None
if self._w3c :
if name == 'style':
return self.parent.execute_script("return arguments[0].style.cssText", self)
attributeValue = self.get_property(name)
if (attributeValue in [None, '', False] and name != 'value') or name in self.boolean_attributes:
# We need to check the attribute before we really set it to None
resp = self._execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name})
attributeValue = resp.get('value')

# Even though we have a value, we could be getting the browser default,
# We now need check it's there in the DOM...
resp = self.parent.execute_script("return arguments[0].hasAttribute(arguments[1])",
self, name)
if resp is False:
attributeValue = None
else:
attributeValue = "{0}".format(attributeValue)

if attributeValue is not None:
if name != 'value' and attributeValue.lower() in ('true', 'false'):
attributeValue = attributeValue.lower()

else:
attributeValue = resp['value']
resp = self._execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name})
attributeValue = resp.get('value')
if name != 'value' and attributeValue.lower() in ('true', 'false'):
attributeValue = attributeValue.lower()
return attributeValue
Expand Down
20 changes: 8 additions & 12 deletions py/test/selenium/webdriver/common/element_attribute_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def testShouldReturnNullWhenGettingSrcAttributeOfInvalidImgTag(self):
self._loadSimplePage()
img = self.driver.find_element_by_id("invalidImgTag")
img_attr = img.get_attribute("src")
self.assertTrue(img_attr is None)
self.assertEqual(img_attr, None)

def testShouldReturnAnAbsoluteUrlWhenGettingSrcAttributeOfAValidImgTag(self):
self._loadSimplePage()
Expand Down Expand Up @@ -130,14 +130,14 @@ def testShouldReturnTheValueOfSelectedForRadioButtonsEvenIfTheyLackThatAttribute
initiallyNotSelected = self.driver.find_element_by_id("peas")
initiallySelected = self.driver.find_element_by_id("cheese_and_peas")

self.assertTrue(neverSelected.get_attribute("selected") is None, "false")
self.assertTrue(initiallyNotSelected.get_attribute("selected") is None, "false")
self.assertEqual("true", initiallySelected.get_attribute("selected"), "true")
self.assertTrue(neverSelected.get_attribute("checked") is None, )
self.assertTrue(initiallyNotSelected.get_attribute("checked") is None, )
self.assertEqual("true", initiallySelected.get_attribute("checked"))

initiallyNotSelected.click()
self.assertTrue(neverSelected.get_attribute("selected") is None)
self.assertEqual("true", initiallyNotSelected.get_attribute("selected"))
self.assertTrue(initiallySelected.get_attribute("selected") is None)
self.assertEqual(neverSelected.get_attribute("selected"), None)
self.assertEqual("true", initiallyNotSelected.get_attribute("checked"))
self.assertEqual(initiallySelected.get_attribute("checked"), None)

def testShouldReturnTheValueOfSelectedForOptionsInSelectsEvenIfTheyLackThatAttribute(self):
self._loadPage("formPage")
Expand All @@ -148,7 +148,7 @@ def testShouldReturnTheValueOfSelectedForOptionsInSelectsEvenIfTheyLackThatAttri
self.assertTrue(one.is_selected())
self.assertFalse(two.is_selected())
self.assertEqual("true", one.get_attribute("selected"))
self.assertTrue(two.get_attribute("selected") is None)
self.assertEqual(two.get_attribute("selected"), None)

def testShouldReturnValueOfClassAttributeOfAnElement(self):
self._loadPage("xhtmlTest")
Expand Down Expand Up @@ -235,8 +235,6 @@ def testShouldReturnNullForNonPresentBooleanAttributes(self):
self._loadPage("booleanAttributes")
element1 = self.driver.find_element_by_id("working")
self.assertEqual(None, element1.get_attribute("required"))
element2 = self.driver.find_element_by_id("wallace")
self.assertEqual(None, element2.get_attribute("nowrap"))

@pytest.mark.ignore_ie
def testShouldReturnTrueForPresentBooleanAttributes(self):
Expand All @@ -249,8 +247,6 @@ def testShouldReturnTrueForPresentBooleanAttributes(self):
self.assertEqual("true", element3.get_attribute("required"))
element4 = self.driver.find_element_by_id("textAreaRequired")
self.assertEqual("true", element4.get_attribute("required"))
element5 = self.driver.find_element_by_id("unwrappable")
self.assertEqual("true", element5.get_attribute("nowrap"))

def tesShouldGetUnicodeCharsFromAttribute(self):
self._loadPage("formPage")
Expand Down

0 comments on commit 941ddb9

Please sign in to comment.