</>

Technology

Cypress

Difficulty

Intermediate

Interview Question

How do you implement Page Object Model (POM) in Cypress?

Answer

Page Object Model in Cypress

Cypress doesn't enforce any structure, but POM keeps tests maintainable by separating selectors and actions from test logic.

Project Structure

CODE
cypress/
├── e2e/
│   ├── login.cy.js
│   └── dashboard.cy.js
├── pages/
│   ├── LoginPage.js
│   ├── DashboardPage.js
│   └── BasePage.js
├── support/
│   └── commands.js
└── fixtures/
    └── users.json

Base Page

JavaScript
// cypress/pages/BasePage.js
class BasePage {
  visit(path) {
    cy.visit(path);
    return this;
  }

  getElement(selector) {
    return cy.get(selector);
  }

  clickElement(selector) {
    cy.get(selector).click();
    return this;
  }

  typeInField(selector, text) {
    cy.get(selector).clear().type(text);
    return this;
  }
}

export default BasePage;

Login Page Object

JavaScript
// cypress/pages/LoginPage.js
import BasePage from './BasePage';

class LoginPage extends BasePage {
  // Selectors
  elements = {
    emailInput:    () => cy.get('[data-testid="email"]'),
    passwordInput: () => cy.get('[data-testid="password"]'),
    loginBtn:      () => cy.get('[data-testid="login-btn"]'),
    errorMsg:      () => cy.get('[data-testid="error-message"]'),
  };

  // Actions
  visit() {
    return super.visit('/login');
  }

  enterEmail(email) {
    this.elements.emailInput().type(email);
    return this;
  }

  enterPassword(password) {
    this.elements.passwordInput().type(password);
    return this;
  }

  clickLogin() {
    this.elements.loginBtn().click();
    return this;
  }

  login(email, password) {
    return this.visit()
               .enterEmail(email)
               .enterPassword(password)
               .clickLogin();
  }

  // Assertions
  verifyErrorMessage(msg) {
    this.elements.errorMsg().should('be.visible').and('contain', msg);
    return this;
  }
}

export default new LoginPage();

Dashboard Page Object

JavaScript
// cypress/pages/DashboardPage.js
import BasePage from './BasePage';

class DashboardPage extends BasePage {
  elements = {
    heading:   () => cy.get('h1'),
    userName:  () => cy.get('[data-testid="user-name"]'),
    logoutBtn: () => cy.get('[data-testid="logout"]'),
  };

  verifyUserLoggedIn(name) {
    this.elements.heading().should('contain', 'Dashboard');
    this.elements.userName().should('contain', name);
    return this;
  }

  logout() {
    this.elements.logoutBtn().click();
    return this;
  }
}

export default new DashboardPage();

Test Using Page Objects

JavaScript
// cypress/e2e/login.cy.js
import LoginPage from '../pages/LoginPage';
import DashboardPage from '../pages/DashboardPage';

describe('Login Tests', () => {
  it('should login successfully', () => {
    LoginPage
      .login('test@automateqa.com', 'Test@123');

    DashboardPage
      .verifyUserLoggedIn('QA Tester');
  });

  it('should show error for wrong password', () => {
    LoginPage
      .visit()
      .enterEmail('test@automateqa.com')
      .enterPassword('WrongPass')
      .clickLogin()
      .verifyErrorMessage('Invalid credentials');
  });
});

Follow AutomateQA

Related Topics