Hey everyone! I’m new to Puppeteer and trying to figure out how to use the Page Object Model (POM) pattern for my e2e tests. I’ve got some background with Selenium WebDriver, but I can’t find any clear examples for Puppeteer.
I’ve got a simple login test that looks like this:
async function loginTest() {
await browser.goTo('mywebsite.com');
await browser.waitForElement('#username');
await browser.typeText('#username', 'testuser');
await browser.typeText('#password', 'secretpass');
await browser.clickButton('Submit');
await browser.waitForElement('.welcome-message');
}
How would I turn this into a POM? Do I need to use import or is there a better way to structure it? Any tips or basic examples would be super helpful. Thanks!
hey there! i’ve used POM with puppeteer and it’s pretty cool. here’s a quick tip:
create a folder called ‘pages’ and make separate files for each page. then use classes to define the page objects.
for ur login test, u could do something like:
class LoginPage {
constructor(page) {
this.page = page;
}
async login(user, pass) {
await this.page.type('#username', user);
await this.page.type('#password', pass);
await this.page.click('button[type="submit"]');
}
}
hope that helps!
I’ve implemented POM with Puppeteer in my projects, and it’s quite straightforward. Here’s a concise approach:
Create a base Page class that handles common operations. Then, extend it for specific pages. For your login scenario:
// BasePage.js
class BasePage {
constructor(page) {
this.page = page;
}
async navigate(url) {
await this.page.goto(url);
}
async waitAndType(selector, text) {
await this.page.waitForSelector(selector);
await this.page.type(selector, text);
}
}
// LoginPage.js
class LoginPage extends BasePage {
async login(username, password) {
await this.waitAndType('#username', username);
await this.waitAndType('#password', password);
await this.page.click('button[type="submit"]');
await this.page.waitForSelector('.welcome-message');
}
}
export { BasePage, LoginPage };
This structure promotes code reuse and makes tests more maintainable. You can then use it in your test files by importing and instantiating the LoginPage class.
I’ve been using Puppeteer with POM for a while now, and it’s definitely improved my test organization. Here’s how I structure it:
- Create a separate file for each page object (e.g., LoginPage.js).
- In each page object, define methods for actions and selectors.
- Use ES6 classes to create page objects.
For your login example, it might look like this:
// LoginPage.js
class LoginPage {
constructor(page) {
this.page = page;
this.usernameSelector = '#username';
this.passwordSelector = '#password';
this.submitButtonSelector = 'button[type="submit"]';
}
async login(username, password) {
await this.page.type(this.usernameSelector, username);
await this.page.type(this.passwordSelector, password);
await this.page.click(this.submitButtonSelector);
await this.page.waitForSelector('.welcome-message');
}
}
export default LoginPage;
Then in your test file:
import LoginPage from './LoginPage';
describe('Login Test', () => {
it('should log in successfully', async () => {
const loginPage = new LoginPage(page);
await page.goto('mywebsite.com');
await loginPage.login('testuser', 'secretpass');
// Add assertions here
});
});
This approach has made my tests much more maintainable and easier to read. Hope it helps!