WaitForElement does not work in the PageObject - java

The problem is that it is waiting for element for a long period of time and does not find. And error is not present. But when I try debug element is finding.
As you can see I use WebDriverWait wait = new WebDriverWait(driver, 20); in every method. May be it is the problem.
I have BasicClasses
public class BasicClasses {
protected WebDriver driver;
protected LoginPage login;
protected AccountsPage account;
protected ContactPage contact;
protected HomePage home;
private StringBuffer verificationErrors = new StringBuffer();
#Before
public void setup() throws Exception {
driver = new FirefoxDriver();
driver.get(Url.loginUrl);
login = new LoginPage(driver);
home = new HomePage(driver);
login.loginAs(Data.usernameLogin, Data.passwordLogin).chooseDealerFromDealerPopUP();
home.checkIfAccountForTestingIsPresent();
}
#After
public void tearDown() throws Exception {
driver.quit();
String verificationErrorString = verificationErrors.toString();
if (!"".equals(verificationErrorString)) {
fail(verificationErrorString);
}
}
Login Page:
public class LoginPage extends Page {
public LoginPage(WebDriver driver) {
super(driver);
// TODO Auto-generated constructor stub
}
public HomePage loginAs(String user, String pass) throws InterruptedException{
assertEquals("Sign In", driver.findElement(By.xpath(Locator.headerForm)).getText());
driver.findElement(By.id(Locator.usernameLocatorLogin)).clear();
driver.findElement(By.id(Locator.usernameLocatorLogin)).sendKeys(user);
driver.findElement(By.id(Locator.passwordLocatorLogin)).clear();
driver.findElement(By.id(Locator.passwordLocatorLogin)).sendKeys(pass);
driver.findElement(By.cssSelector(Locator.submitButtonLoginPage)).click();
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(Locator.selectDealerPopUp)));
return new HomePage(driver);
}
Abstact class Page:
public abstract class Page {
protected WebDriver driver;
public Page(WebDriver driver) {
this.driver = driver;
}
public WebDriver getWebDriver() {
return driver;
}
And test:
public class AddContactAT extends BasicClasses {
#Test
public void testAddContactWithNoAccess() throws Exception {
contact.addContactWithFullAccess("sss");
}

Related

Java (Selenium) - super class constructor to initialise sub classes

PageOne and PageTwo both need to make use of MasterPage methods (eg click Ok). I'm trying to initialize both pages within the constructor of MasterPage.
IntelliJ tells me to either add super(driver) to the Page1/Page2 constructors, or to add a no arg constructor to master. In both cases, the tests can't run. with a super(driver) constructor, the pages fail to initialize, and in the no arg constructor, the clickOk() method fails when called from the Page1/Page2 method.
MasterPage:
public class MasterPage {
private WebDriver driver;
public Page1 p1;
public Page2 p2;
public MasterPage(WebDriver driver) {
this.driver = driver;
p1 = new Page1(driver);
p2 = new Page2(driver);
PageFactory.initElements(driver, this);
}
#FindBy(id = "OkBtn")
private WebElement okBtn;
public void clickOk() {
okBtn.click();
}
}
Page1:
public class Page1 extends MasterPage {
private WebDriver driver;
public Page1(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
#FindBy(id="field")
private WebElement elementOne;
public void completePage() {
elementOne.click();
clickOk();
}
}
Page2:
public class Page2 extends MasterPage {
private WebDriver driver;
public Page2(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
#FindBy (id="field")
private WebElement elementTwo;
public void completePageTwo() {
elementTwo.click();
clickOk();
}
}
My intention is to utilise them like this:
public class Page1Steps {
MasterPage master;
WebDriver driver;
public void testMethod() {
master = new MasterPage(driver);
master.p1.completePage();
master.p2.completePageTwo();
}
}
You may be able to tell, I'm not 100% sure of the best way to approach this problem, so any guidance would be really appreciated.
First of all, MasterPage shouldn't know about page1 and page2, it's their base class. You also don't need driver in each one of the derived Page, you can hold it in the parent MasterPage.
The problem is MasterPage constructor receives WebDriver parameter, but you don't have call to super(driver) in the derived classes constructors.
I also suggest each method which navigates the test to the another page will return this new page
MasterPage:
public class MasterPage { // can be abstract
protected WebDriver driver;
public MasterPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
#FindBy(id = "OkBtn")
private WebElement okBtn;
protected void clickOk() {
okBtn.click();
}
}
Page1:
public class Page1 extends MasterPage {
public Page1(WebDriver driver) {
super(driver);
}
#FindBy(id="field")
private WebElement elementOne;
public Page2 completePageAndGoToPageTwo() {
elementOne.click();
clickOk();
return new Page2(driver);
}
}
Page2:
public class Page2 extends MasterPage {
public Page2(WebDriver driver) {
super(driver);
}
#FindBy (id="field")
private WebElement elementTwo;
public void completePageTwo() {
elementTwo.click();
clickOk();
}
}
Page1Steps:
public class Page1Steps {
public void testMethod() {
Page1 pageOne = new Page1(driver);
pageOne
.completePageAndGoToPageTwo()
.completePageTwo();
}
}

WebDriver cannot be initialized

I got NullPointerException when I run the #testCase
1. In FrameworkTestCases.class -> #BeforeClass I initialize the instance of the selected webdriver. The browser is running when I start the FrameworkTestCases.class as jUnit test, but when I reach the testCase it says NullPointerException. What is the reason? I also used a constructor with 2 arguments to inherit the driver from the Generic.class to LoginPageFactory.class, but nothing happened.
Here is my FrameworkTestCases class:
public class FrameworkTestCases {
static WebDriver driver;
private static String baseURl = "https://management.tacticlicks.com/";
static LoginPageFactory loginPage;
static Generic generic;
//WebDriver driver;
//static LoginPageFactory lpFactory;
#BeforeClass
public static void setUp() {
generic = new Generic(driver);
generic.getDriver(baseURl, "chrome");
}
#Test
public void test() {
System.out.println("Executing test");
loginPage
.fillUsernameField("ivailostefanov1989#gmail.com")
.fillPasswordField("astral8909")
.clickSubmit();
}
#AfterClass
public static void tearDown() {
driver.quit();
}
}
public class LoginPageFactory extends Generic {
public LoginPageFactory(WebDriver driver2, Class<LoginPageFactory> class1) {
super(driver2, class1);
// TODO Auto-generated constructor stub
}
WebDriver driver;
#FindBy(name="email") //.//*[#id='login']/div[1]/div/div/table/tbody/tr/td[2]/div[1]/form/div[1]/input
WebElement loginUsernameField;
#FindBy(name="password")
WebElement loginPasswordField;
#FindBy(tagName="button")
WebElement loginSubmitButton;
public LoginPageFactory(WebDriver driver) {
System.out.println("LoginPageFactory");
this.driver = driver;
PageFactory.initElements(driver, this);
}
public LoginPageFactory fillUsernameField(String username) {
System.out.println("Before field initializing");
WebElement emailField = driver.findElement(By.name("email"));
emailField.click();
emailField.sendKeys(username);
return this;
}
public LoginPageFactory fillPasswordField(String password) {
loginPasswordField.click();
loginPasswordField.clear();
loginPasswordField.sendKeys(password);
return this;
}
public LoginPageFactory clickSubmit() {
loginSubmitButton.click();
return this;
}
}
public class Generic {
WebDriver driver;
public Generic(WebDriver driver) {
this.driver = driver;
}
public Generic(WebDriver driver2, Class<LoginPageFactory> class1) {
// TODO Auto-generated constructor stub
}
private void getBrowser(String browser) {
if (browser.equalsIgnoreCase("Firefox")) {
File chromeDriver = new File("C:\\Users\\Ivo\\Desktop\\geckodriver.exe");
System.setProperty("webdriver.gecko.driver", chromeDriver.getAbsolutePath());
driver = new FirefoxDriver();
} else if (browser.equalsIgnoreCase("Chrome")) {
//set chromedriver property
File chromeDriver = new File("C:\\Users\\Ivo\\Desktop\\chromedriver.exe");
System.setProperty("webdriver.chrome.driver", chromeDriver.getAbsolutePath());
driver = new ChromeDriver();
} else {
System.out.println("Browser cannot be launched");
}
}
public WebDriver getDriver(String appUrl, String browser) {
getBrowser(browser);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.get(appUrl);
return driver;
}
}
You are missing a variable assignment in #BeforeClass method.
Change
#BeforeClass
public static void setUp() {
generic = new Generic(driver);
generic.getDriver(baseURl, "chrome");
}
to
#BeforeClass
public static void setUp() {
generic = new Generic(driver);
driver = generic.getDriver(baseURl, "chrome");
}
And also you did not create any instance of LoginPageFactory class. You have created a variable static LoginPageFactory loginPage; but didn't initialize it (at least nowhere in provided code).
In method
#Test
public void test() {
System.out.println("Executing test");
//add this line of code to initialize elements via Page Factory
loginPage = new LoginPageFactory(driver);
loginPage
.fillUsernameField("ivailostefanov1989#gmail.com")
.fillPasswordField("astral8909")
.clickSubmit();
}

Selenium Java base class for all browser drivers and code which is redundant

I am new in Selenium and Java and I need help with base class. I have I base where I set methods for driver browsers and for its close. Problem is that when I call these method from main always web driver is called and browser is open many times. What is best practice if I don't want to have code duplication
and I want a good structure of project.
Main:
public class Main extends TestBase {
public static void main(String[] args) throws InterruptedException, ClassNotFoundException, SQLException {
LoginTest LoginTest = new LoginTest();
LogofTest LogofTest = new LogofTest();
TestBase TestBase = new TestBase();
LoginTest.setUpBeforeTestMethod();
LoginTest.loginAsAdmin();
LogofTest.logofAsAdmin();
LoginTest.tearDownAfterTestClass();
}
}
TestBase:
public class TestBase {
String a = System.setProperty("webdriver.chrome.driver",
"path");
WebDriver driver = new ChromeDriver();
protected WebDriver setUpBeforeTestClass() {
return driver;
}
protected void setUpBeforeTestMethod() {
driver.get("website");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void tearDownAfterTestClass() {
driver.close();
}}
LoginTest:
public class LoginTest extends TestBase {
public void login() throws InterruptedException {
WebElement username = driver.findElement(By.name("username"));
username.sendKeys("username");
}
}
The main focus is that I don't want to write again
WebDriver driver = new ChromeDriver();
driver.get("website"); System.setProperty("webdriver.chrome,"path");
for each test in function or class. So I want to create base class and inherit from it.
Example Selenium Test with JUnit using the Page Object Model
TestBase
public class TestBase
{
private String a = System.setProperty("webdriver.chrome.driver", "path");
protected WebDriver driver;
#Before //Before each test case, use BeforeClass for before each test class
public static void setUpBeforeTestCase() {
driver = new ChromeDriver();
driver.get("website");
}
#After
public static void tearDownAfterTestCase() {
driver.Quit(); //driver.Close() closes the window, but doesn't properly dispose of the driver
}
}
LoginTest:
public class LoginTest extends TestBase {
#Test
public void loginAndOutAsAdmin(){
LoginPage loginPage = PageFactory.initElements(driver, LoginPage.class);
LandingPage landingPage = loginPage.login("adminUser", "adminPassword");
landingPage.logout();
//Do some sort of assert here that you are logged out
}
}
BasePage
public class BasePage
{
protected WebDriver driver;
//Other common stuff your Page Objects will do, like wait for an element
}
LoginPage
public class LoginPage extends BasePage
{
#FindBy(how = How.NAME, using = "username")
private WebElement usernameBox;
//something for passwordBox and loginButton
public LoginPage(WebDriver currentDriver)
{
driver = currentDriver;
}
public LandingPage login(String username, String password)
{
usernameBox.sendKeys(username);
passwordBox.sendKeys(password);
loginButton.click();
return PageFactory.initElements(driver, LandingPage.class);
}
}
I haven't tried to compile this, but that's the basic idea. I'll let you fill in the details.

Selenium setting up for tests

I need to be login in to start my tests. So in my test class I make #BeforeClass method where I login to my application. Then I start simply test but it did not work. When I remove my login from #BeforeClass and put it to my test it works fine. But I do not want to login in in all my test before I can start them. I think there is problem with that my object are static but i do not have clue why.
Here is my not working code:
public class ModulesTests extends FunctionalTest {
static LoginPage loginPage;
static LoginPageReceipt loginPageReceipt;
#BeforeClass
public static void login() {
FunctionalTest.driver.get(GlobalVariables.URL);
loginPage = new LoginPage(FunctionalTest.driver);
loginPageReceipt = loginPage.login(GlobalVariables.USER_NAME, GlobalVariables.PASSWORD);
}
#Test
public void products() {
ProductsPage productsPage = loginPageReceipt.productsPage();
}
}
Here is when it works:
public class ModulesTests extends FunctionalTest {
#BeforeClass
public static void login() {
FunctionalTest.driver.get(GlobalVariables.URL);
}
#Test
public void products() {
LoginPage loginPage = new LoginPage(FunctionalTest.driver);
LoginPageReceipt loginPageReceipt = loginPage.login(GlobalVariables.USER_NAME, GlobalVariables.PASSWORD);
ProductsPage productsPage = loginPageReceipt.productsPage();
}
}
And rest of my classes:
public class FunctionalTest {
protected static WebDriver driver;
#BeforeClass
public static void setUp() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--start-maximized");
System.setProperty("webdriver.chrome.driver", "src\\main\\resources\\chromedriver.exe");
driver = new ChromeDriver(options);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
#After
public void cleanUp() {
driver.manage().deleteAllCookies();
}
#AfterClass
public static void tearDown() {
driver.close();
}
}
public class LoginPage extends PageObject {
#FindBy(id = "UserName")
private WebElement userName;
#FindBy(id = "Password")
private WebElement password;
#FindBy(id = "loginButton")
private WebElement loginButton;
public LoginPage(WebDriver driver) {
super(driver);
assertTrue(userName.isDisplayed());
assertTrue(password.isDisplayed());
assertTrue(loginButton.isDisplayed());
}
public void enterUserName(String userName) {
this.userName.clear();
this.userName.sendKeys(userName);
}
public void enterUserPassword(String password) {
this.password.clear();
this.password.sendKeys(password);
}
public LoginPageReceipt login(String userName, String password) {
enterUserName(userName);
enterUserPassword(password);
loginButton.click();
return new LoginPageReceipt(driver);
}
}
public class LoginPageReceipt extends PageObject {
public NavigationModules mainNav;
#FindBy(xpath = "//*[#id=\"loginPartial\"]")
private WebElement userNamePanel;
#FindBy(id = "products-menuitem")
private WebElement goToProductsPage;
public LoginPageReceipt(WebDriver driver) {
super(driver);
}
public String loginConfirmation() {
return userNamePanel.getText();
}
public ProductsPage productsPage() {
System.out.println(goToProductsPage.getText());
goToProductsPage.click();
return new ProductsPage(driver);
}
public NavigationModules initModuleNav() {
return new NavigationModules(driver);
}
}
public class ProductsPage extends PageObject {
#FindBy(id = "products-content-navigation")
private WebElement productMenu;
public ProductsPage(WebDriver driver) {
super(driver);
assertTrue(productMenu.isDisplayed());
}
}
public class PageObject {
protected WebDriver driver;
public PageObject(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
System.out.println(getClass().getName());
}
}
Edit. I just saw that when I use #BeforeClass method I get also java.lang.reflect.constructor.newinstance(unknown source) exception.
You should use #Before so that all your tests have to login before proceeding, meanwhile, #BeforeClass runs one time, and it's usefull just in case multiple tests will share same objects.
Please take a look on this link.

Error: Either make it static or add a no-args constructor to your class

I am running this class as testNG and getting error either make it static or add a no-args constructor. If I add no arg constructor, I get error: "implicit super constructor BaseClass() is undefined."
public class testmaven extends BaseClass{
public testmaven(WebDriver driver) {
super(driver);
// TODO Auto-generated constructor stub
}
#Test
public void myMethod() throws Exception {
logInPage.openApp("Chrome","http://url.com");
}
Here is the Base Class:
public class BaseClass {
public WebDriver driver;
public boolean isDisplay;
public LogInPage logInPage;
public WaitForObj wait;
public DashboardPage dashboardPage;
public Actions action;
public Util util;
public BaseClass(WebDriver driver){
this.driver = driver;
this.isDisplay = false;
logInPage = new LogInPage(driver);
wait = new WaitForObj(driver);
dashboardPage = new DashboardPage(driver);
util = new Util (driver);
action = new Actions(driver);
}
Here is the Login class
public class LogInPage extends BaseClass {
BrowserFactory browserfactory = new BrowserFactory();
public LogInPage(WebDriver driver){
super(driver);
}
public void openApp(String browserName, String env) throws Exception{
driver = browserfactory.getBrowser(browserName);
Log.info("Browser:" + browserName);
driver.manage().window().maximize();
driver.get(env);
Log.info("Env: " + env);
wait.wait(1);
}
You have to explain to TestNG how it is supposed to instanciate your test class.
A solution is using a #Factory.
Another solution, which is a more common pattern, is having an empty constructor and using #BeforeX and/or #AfterX methods for the initialisation of attributes.

Categories

Resources