In Selenium how exactly are the sendKeys() and setValue() methods different? - selenium

I've used both
WebElement.sendKeys('')
and
WebElement.setValue('')
In order to input text into fields. The vast majority of the time they seem to act the same, but I've found a few cases where setValue() works but sendKeys() does not.
All I can find in the Selenium docs is that sendKeys() 'more accurately imitates user input' then setValue(). Does anyone know what is actually happening under the hood?

sendKeys()
sendKeys() is the Java method from WebElement to simulate typing into an element, which may set its value.
Defination:
void sendKeys(java.lang.CharSequence... keysToSend)
Use this method to simulate typing into an element, which may set its value.
Parameters:
keysToSend - character sequence to send to the element
Throws:
java.lang.IllegalArgumentException - if keysToSend is null
Usage:
driver.findElement(By.id("identifierId")).sendKeys("C.Peck#stackoverflow.com");
However there is no setValue() method in Java and the closest match seems to be setAttribute() JavaScript method.
setAttribute()
setAttribute() is the JavaScript method which sets the value of an attribute on the specified element. If the attribute already exists, the value is updated; otherwise a new attribute is added with the specified name and value.
Syntax:
Element.setAttribute(name, value);
Example:
HTML:
<button>Hello World</button>
JavaScript:
var b = document.querySelector("button");
b.setAttribute("name", "helloButton");
b.setAttribute("disabled", "");
Implementation through Java executeScript():
((JavascriptExecutor)driver).executeScript("document.getElementById('elementID').setAttribute('attribute_name', 'new_value_for_element')");

Related

How to use findElements method with implicit waiting?

