Skip to content

Commit

Permalink
Merge pull request #1850 from emanlove/new-attribute-property-keyword…
Browse files Browse the repository at this point in the history
…s-1822

New attribute property keywords 1822
  • Loading branch information
emanlove authored Dec 19, 2023
2 parents fe01706 + 085fc64 commit 4ba475b
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 1 deletion.
87 changes: 87 additions & 0 deletions atest/acceptance/keywords/elements.robot
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Documentation Tests elements
Test Setup Go To Page "links.html"
Resource ../resource.robot
Library String
Library DebugLibrary

*** Test Cases ***
Get Many Elements
Expand Down Expand Up @@ -60,6 +61,92 @@ Get Element Attribute
${class}= Get Element Attribute ${second_div} class
Should Be Equal ${class} Second Class

# About DOM Attributes and Properties
# -----------------------------------
# When implementing the new `Get DOM Attirbute` and `Get Property` keywords (#1822), several
# questions were raised. Fundamentally what is the difference between a DOM attribute and
# a Property. As [1] explains "Attributes are defined by HTML. Properties are defined by the
# DOM (Document Object Model)."
#
# Below are some references which talk to some descriptions and oddities of DOM attributes
# and properties.
#
# References:
# [1] HTML attributes and DOM properties:
# https://angular.io/guide/binding-syntax#html-attribute-vs-dom-property
# [2] W3C HTML Specification - Section 13.1.2.3 Attributes:
# https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
# [3] JavaScript.Info - Attributes and properties:
# https://javascript.info/dom-attributes-and-properties
# [4] "Which CSS properties are inherited?" - StackOverflow
# https://stackoverflow.com/questions/5612302/which-css-properties-are-inherited
# [5] MDN Web Docs: Attribute
# https://developer.mozilla.org/en-US/docs/Glossary/Attribute
# [6] MDN Web Docs: HTML attribute reference
# https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes

Get DOM Attribute
# Test get DOM attribute
${id}= Get DOM Attribute link:Link with id id
Should Be Equal ${id} some_id
# Test custom attribute
${existing_custom_attr}= Get DOM Attribute id:emptyDiv data-id
Should Be Equal ${existing_custom_attr} my_id
${doesnotexist_custom_attr}= Get DOM Attribute id:emptyDiv data-doesnotexist
Should Be Equal ${doesnotexist_custom_attr} ${None}
# Get non existing DOM Attribute
${class}= Get DOM Attribute link:Link with id class
Should Be Equal ${class} ${NONE}

More DOM Attributes
[Setup] Go To Page "forms/enabled_disabled_fields_form.html"
# Test get empty boolean attribute
${disabled}= Get DOM Attribute css:input[name="disabled_input"] disabled
Should Be Equal ${disabled} true
# Test boolean attribute whose value is a string
${disabled}= Get DOM Attribute css:input[name="disabled_password"] disabled
Should Be Equal ${disabled} true
# Test empty string as the value for the attribute
${empty_value}= Get DOM Attribute css:input[name="disabled_password"] value
Should Be Equal ${empty_value} ${EMPTY}
# Test non-existing attribute
${disabled}= Get DOM Attribute css:input[name="enabled_password"] disabled
Should Be Equal ${disabled} ${NONE}

Get Property
[Setup] Go To Page "forms/enabled_disabled_fields_form.html"
${tagName_prop}= Get Property css:input[name="readonly_empty"] tagName
Should Be Equal ${tagName_prop} INPUT
# Get a boolean property
${isConnected}= Get Property css:input[name="readonly_empty"] isConnected
Should Be Equal ${isConnected} ${True}
# Test property which returns webelement
${children_prop}= Get Property id:table1 children
Length Should Be ${children_prop} ${1}
${isWebElement}= Evaluate isinstance($children_prop[0], selenium.webdriver.remote.webelement.WebElement) modules=selenium
Should Be Equal ${isWebElement} ${True}
# ToDo: need to test own versus inherited property
# ToDo: Test enumerated property

Get "Attribute" That Is Both An DOM Attribute and Property
[Setup] Go To Page "forms/enabled_disabled_fields_form.html"
${value_property}= Get Property css:input[name="readonly_empty"] value
${value_attribute}= Get DOM Attribute css:input[name="readonly_empty"] value
Should Be Equal ${value_property} ${value_attribute}

Modify "Attribute" That Is Both An DOM Attribute and Property
[Setup] Go To Page "forms/prefilled_email_form.html"
${initial_value_property}= Get Property css:input[name="email"] value
${initial_value_attribute}= Get DOM Attribute css:input[name="email"] value
Should Be Equal ${initial_value_property} ${initial_value_attribute}
Should Be Equal ${initial_value_attribute} Prefilled Email
Input Text css:input[name="email"] [email protected]
${changed_value_property}= Get Property css:input[name="email"] value
${changed_value_attribute}= Get DOM Attribute css:input[name="email"] value
Should Not Be Equal ${changed_value_property} ${changed_value_attribute}
Should Be Equal ${changed_value_attribute} Prefilled Email
Should Be Equal ${changed_value_property} [email protected]

Get Element Attribute Value Should Be Should Be Succesfull
Element Attribute Value Should Be link=Absolute external link href http://www.google.com/
Element Attribute Value Should Be link=Absolute external link nothere ${None}
Expand Down
32 changes: 32 additions & 0 deletions src/SeleniumLibrary/keywords/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,38 @@ def get_element_attribute(
"""
return self.find_element(locator).get_attribute(attribute)

@keyword
def get_dom_attribute(
self, locator: Union[WebElement, str], attribute: str
) -> str:
"""Returns the value of ``attribute`` from the element ``locator``. `Get DOM Attribute` keyword
only returns attributes declared within the element's HTML markup. If the requested attribute
is not there, the keyword returns ${None}.
See the `Locating elements` section for details about the locator
syntax.
Example:
| ${id}= | `Get DOM Attribute` | css:h1 | id |
"""
return self.find_element(locator).get_dom_attribute(attribute)

@keyword
def get_property(
self, locator: Union[WebElement, str], property: str
) -> str:
"""Returns the value of ``property`` from the element ``locator``.
See the `Locating elements` section for details about the locator
syntax.
Example:
| ${text_length}= | `Get Property` | css:h1 | text_length |
"""
return self.find_element(locator).get_property(property)

@keyword
def element_attribute_value_should_be(
self,
Expand Down
2 changes: 1 addition & 1 deletion utest/test/api/test_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def setUpClass(cls):
def test_no_libraries(self):
for item in [None, "None", ""]:
sl = SeleniumLibrary(plugins=item)
self.assertEqual(len(sl.get_keyword_names()), 178)
self.assertEqual(len(sl.get_keyword_names()), 180)

def test_parse_library(self):
plugin = "path.to.MyLibrary"
Expand Down

0 comments on commit 4ba475b

Please sign in to comment.