Passing parameters in #FindBy Page factory - selenium

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

Related

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

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')");

Is it possible to search elements using regular expressions in locators using Tcl Selenium Webdriver interface?

Is it possible to search elements usign regular expressions in locators.
The following works
set login [$window element by_class_name "frost-button"]
But the following doesn't work.
set login [$window element by_class_name "*button"]
No, you can't. When you call something like "by_class_name", the program will try to find element(s) that match the class name exactly that you pass as paramether.
So, if you try to search a class that contains a string, you need to use xpath or cssselector, but without using regex as well.
in Cssselector, the selector is this way:
*[class*='button']
Also, in Xpath is this way:
//*[contains(#class, 'button')]
i think to convert it into a tcl string you need to insert some slashes in the string. As i don't know the tcl, better I don't try.

Check a defined WebElement in a Page Object

My first question here. I hope this question is not already answered. I previously searched if it exists, sorry if I'm wrong.
My question is the next. I have this webelement in a PageObject class for automated tests:
//Customer filter
#FindBy(id = "customer_filter")
private WebElement customerFilter;
Later I try to check if it's present or not, like this:
Boolean test = customerFilter.isDisplayed();
But it doesn't work, it says the webelement is not present when actually is not present, and the test ends. I've also tried with isEnabled() and isSelected(). I have to use instead the next code so everything works:
Boolean isPresent = driver.findElements(By.id("customer_filter")).size() > 0;
if(isPresent){
Is there a way to use webelement directly so I don't have to continuosly use the id locator?
Thanks in advance!!!
Edit: Looking for a little more information, I found this thread about the same problem, but it wasn't resolved: https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/1880
When you use the "#FindBy" annotation, it returns a WebElement Proxy. The WebElementProxy is a wrapper around webelement, and has a "UnderlyingWebElement" property, which is what you're looking for.
https://github.com/barancev/webdriver-samples/blob/master/src/ru/st/selenium/WebElementProxy.java#L141
How you can leverage this, is you can do some creative typecasting to access some of these methods that are not in the IWebElement interface.
if( ((WebElementProxy)customerFilter).getWrappedElement() != null) {
//do something
}
Please refer to this post:post
Also have in mind that when you're checking if .size()>0, this has nothing to do with either visible or presented element. This collection contains all element in the DOM that are matching the criteria.
My advise is to create a method that you call each time with parameter the element that you're looking for.

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.

Understanding the evaluate function in CasperJS

I want to understand in which case I should or have to use the evaluate function.
I have read the API doc about the evaluate function of CasperJS, but I'm unsure in which case I should use this function. And what does DOM context mean? Can somebody provide an example?
The CasperJS documentation has a pretty good description of what casper.evaluate() does.
To recap: You pass a function that will be executed in the DOM context (you can also call it the page context). You can pass some primitives as arguments to this function and return one primitive back. Keep in mind that this function that you pass to evaluate must be self contained. It cannot use variables or functions that are defined outside of this function.
CasperJS provides many good functions for everyday tasks, but you may run into a situation when you need a custom function to do something. evaluate is basically there to do
Retrieve some value from the page to take action based on it in your script
Manipulate the page in some way other than clicking or filling out a form
Combinations of points 1. and 2.
Examples
You may need a generic function to get the checked property from a checkbox. CasperJS currently only provides getElementAttribute function which will not work in this case.
function getChecked(cssSelector){
return document.querySelector(cssSelector).checked;
}
if (casper.evaluate(getChecked, selector)){
// do something
} else {
// do something else
}
In most of the cases it is just preference of what you want to use. If you have a list of users with data-uid on each li element then you have at least 2 possibilities to retrieve the uids.
Casper-only:
var uids = casper.getElementsAttribute('ul#user-list > li', 'data-uid');
Casper-Evaluate:
var uids = casper.evaluate(function(){
return Array.prototype.map.call(document.querySelectorAll('ul#user-list > li'), function(li){ return li["data-uid"]});
});
Regarding manipulation everything is possible but depends on what you want to do. Let's say you want to take screenshots of web pages, but there are some elements that you don't want to be there. Or you could add your own CSS to the document.
Remove elements:
function removeSelector(cssSelector){
var elements = document.querySelectorAll(cssSelector);
Array.prototype.forEach.call(elements, function(el){
el.parent.removeChild(el);
});
}
casper.evaluate(removeSelector, '.ad'); // if it would be that easy :)
Change site appearance through CSS:
function applyCSS(yourCss){
var style = document.createElement("style");
style.innerHTML = yourCss;
document.head.appendChild(style);
}
casper.evaluate(applyCSS, 'body { background-color: black; }'); // non-sense
Roots
CasperJS is built on top of PhantomJS and as such inherits some of its quirks. The PhantomJS documentation for page.evaluate() says this:
Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.
Closures, functions, DOM nodes, etc. will not work!