Skip to content

Commit 8b79835

Browse files
committed
[java] Implementing a new operation to get element property, see https://www.w3.org/TR/webdriver/#get-element-property
1 parent 35fc551 commit 8b79835

File tree

6 files changed

+279
-1
lines changed

6 files changed

+279
-1
lines changed

java/client/src/org/openqa/selenium/WebElement.java

+39
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,45 @@ public interface WebElement extends SearchContext, TakesScreenshot {
9393
*/
9494
String getTagName();
9595

96+
/**
97+
* Get the value of the given property of the element. Will return the current value, even if
98+
* this has been modified after the page has been loaded.
99+
* <p>
100+
* See <a href="https://w3c.github.io/webdriver/#get-element-property">W3C WebDriver specification</a>
101+
* for more details.
102+
*
103+
* @param name The name of the property.
104+
* @return The property's current value or null if the value is not set.
105+
*/
106+
default String getDomProperty(String name) {
107+
throw new UnsupportedOperationException();
108+
}
109+
110+
/**
111+
* Get the value of the given attribute of the element. Will return the current value, even if
112+
* this has been modified after the page has been loaded.
113+
* <p>
114+
* This method, unlike {@link #getAttribute(String)}, returns the value of the attribute with the
115+
* given name but not the property with the same name.
116+
* <p>
117+
* The following are deemed to be "boolean" attributes, and will return either "true" or null:
118+
* <p>
119+
* async, autofocus, autoplay, checked, compact, complete, controls, declare, defaultchecked,
120+
* defaultselected, defer, disabled, draggable, ended, formnovalidate, hidden, indeterminate,
121+
* iscontenteditable, ismap, itemscope, loop, multiple, muted, nohref, noresize, noshade,
122+
* novalidate, nowrap, open, paused, pubdate, readonly, required, reversed, scoped, seamless,
123+
* seeking, selected, truespeed, willvalidate
124+
* <p>
125+
* See <a href="https://w3c.github.io/webdriver/#get-element-attribute">W3C WebDriver specification</a>
126+
* for more details.
127+
*
128+
* @param name The name of the attribute.
129+
* @return The attribute's current value or null if the value is not set.
130+
*/
131+
default String getDomAttribute(String name) {
132+
throw new UnsupportedOperationException();
133+
}
134+
96135
/**
97136
* Get the value of the given attribute of the element. Will return the current value, even if
98137
* this has been modified after the page has been loaded.

java/client/src/org/openqa/selenium/remote/DriverCommand.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,14 @@ static CommandPayload GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW(String id) {
184184
static CommandPayload GET_ELEMENT_SIZE(String id) {
185185
return new CommandPayload(GET_ELEMENT_SIZE, ImmutableMap.of("id", id));
186186
}
187+
String GET_ELEMENT_PROPERTY = "getElementProperty";
188+
static CommandPayload GET_ELEMENT_PROPERTY(String id, String name) {
189+
return new CommandPayload(GET_ELEMENT_PROPERTY, ImmutableMap.of("id", id, "name", name));
190+
}
187191
String GET_ELEMENT_ATTRIBUTE = "getElementAttribute";
188192
static CommandPayload GET_ELEMENT_ATTRIBUTE(String id, String name) {
189193
return new CommandPayload(GET_ELEMENT_ATTRIBUTE, ImmutableMap.of("id", id, "name", name));
190194
}
191-
String GET_ELEMENT_PROPERTY = "getElementProperty";
192195
String GET_ELEMENT_VALUE_OF_CSS_PROPERTY = "getElementValueOfCssProperty";
193196
static CommandPayload GET_ELEMENT_VALUE_OF_CSS_PROPERTY(String id, String name) {
194197
return new CommandPayload(GET_ELEMENT_VALUE_OF_CSS_PROPERTY, ImmutableMap.of("id", id, "propertyName", name));

java/client/src/org/openqa/selenium/remote/RemoteWebElement.java

+7
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@ public String getTagName() {
134134
.getValue();
135135
}
136136

137+
@Override
138+
public String getDomProperty(String name) {
139+
return stringValueOf(
140+
execute(DriverCommand.GET_ELEMENT_PROPERTY(id, name))
141+
.getValue());
142+
}
143+
137144
@Override
138145
public String getAttribute(String name) {
139146
return stringValueOf(

java/client/src/org/openqa/selenium/remote/codec/w3c/W3CHttpCommandCodec.java

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_ATTRIBUTE;
4141
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_LOCATION;
4242
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW;
43+
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_PROPERTY;
4344
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_RECT;
4445
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_SIZE;
4546
import static org.openqa.selenium.remote.DriverCommand.GET_LOCAL_STORAGE_ITEM;
@@ -157,6 +158,9 @@ public W3CHttpCommandCodec() {
157158
defineCommand(ACTIONS, post(sessionId + "/actions"));
158159
defineCommand(CLEAR_ACTIONS_STATE, delete(sessionId + "/actions"));
159160

161+
String elementId = sessionId + "/element/:id";
162+
defineCommand(GET_ELEMENT_PROPERTY, get(elementId + "/property/:name"));
163+
160164
// Emulate the old Actions API since everyone still likes to call these things.
161165
alias(CLICK, ACTIONS);
162166
alias(DOUBLE_CLICK, ACTIONS);

java/client/src/org/openqa/selenium/support/ui/ExpectedConditions.java

+28
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,34 @@ public String toString() {
10351035
};
10361036
}
10371037

1038+
/**
1039+
* An expectation for checking given WebElement has property with a specific value
1040+
*
1041+
* @param element used to check its parameters
1042+
* @param property property name
1043+
* @param value used as expected property value
1044+
* @return Boolean true when element has property with the value
1045+
*/
1046+
public static ExpectedCondition<Boolean> domPropertyToBe(final WebElement element,
1047+
final String property,
1048+
final String value) {
1049+
return new ExpectedCondition<Boolean>() {
1050+
private String currentValue = null;
1051+
1052+
@Override
1053+
public Boolean apply(WebDriver driver) {
1054+
currentValue = element.getDomProperty(property);
1055+
return value.equals(currentValue);
1056+
}
1057+
1058+
@Override
1059+
public String toString() {
1060+
return String.format(property + " to be \"%s\". Current " + property + ": \"%s\"", value,
1061+
currentValue);
1062+
}
1063+
};
1064+
}
1065+
10381066
/**
10391067
* An expectation for checking given WebElement has attribute with a specific value
10401068
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium;
19+
20+
import static org.assertj.core.api.Assertions.assertThat;
21+
import static org.openqa.selenium.testing.drivers.Browser.CHROME;
22+
import static org.openqa.selenium.testing.drivers.Browser.CHROMIUMEDGE;
23+
import static org.openqa.selenium.testing.drivers.Browser.MARIONETTE;
24+
25+
import org.junit.Test;
26+
import org.openqa.selenium.support.ui.ExpectedConditions;
27+
import org.openqa.selenium.testing.JUnit4TestBase;
28+
import org.openqa.selenium.testing.NotYetImplemented;
29+
30+
import java.util.List;
31+
32+
public class ElementPropertyTest extends JUnit4TestBase {
33+
34+
@Test
35+
public void testShouldReturnNullWhenGettingTheValueOfAPropertyThatDoesNotExist() {
36+
driver.get(pages.simpleTestPage);
37+
WebElement head = driver.findElement(By.xpath("/html"));
38+
assertThat(head.getDomProperty("cheese")).isNull();
39+
}
40+
41+
@Test
42+
public void testShouldReturnAnAbsoluteUrlWhenGettingSrcAttributeOfAValidImgTag() {
43+
driver.get(pages.simpleTestPage);
44+
WebElement img = driver.findElement(By.id("validImgTag"));
45+
assertThat(img.getDomProperty("src")).isEqualTo(appServer.whereIs("icon.gif"));
46+
}
47+
48+
@Test
49+
public void testShouldReturnAnAbsoluteUrlWhenGettingHrefAttributeOfAValidAnchorTag() {
50+
driver.get(pages.simpleTestPage);
51+
WebElement img = driver.findElement(By.id("validAnchorTag"));
52+
assertThat(img.getDomProperty("href")).isEqualTo(appServer.whereIs("icon.gif"));
53+
}
54+
55+
@Test
56+
public void testShouldReturnTheValueOfTheIndexAttributeEvenIfItIsMissing() {
57+
driver.get(pages.formPage);
58+
WebElement multiSelect = driver.findElement(By.id("multi"));
59+
List<WebElement> options = multiSelect.findElements(By.tagName("option"));
60+
assertThat(options.get(1).getDomProperty("index")).isEqualTo("1");
61+
}
62+
63+
@Test
64+
public void testShouldReturnTheValueOfCheckedForACheckboxOnlyIfItIsChecked() {
65+
driver.get(pages.formPage);
66+
WebElement checkbox = driver.findElement(By.xpath("//input[@id='checky']"));
67+
assertThat(checkbox.getDomProperty("checked")).isEqualTo("false");
68+
checkbox.click();
69+
assertThat(checkbox.getDomProperty("checked")).isEqualTo("true");
70+
}
71+
72+
@Test
73+
public void testShouldReturnTheValueOfSelectedForOptionsOnlyIfTheyAreSelected() {
74+
driver.get(pages.formPage);
75+
WebElement selectBox = driver.findElement(By.xpath("//select[@name='selectomatic']"));
76+
List<WebElement> options = selectBox.findElements(By.tagName("option"));
77+
WebElement one = options.get(0);
78+
WebElement two = options.get(1);
79+
assertThat(one.isSelected()).isTrue();
80+
assertThat(two.isSelected()).isFalse();
81+
assertThat(one.getDomProperty("selected")).isEqualTo("true");
82+
assertThat(two.getDomProperty("selected")).isEqualTo("false");
83+
assertThat(selectBox.getDomProperty("selectedIndex")).isEqualTo("0");
84+
}
85+
86+
@Test
87+
@NotYetImplemented(CHROME)
88+
@NotYetImplemented(CHROMIUMEDGE)
89+
public void testShouldGetClassPropertiesOfAnElement() {
90+
driver.get(pages.xhtmlTestPage);
91+
WebElement heading = driver.findElement(By.cssSelector(".nameA"));
92+
assertThat(heading.getDomProperty("class")).isNull();
93+
assertThat(heading.getDomProperty("className")).isEqualTo("nameA nameBnoise nameC");
94+
assertThat(heading.getDomProperty("classList")).isEqualTo("nameA nameBnoise nameC");
95+
}
96+
97+
@Test
98+
public void testShouldReturnTheContentsOfATextAreaAsItsValue() {
99+
driver.get(pages.formPage);
100+
WebElement withText = driver.findElement(By.id("withText"));
101+
assertThat(withText.getDomProperty("value")).isEqualTo("Example text");
102+
}
103+
104+
@Test
105+
public void testShouldReturnInnerHtml() {
106+
driver.get(pages.simpleTestPage);
107+
WebElement wrapping = driver.findElement(By.id("wrappingtext"));
108+
assertThat(wrapping.getDomProperty("innerHTML")).contains("<tbody>");
109+
}
110+
111+
@Test
112+
public void testShouldReturnHiddenTextForTextContentProperty() {
113+
driver.get(pages.simpleTestPage);
114+
WebElement element = driver.findElement(By.id("hiddenline"));
115+
assertThat(element.getDomProperty("textContent")).isEqualTo("A hidden line of text");
116+
}
117+
118+
@Test
119+
public void testShouldGetNumericProperty() {
120+
driver.get(pages.formPage);
121+
WebElement element = driver.findElement(By.id("withText"));
122+
assertThat(element.getDomProperty("rows")).isEqualTo("5");
123+
}
124+
125+
@Test
126+
@NotYetImplemented(MARIONETTE)
127+
public void testCanReturnATextApproximationOfTheStyleProperty() {
128+
driver.get(pages.javascriptPage);
129+
WebElement element = driver.findElement(By.id("red-item"));
130+
assertThat(element.getDomProperty("style").toLowerCase()).contains("background-color");
131+
}
132+
133+
@Test
134+
public void testPropertyNamesAreCaseSensitive() {
135+
driver.get(pages.tables);
136+
WebElement th1 = driver.findElement(By.id("th1"));
137+
assertThat(th1.getDomProperty("colspan")).isNull();
138+
assertThat(th1.getDomProperty("COLSPAN")).isNull();
139+
assertThat(th1.getDomProperty("colSpan")).isEqualTo("3");
140+
}
141+
142+
@Test
143+
public void testCanRetrieveTheCurrentValueOfATextFormField_textInput() {
144+
driver.get(pages.formPage);
145+
WebElement element = driver.findElement(By.id("working"));
146+
assertThat(element.getDomProperty("value")).isEqualTo("");
147+
element.sendKeys("hello world");
148+
shortWait.until(ExpectedConditions.domPropertyToBe(element, "value", "hello world"));
149+
}
150+
151+
@Test
152+
public void testCanRetrieveTheCurrentValueOfATextFormField_emailInput() {
153+
driver.get(pages.formPage);
154+
WebElement element = driver.findElement(By.id("email"));
155+
assertThat(element.getDomProperty("value")).isEqualTo("");
156+
element.sendKeys("[email protected]");
157+
shortWait.until(ExpectedConditions.domPropertyToBe(element, "value", "[email protected]"));
158+
}
159+
160+
@Test
161+
public void testCanRetrieveTheCurrentValueOfATextFormField_textArea() {
162+
driver.get(pages.formPage);
163+
WebElement element = driver.findElement(By.id("emptyTextArea"));
164+
assertThat(element.getDomProperty("value")).isEqualTo("");
165+
element.sendKeys("hello world");
166+
shortWait.until(ExpectedConditions.domPropertyToBe(element, "value", "hello world"));
167+
}
168+
169+
@Test
170+
public void testMultiplePropertyShouldBeTrueWhenSelectHasMultipleWithValueAsBlank() {
171+
driver.get(pages.selectPage);
172+
WebElement element = driver.findElement(By.id("selectWithEmptyStringMultiple"));
173+
assertThat(element.getDomProperty("multiple")).isEqualTo("true");
174+
}
175+
176+
@Test
177+
public void testMultiplePropertyShouldBeTrueWhenSelectHasMultipleWithoutAValue() {
178+
driver.get(pages.selectPage);
179+
WebElement element = driver.findElement(By.id("selectWithMultipleWithoutValue"));
180+
assertThat(element.getDomProperty("multiple")).isEqualTo("true");
181+
}
182+
183+
@Test
184+
public void testMultiplePropertyShouldBeTrueWhenSelectHasMultipleWithValueAsSomethingElse() {
185+
driver.get(pages.selectPage);
186+
WebElement element = driver.findElement(By.id("selectWithRandomMultipleValue"));
187+
assertThat(element.getDomProperty("multiple")).isEqualTo("true");
188+
}
189+
190+
@Test
191+
@NotYetImplemented(MARIONETTE)
192+
public void testGetValueOfUserDefinedProperty() {
193+
driver.get(pages.userDefinedProperty);
194+
WebElement element = driver.findElement(By.id("d"));
195+
assertThat(element.getDomProperty("dynamicProperty")).isEqualTo("sampleValue");
196+
}
197+
}

0 commit comments

Comments
 (0)