What is By in Selenium - selenium

driver.findElement(By.id(//[#id='kishr']));
What is By above?
Is this class ,reference or object ?

By is an abstract class
and
id is a static method, so is linkText, partialLinkText, name, tagName, xpath, className, cssSelector in By abstract class.
Since it's a class level methods, you don't really need an object to call these methods.
By.id or By.xpath etc. should suffice.
Official docs

By is an abstract class its provides a way to various search criteria's to locate the locator, it provides 8 method for 8 locator stategies,All 8 method are static so call them we have to use class name,

Related

How to execute specific method implicitly before interacting with element in Selenium?

The application I'm automating is using jQuery and ajax calls. Hence before interacting with elements, I wait for document to be ready and all ajax calls to complete. Only then I interact with element like sendKeys(), click() etc
For this, I need to add that method (say waitForDocumentReadyAndAjaxTocomplete()) explicitly everywhere wherever element is being interacted.
Is there anyway I can call that method waitForDocumentReadyAndAjaxTocomplete() implicitly before interacting with an element?
Yes, there is a way. You can create an utility class which creates your identifier using the locator you want to use and in the method where you create the identifier you can call the waitForDocumentReadyAndAjaxTocomplete method.
Basically the utility class will handle the call and you can actually have a try catch or a polling mechanism to optimize the call to the method as suits your requirement.
This way you donot have to call the waitForDocumentReadyAndAjaxTocomplete method everytime. It will be called in your utility class.
You can use the power of PageFactory.initElements(..) where you can:
Design your bindings in Page Object pattern
Intitialize elements of your page classes using your custom ElementLocatorFactory / ElementLocator. Where you can can add waiting of your dom events before finding elements.
You can check how AjaxElementLocatorFactory is implemented. There should not be issues with following this approach sine all key methods are public so can be simply overriden.
However I guess you will have to supply #CacheLookup annotation to all your fields annotated with #FindBy

How driver.navigate().to() work on selenium in Selenium class? Means what is navigate() and to()?

I am confused with this. Basically when we create an object of a class, then we can access property or method. Up to I am fine. But what when we are creating an object of WebDriver class in Selenium and setting URL through driver.navigate().to(). So Why are here two things navigate() and to() after the Selenium object driver.
Navigate is an interface to navigate through the browser:
Navigate is a way of interacting with the browser.
The method .to() is a function of the interface to get a URL.
The shorter way to do driver.navigate().to() is driver.get()
With navigate you have more methods like: driver.navigate().forward();
and driver.navigate().back();
Hope this helps you!
PS:
As #muraliselenium has commented if your question is about "method chaining" you can read more about it here

In the Page Object Model, why do we use Webelements instead of Strings as class variables?

Simply put: when implementing the POM framework we have Pagefactory initialize all the elements in a pageobject. Why do we do this instead of storing the xpath/css selectors as strings and calling those as needed instead?
ex:
#FindBy(xpath = "//Button[text()='Add and Edit']")
#CacheLookup
private WebElement addAndEdit;
vs
private String addAndEdit;
This is not defined as part of the page object model, this is defined by PageFactory which is a helper class in initializing elements in a page object. The intent there is to set up a proxy so that the element's location strategy is defined by the #FindBy and you can reference the WebElement and it will go look it up for you when you use the reference.
If you are going to store locators, don't store a string... store instead a By locator. It has the extra information of the TYPE of locator, e.g. By.id, By.cssSelector, etc. I think this is much cleaner approach and will prevent you from having to somehow determine what type of locator that string variable is. This is the approach I use in all the Selenium projects that I have written and/or maintain.
According to the Selenium contributors, PageFactory should not be used. See this yt video of Simon Stewart, Lead Committer, stating don't use it (27:26) and so on and why. The link starts the section that leads into his comments on PageFactory.

Pass value to xpath at runtime

Please read the whole Q before disliking or commenting something. I have searched on internet before posting it here. I'm having the below project structure.
pages(package)
> Homepage.java
test(package)
> Flipkart.java
Inside Homepage.java i have declared all the WebElements using POM Page Factory methods and created respective method to click on Electronics link.
#FindBy(xpath = '//input[#title='Electronics']')
private WebElement lnkElectronics;
Inside Fipkart.java I'm calling the Electronics click method.
My doubt over here is the declared WebElement is specifically for Electronics.
Is there a way i can create a WebElement with type like mentioned below and pass value for %s dynamically from main method?
#FindBy(xpath = '//input[#title='%s']')
private WebElement lnkElectronics;
Answer referenced from Page Object Model in Selenium
You cannot create a FindBy with Variable, FindBy accepts only constants.
In case if you want to achieve that variability then you should write or find the element using normal findElement method
As per the Test Design Consideration following Page Object Design Pattern :
A Page Object is an object-oriented class that serves as an interface to a page of the Application Under Test. Your #Tests uses the methods of this Page Object class whenever they need to interact with the User Interface of that page. The benefit is that if the UI changes for the page your #Tests themselves don’t needs to be changed. Only the code within the Page Object needs to be changed.
Advantages :
Clean separation between test code and page specific code such as locators, methods and layout.
A single repository for the operations offered by the page rather than having these services scattered throughout the tests.
Based on these Page Factory features you won't be able to create any generic WebElement for which you can pass value dynamically from main() or #Test annotated method e.g.
#FindBy(xpath = '//input[#title='%s']')
private WebElement lnkElectronics;
You can find almost a similar discussion in Where should I define modal specific code in Selenium Page Object Model pattern
WorkAround : on page class you can define a method, and can pass the text on the fly from the calling class to click on specific tab
if you want to click any common text on the page. You can create a method as given below and can pass the text on the fly to click on that specific tab on that page
public void clickTab(String tabText){
String tabxpath = "//div[contains(text(), '" + tabText + "')]";
driver.findElement(By.xpath(tabxpath)).click();
}

#FindBy doesn't care if the element isn't there when I call initElements

For instance, let's say I have class FanPage, with this annotation
#FindBy(how = How.ID, using = "ctl00__lvph_Add")
private WebElement _AddFanButton;
and then in my test code I say
fanPage = homePage.GoToFanPage()
which does
return PageFactory.initElements(driver, CC_VendorStatisticsMetadata.class);
Now if my annotation is incorrect (let's say it should be ctl00_lvph_AddFan), I would expect my call to initElements to fail. However, it doesn't and it simply returns a FanPage object to me. It only fails if I try to use _AddFanButton.
How do I get PageFactory to look for my annotations from the start?
You don't. The PageFactory does lazy initialization, and that's how it's designed.
Consider a Page Object where certain of your elements don't exist on the page until some action is taken. Since Page Objects are intended to encapsulate business logic and not just the elements on the page, this is a perfectly logical scenario. In that case, your initElements() call would fail on page object initialization every single time, and not give you the chance to call the business logic method that would cause the element to appear.
It's possible that the PageFactory will not work for you if this is a requirement for your test framework. In that case, you'd do well to construct your own implementation.