somaSomski
somaSomski

Reputation: 3

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.

Upvotes: 0

Views: 2258

Answers (1)

Guy
Guy

Reputation: 50809

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();
    }
}

Upvotes: 2

Related Questions