In the method document it's written:
When implicitly waiting, this method will return as soon as there are more than 0 items in the found collection, or will return an empty list if the timeout is reached
As i see (please fix me if i'm wrong), when the method find one element it returns it without searching the others.
So what is the advantage of using this method upon using findElement method?
findElements method returns a list of web elements matching the passed locator while findElement method will always return a single web element.
Also in many cases you are applying findElement and findElements methods on already fully loaded page. In this case findElements will return you a list of All the web elements matching the passed locator.
However in order to get all the matching elements in loading page you can't effectively use findElements with implicit wait.
Expected conditions implementing explicit wait should be used instead.
In case you know the exact amount of elements matching the passed locator presented on that page you can use this method:
wait.until(ExpectedConditions.numberOfElementsToBe(element, expectedElementsAmount))
And in case you know that it should be at least some known amount of elements you can use this method:
wait.until(ExpectedConditions.numberOfElementsToBeMoreThan(element, expectedElementsAmount))
Rather individually, you need to read the line in it's entire context.
findElements():
Find all elements within the current page using the given mechanism.
This method is affected by the 'implicit wait' times in force at the
time of execution. When implicitly waiting, this method will return as
soon as there are more than 0 items in the found collection, or will
return an empty list if the timeout is reached.
Here, more than 0 items implies greater then 0 i.e. n > 0 but definitely find all elements within the current page till the timeout is reached.

For the W3C WebDriver "Find Element From Element" command, how does one format the element ID in request URL?

I'm learning how a WebDriver works, and I don't understand how to format the request URL for Find Element From Element.
The element ID of Find Element will return something like this:
{"element-6066-11e4-a52e-4f735466cecf": "e72b0320-5d61-4886-b903-5b2e4bb43d88"}
As I understand it, the above {key: value} format IS the element ID. If that is the case, how does one user that as the {element id} in "POST /session/{session id}/element/{element id}/element"? If {key: value} IS NOT the element ID, what is? And what would a properly formatted request URL look like?
Thanks!
In the above example, the element ID is "e72b0320-5d61-4886-b903-5b2e4bb43d88". It's a bit confusing because rather than creating an object that looks like this:
{"ELEMENT": "e72b0320-5d61-4886-b903-5b2e4bb43d88"}
We have the very odd:
{"element-6066-11e4-a52e-4f735466cecf": "e72b0320-5d61-4886-b903-5b2e4bb43d88"}
What's going on here? It has been deemed from on high that the key which in a JSON object indicates that we are dealing with an element ID is the arbitrary and constant string "element-6066-11e4-a52e-4f735466cecf". The reason is that any non-arbitrary key might end up being a return value of some unrelated JavaScript code. Consider this JavaScript code:
return document.getElementById('foo');
This could be used in ExecuteScript as follows (for example in Python):
driver.execute_script("return document.getElementById('foo');");
What should be returned here? Well we are dealing with an actual HTML element, which can't be converted into JSON and sent back over the wire to the Python client. So instead, WebDriver stores a reference to that element as an ID, and sends that back. But it can't just send back the ID as a string, because there's no way for driver.execute_script to know in advance what sort of thing might be returned. Maybe it's not an element ID--maybe it's some other string related to your application. In the past, the standard format for a JSON WebElement was as I noted above (with the ELEMENT key).
At some point, however, someone must have written some JavaScript code which resulted in a JS object which contained the word ELEMENT as key somewhere inside. This object had nothing to do with WebElements, but when it was returned via a call to driver.execute_script, the client converted it into a WebElement object!
Whether or not this scenario ever actually happened is beside the point; the point is that a simple short word like ELEMENT is ripe for name clashes. The spec authors wanted a way to unambiguously denote that we are dealing with a WebElement even if we encounter it in a serialized JSON format, and in a way that is not likely to clash with other things web developers or testers are doing.
So the most direct answer to your question is, your POST request should look like:
POST /session/{session id}/element/e72b0320-5d61-4886-b903-5b2e4bb43d88/element

getting error method send keys is undefined for the type webelement

My code:
driver.findElements(By.id("email")).sendKeys("");
.sendkeys method is not appearing and getting error
getting error method send keys is undefined for the type webelement
it should be findelement in singular not elements in plural
sendKeys()
As per the documentation sendKeys() method is used to simulate typing into an element, which may set its value.
As per your code trials:
driver.findElements(By.id("email"));
Would return a List and you can't invoke sendKeys() on a List.
Solution
You need to replace findElements() with findElement() which would return an element on which you can invoke sendKeys(). So effectively your line of code will be:
driver.findElement(By.id("email")).sendKeys("");

Passing parameters in #FindBy Page factory

Is there any way so that we can parameterize the string which we pass to create a page object using a page factory?
ex:
String v = "password";
#FindBy(name=v)
private WebElementFacade password_Field;
I am trying to push the string v into the #FindBy but I am getting an error.
I am getting
The value for annotation attribute FindBy.name must be a constant expression.
Yes. It is possible. Please find the solution below:
In your Page, instead of using #FindBy, get the WebElementFacade using find method of the Page and then use it for operations.
For example: If you need to click on an element, please see the code below:
public void click(String elementId) {
WebElementFacade element = find(ById.id(elementId));
element.click();
}
This works perfectly for me. And the element id is coming all the way from .story examples.
No, Unfortunately, it's not possible to send arguments to annotation (reference). Since Java annotations does not allow dynamic parameterization. The compiler evaluates annotation metadata at compile time. So, it must be present. Though there are work around for this.
Check this- Java Annotations values provided in dynamic manner

Protractor Locators, is there a way to find elements using generic search string?

Given:
<span>{{person.name}}</span>
<span ng-bind="person.email"></span>
Question:
Is there anyway I can use a Protractor locator like this:
var eles = element.all(by.binding('person.*'));
Or better yet...
var eles = element.all(by.binding('*'));
I'm wanting to find all elements that are "bound" without knowing the binding string before hand...
A regular CSS selector would do the job. E.g. getting all elements that have a person in binding:
$$("[ng-bind*=person]"); // *= means "contains".
Or, all elements having a binding (having the ng-bind attribute):
$$("[ng-bind]");
Or, $$(".ng-binding") - FYI, this is how Protractor internally locates the elements with a binding.
where $$ is a shortcut for element.all(by.css()).
Note that this would not work if data-ng-bind is used, for example. You may tweak the expression to handle that.