Frameworkium / frameworkium-bdd

Integration of Cucumber BDD and frameworkium-core to offer support for using tests written as feature files.
Apache License 2.0
15 stars 19 forks source link

[Question] Calling methods from the same page #13

Closed marek2209 closed 4 years ago

marek2209 commented 4 years ago
   @Step
    @Given("^I have opened Admin Ui login page$")
    public void givenIHaveLogedToAdminUi() throws InterruptedException {
        LoginPage.open();
    }

    @Given("^User logged to Admin Ui as a \"([^\"]*)\" and \"([^\"]*)\"$")
    public void whenImLoginIntoAdminUiAsATypeAnd(String username, String password) throws InterruptedException {
        new LoginPage().get().fillLoginForm(username, password);
        new LoginPage().get().login();
        new DashboardPage().get().getMainMenu();
    }

    @Then("^I click submit button with empty credential$")
    public void thenIClickSubmitButtonWithEmptyCredential() throws InterruptedException {
        new LoginPage().get().loginWithWrongCred();
    }

    @Then("^I should see Invalid Username or Password message$")
    public void thenIShouldSeeInvalidUsernameOrPassword() throws InterruptedException {
        Assert.assertTrue(new LoginPage().get().getInvalidUsernameAndPasswordError());
    }

I have Following code and my question is should i always call (new LoginPage().get().SOME_METHOD or create an LoginPage object and reuse it in other methods? New keyword should be rather for creating instance of page ?

ham1 commented 4 years ago

You can call new LoginPage().get(), however this is a little verbose and it will perform the @Visible etc. checks each time, which might not be required if the page isn't refreshing between each action.

I would recommend the following, "fluent" style:

new LoginPage().get()
        .fillLoginForm(username, password)
        .login()
        .doSomethingWithMainMenu();

Wereby each method returns the page object that you then expect to be on, i.e. fillLoginForm() returns this and login() returns new DashboardPage().get().

Hope that helps.

marek2209 commented 4 years ago

new LoginPage().get() .fillLoginForm(username, password) .login() .doSomethingWithMainMenu();

sorry but that "fluent" style does not work . for me i receive Cannot resolve method error. How methods from pages layer should declared ? im just using public void methodName etc.

madmaximillion commented 4 years ago

Instead of void you will need to return the instance of the page object. That will then allow you to call the next method. So as @ham1 suggests, in the the example given, fillLoginForm(username, password) needs to return LoginPage. eg

public LoginPage fillLoginForm(String username, String password) {
    // do your string entry actions

    return this;
}
marek2209 commented 4 years ago

Instead of void you will need to return the instance of the page object. That will then allow you to call the next method. So as @ham1 suggests, in the the example given, fillLoginForm(username, password) needs to return LoginPage. eg

public LoginPage fillLoginForm(String username, String password) {
    // do your string entry actions

    return this;
}

That works thanks ! But how to avoid using new keyword in methods within the same class . @Then("^I click submit button with empty credential$") public void thenIClickSubmitButtonWithEmptyCredential() throws InterruptedException { new LoginPage().get().loginWithWrongCred(); }

`@Then("^I should see Invalid Username or Password message$")
public void thenIShouldSeeInvalidUsernameOrPassword() throws InterruptedException {
    Assert.assertTrue(new LoginPage().get().getInvalidUsernameAndPasswordError());
}`

and something like this :

new NewPlanPage().get().getPlanDetailsPage(); Assert.assertEquals(new NewPlanDetailsPage().get().getPlanRequestHeader(), "Request"); Assert.assertEquals(new NewPlanDetailsPage().get().getPlanResponseHeader(), "Response");

madmaximillion commented 4 years ago

In your first 2 Steps you can't really avoid it but for your last example could be something like this given that the first line (new NewPlanPage().get().getPlanDetailsPage()) is redundant and not required as you are not using the (i assume) PlanDetailsPage object.

NewPlanDetailsPage newPlanDetailsPage = new NewPlanDetailsPage().get();
Assert.assertEquals(newPlanDetailsPage.getPlanRequestHeader(), "Request");
Assert.assertEquals(newPlanDetailsPage .getPlanResponseHeader(), "Response");

That way you only need to get an instantiate of the object once and then re-use it.

madmaximillion commented 4 years ago

You could also use the FWs PageFactory to completely remove the "new" . This is located in com.frameworkium.core.ui.pages and could be used as follows but also has some useful overloads PageFactory.newInstance(NewPlanDetailsPage.class)

marek2209 commented 4 years ago

Thank you that will be helpful :)