What's the purpose of By keyword in Selenium Java - selenium

Sample Code:
public class RediffLoginPage
{
Webdriver driver;
public RediffLoginPage(Webdriver driver){
this.driver=driver;
}
By username=By.xpath(".//*(#id='login1']");
By Password=By.name("passwd");
}
public Webelement Emailid()
{
return driver.findElement(username);
}
public Webelement Password(){return driver.findElement(Password);}
In this line,
By username=By.xpath(".//*(#id='login1']");
what's the purpose of first By keyword here?
It's object repository code for a testcase.

Class By
Class By extends java.lang.Object and is defined as:
public abstract class By
extends java.lang.Object
Mechanism used to locate elements within a document. In order to create your own locating mechanisms, it is possible to subclass this class and override the protected methods as required, though it is expected that all subclasses rely on the basic finding mechanisms provided through static methods of this class:
public WebElement findElement(WebDriver driver) {
WebElement element = driver.findElement(By.id(getSelector()));
if (element == null)
element = driver.findElement(By.name(getSelector());
return element;
}
By have the following direct known Subclasses:
By.ByClassName
By.ByCssSelector
By.ById
By.ByLinkText
By.ByName
By.ByPartialLinkText
By.ByTagName
By.ByXPath
By.Remotable

Related

Serenity Widget element in Kotlin

We have JUnit Serenity project in kotlin for testing of mobile applications.
We are trying to create custom widget element, but we are half-way successful.
Implementation in java - working
#ImplementedBy(MyWidgetJImpl.class)
public interface MyWidgetJ extends WidgetObject {
public void aaa();
}
public class MyWidgetJImpl extends WidgetObjectImpl implements MyWidgetJ {
public MyWidgetJImpl(final PageObject page, final ElementLocator locator, final WebElement webElement, final long timeoutInMilliseconds) {
super(page, locator, webElement, timeoutInMilliseconds);
}
#FindBy(xpath = "//*[#id='button_text_title']")
private WebElementFacade title;
#Override
public void aaa() {
System.out.println("*********************************" + title.getText());
}
}
This element is correctly initialized in PageObject and title is printed.
Implementation in kotlin - not working
#ImplementedBy(MyWidgetKImpl::class)
interface MyWidgetK : WidgetObject {
fun aaa()
}
class MyWidgetKImpl(page: PageObject, locator: ElementLocator, webElement: WebElement, timeOut: Long) : WidgetObjectImpl(page, locator, webElement, timeOut), MyWidgetK {
#FindBy(xpath = "//*[#id='button_text_title']")
private lateinit var title: WebElementFacade
override fun aaa() {
println("*********************************" + title.text)
}
}
In this case we are not able to build the project. Build errors are:
Error:(10, 1) Kotlin: MyWidgetKImpl inherits conflicting members:
public open fun waitUntilEnabled(): WebElementFacade! defined in
net.serenitybdd.core.pages.WidgetObjectImpl, public abstract fun waitUntilEnabled(): T! defined in
xx.xx.mobile.framework.xxx.MyWidgetK
28 errors of functions/members from WebElementFacade/WebElementFacadeImpl.
Do you know how to properly implement custom serenity Widget in kotlin?
Or by any chance is there different way to create WebElements with custom functionality?

Selenium PageFactory placement in framework

Currently I have the following classes which use PageFactory to initialize the elements that I use.
Base Class:
public class BaseClass {
public static WebDriver driver;
public static boolean bResult;
public BaseClass(WebDriver driver){
BaseClass.driver = driver;
BaseClass.bResult = true;
}}
Login Page Classs that holds the elements:
public class LoginPage extends BaseClass{
public LoginPage(WebDriver driver)
{
super(driver);
}
#FindBy(how= How.XPATH, using="//input[#placeholder='Username']")
public static WebElement username;
Then I use a separate Login class for my actions:
public class Login {
//Login
public static void enterUsernamePassword(String username, String password) throws Exception{
LoginPage.username.sendKeys(username);
LoginPage.password.sendKeys(password);
}
Then my steps class:
#When("^I enter a valid username (.*) and password (.*)")
public void I_enter_a_valid_username_and_password(String username, String password) throws Throwable
{
PageFactory.initElements(driver, LoginPage.class);
Login.enterUsernamePassword(username, password);
}
As you can see I am using PageFactory within the steps class. I hate doing this and would like to put the PageFactory somewhere else, just not in the steps class.
Without adding or deleting any classes, where could I place the PageFactory class? Any help would be appreciated.
I found that the best to do it is by using an Inversion Of Control / Dependency Injection framework. I use Spring but there are other options as well, e.g. Guice, Weld, Picocontainer.
Using Spring you can annotate all pages with #Component and add a PageObject Bean postprocessor to initialize all page elements when the pages are being created.
This approach is also recommended by the Cucumber for Java Book by Aslak Hellesoy (Cucumber Ltd founder). Cucumber also provides

Cannot create an instance for Expected Condition class in C# Selenium

When I try to create an instance for Expected Condition class it throws an error
ExpectedConditions obj = new ExpectedConditions();
The error I'm getting here is "Has no Constructors defined".
ExpectedConditions is a sealed class. And the method reside inside the sealed class are static methods.
In C# class, by default there is a constructor. Only the static classes doesn't have a default constructor.
So I have tried a small example
public sealed class A
{
public static string GetName()
{
return "name";
}
public static int GetID()
{
return 1;
}
public string Name()
{
return "aa";
}
}
//Sealed class with static methods
B obj2 = new B();
B.GetName();
B.GetID();
obj2.Name();
Build Succeeded
In my example code, It's possible to create an object for the sealed class and can be able to access the methods.
Why it is not possible to create an object with default constructor
ExpectedConditions obj = new ExpectedConditions();
for the ExpectedCondition class in C# Selenium? Why it is throwing an error when instantiating?
Some notes before:
The sealed modifier is used for a class to prevent other classes to inherit from it.
static classes do have a static constructor that is called automatically to initialize the class before the first instance is created or any static members are referenced. However, the constructor cannot be called directly. You can read more on the topic here.
Now, to get on the subject, you cannot instantiate the ExpectedConditions class because it's constructor is private. You can only use the it's static methods.
An example would be to find an element by ID and wait until it is clickable:
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementIsClickable(By.Id("id")));
You can see the implementation of the ExpectedConditions class here.
Github location of the ExpectedConditions class is here.

How to get the current remote webdriver instance inside onTestFailure(ITestResult)

I want to integrate the code to take screenshot using remoteWebdriver inside, testng's onTestFailure(ITestResult). I am unable to get the current webdriver instance inside onTestFailure().
Okay, I had a similar problem.
And since there's no clear answer here, I would post my ( working) solution
On your BaseTest / TestBase class, make your RemoteWebdriver instance accessible ( either by having it as a public property or with a getter)
In the Listener class (In my case its a public property):
public class BaseTest {
public RemoteWebDriver remoteDriver;
//... initalize driver
}
public class TestListener implements ITestListener {
#Override
public void onTestFailure(ITestResult result) {
BaseTest test = (BaseTest) result.getInstance();
if (test == null) {
return;
}
RemoteWebDriver driver = test.remoteDriver;
}
}

Page Factory with properties

i m confused :( as automation framework if i use page object/factory than i should use object repository I mean Properties file in selenium webdriver.
OR
i can use one at a time either page factory or properties file approach.
i m using this code:
package Pages;
import java.util.Properties;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
final WebDriver driver;
static Properties prop = new Properties();
#FindBy(how = How.ID, using = "form-login-username")
private WebElement usernameEditbox;
#FindBy(how = How.NAME, using = "password")
private WebElement passwordEditbox;
#FindBy(how = How.NAME, using = "Log In")
private WebElement loginButton;
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public void enterUsername(String login) {
usernameEditbox.clear();
usernameEditbox.sendKeys(login);
}
/*public void enterUsername(String login) {
signInUsername.clear();
usernameEditbox.sendKeys(login);
}*/
public void enterPassword(String password) {
passwordEditbox.clear();
passwordEditbox.sendKeys(password);
}
public void clickSigninButton() {
loginButton.click();
}
public LandingPage login(String login, String password) {
enterUsername(login);
enterPassword(password);
clickSigninButton();
return PageFactory.initElements(driver, LandingPage.class);
}
}
Instead on defining #FindBy(how = How.ID, using = "form-login-username")
private WebElement usernameEditbox; in same file how i can call it from OR.properties ???
Here's a suggestion I made to somebody else using Page Object Pattern.
Properties files would be no different than just separating your elements to an elements class file and initializing them in the way I describe in the linked post.
Edit: Example of an elements class:
#FindBy(css = "button[id='Save']")
public static WebElement buttonSave;
#FindBy(css = "button[id='Cancel']")
public static WebElement buttonCancel;
And so on. The elements class is just meant to hold on to your elements. You then use those elements via the PageFactory.init example shown in the link above. It would be preferred to have a separate elements class for each "page." I hope that's clear enough :)
If you follow the page object pattern, then in theory each selector will only exist once. Therefore, it is acceptable to in affect hard code them in the page object class rather than create some kind of repository or external resource.
Take a look at Test Automation Framework (TAF) which have enhanced Page Object Factory implementation. It will allow you to use a properties file for your locators for your Page Factory classes.
You can mention a default locator file for your factory and can also override it at runtime (if required) by providing a external file.
http://menonvarun.github.io/taf/
http://menonvarun.github.io/taf/pages/locator_in_taf.html