0

I want to use Playwright's Locators in my page objects. I found an example for Javascript (stripped for brevity):

import { Page } from '@playwright/test';

export class TodoPage {
  listItems = this.page.locator('.todo-list li');

  constructor(public readonly page: Page) { }
}

Trying to do the same in my Java code:

public class LoginPage {

    private Page page;

    private Locator loginButton = this.page.locator("#loginButton");

    public LoginPage(Page page){
        this.page = page;
    }
}

throws a null pointer exception, because page is not yet initiated, when initializing loginButton.

I could do

private Locator loginButton;

public LoginPage(Page page){
    this.page = page;

    loginButton =  this.page.locator("#loginButton");
}

but this would become kind of lenghty/ messy, for large page object classes.

Any ideas on how to do that in Java?

Thanks!

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Christian Baumann
  • 3,188
  • 3
  • 20
  • 37

3 Answers3

1

You could put the Locator definition inside the constructor:

public class LoginPage {

    private Page page;
    private Locator loginButton;

    public LoginPage(Page page){
        this.page = page;
        this.loginButton = this.page.locator("#loginButton");
    }
}
  • This is exactly what I already had proposed in my question, but "this would become kind of lenghty/ messy, for large page object classes." – Christian Baumann Feb 11 '22 at 12:28
  • 1
    Ah yes I see it now Christian, not sure how I missed it. It does make the class code longer, but it's the best solution I've come up with. – Peter Jenkins Feb 12 '22 at 18:05
0

I could create a Locator class:

public class LoginPageLocators {

    public Locator LoginButton;

    public LoginPageLocators(Page page) {
        LoginButton = page.locator("#loginButton");
    }
}

And then access the locators in the page object class via eg locators.LoginButton.click().

It wouldn't avoid the clumsiness/ messiness, but at least hide it from the page object class.

Christian Baumann
  • 3,188
  • 3
  • 20
  • 37
0

Following the Playwright page object model docs here: https://playwright.dev/java/docs/pom.

Your setup could look something like this:

public final class LoginPage {
    private final Page page;
    private final Locator loginButton;

    public LoginPage(Page page) {
        this.page = page;
        this.loginButton = page.locator("#loginButton");
    }

    public void clickLoginButton() {
        loginButton.click();
    }
}

public class TestClass {
    Page page;
    Login login;

    @BeforeEach
    void setup() {
        Browser browser = Playwright.create().chromium().launch();
        new BrowserType.LaunchOptions().setHeadless(false);
        page = browser.newPage();
        login = new Login(page);
    }

    @Test
    public void whatever() {
        login.clickLoginButton();
    }
}

Though I'd recommend not splitting out the seperate elements on your page into individual Locators. They add huge amounts of unnecessary typing, I'd keep the locators within the boundary of the method in question, such as this:

public void clickLoginButton() {
    page.locator("#loginButton").click();
}

and then you won't have as much setup.

Iainn
  • 66
  • 6