I have Hooks.java for driver class,LoginPage.java for all login page objects and step definition class. My page factory object is not initializing in my login class, it returns null due to null driver. Driver class having @Before tag and its initiate before all classes but the driver is null. When I use PageFactory.initElements(driver, LoginPage.class); in the hook class that time page factory initialize and program runs successfully. I am using it in LoginPage constructor, just wondering what I am doing wrong. Why page factory returns null? How to use page factory.
Following is the error java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.WebElement.sendKeys(java.lang.CharSequence[])" because "steps.LoginPage.txtUserNameBox" is null
Please help. Thanks
Hooks.java
package steps;
import Util.GetConfigProp;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java8.En;
import org.openqa.selenium.Platform;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.PageFactory;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
public class Hooks extends BaseUtil implements En {
BaseUtil base;
// GetConfigProp prop;
static GetConfigProp prop;
static {
try {
prop = new GetConfigProp();
} catch (IOException e) {
e.printStackTrace();
}
}
public Hooks() {
//Default constructor
Before(() -> {
DesiredCapabilities cap = new DesiredCapabilities();
cap.setBrowserName("chrome");
cap.setPlatform(Platform.WINDOWS);
cap.setCapability("marionette", true);
ChromeOptions COptions = new ChromeOptions();
COptions.merge(cap);
String hubUrl = null; //get hub url from properties file
hubUrl = prop.getHubUrl();
base.driver = new RemoteWebDriver(new URL(hubUrl), COptions);
base.driver.navigate().to(prop.getUrl()); //get url from properties file
base.driver.manage().window().maximize();
base.driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
// PageFactory.initElements(driver, LoginPage.class);
});
}
public Hooks(BaseUtil base) {
this.base = base;
}
public WebDriver getDriver() {
return base.driver;
}
@After
public void tearDown() {
base.driver.quit();
}
}
LoginPage.java
package steps;
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 extends BaseUtil {
BaseUtil base;
@FindBy(how = How.ID, using = "user-name")
public static WebElement txtUserNameBox;
@FindBy(how = How.ID, using = "password")
public static WebElement txtPassword;
@FindBy(how = How.ID, using = "login-button")
public static WebElement btnLogin;
public LoginPage() {
//Default constructor
}
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void login() {
System.out.println("this is title" + base.driver.getTitle());
System.out.println("this is getwindow" + base.driver.getWindowHandle());
txtUserNameBox.sendKeys("standard_user");
txtPassword.sendKeys("secret_sauce");
btnLogin.click();
}
public void loginPassword() {
//to be implement
}
}
MyStepdefs8.java
package steps;
import io.cucumber.java8.En;
public class MyStepdefs8 extends LoginPage implements En {
BaseUtil base;
LoginPage login = new LoginPage();
public MyStepdefs8(BaseUtil base) {
this.base = base;
}
public MyStepdefs8() {
Given("the user is on landing page", () -> {
login.login();
});
When("^the user clicks button$", () -> {
System.out.println("this is second step");
loginPassword();
});
}
}
In the class MyStepdefs8, when you are creating the object of LoginPage initializes the default constructor for LoginPage class. And hence it returns null when you are calling WebElements as they are not initialized yet.