You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

0 Días
10 Hrs
20 Min
58 Seg
Curso de Cypress Avanzado

Curso de Cypress Avanzado

Javier Fuentes Mora

Javier Fuentes Mora

Patrones de diseño: Page Object Model

10/29
Resources

What is the Page Object Model (POM)?

The Page Object Model, commonly abbreviated as POM, is a design pattern that facilitates the organization and maintenance of automated test code. In essence, POM treats each page of a website as an object, allowing it to handle interactions and elements in a scalable and clean way. Instead of directly referencing page elements in multiple places in your tests, they are encapsulated in a single object, allowing for reuse and easy updating.

How to implement the POM in Cypress?

Implementing the Page Object Model in Cypress is simple and brings clarity to your automated tests. To begin, you must create a specific directory for your page objects. This structure not only improves organization, but also simplifies maintenance over time.

Creating and structuring your objects

  1. Create a Page Objects directory: Inside Cypress, a directory called PageObjects is created. All the classes that will represent the pages of the web site will be stored there.

  2. Define a class for each page: Each page must have its corresponding class, for example: loginPage for a login page. Here the identifiers of the relevant elements are stored in constants.

    // Example of class for login pageexport class loginPage { constructor() { this.userInput = 'userLogin'; this.passwordInput = 'password'; this.loginButton = 'loginButton'; }}
  3. Methods to interact with the elements: Within each class, methods are created to handle actions on the page. For example, a visit method to navigate to the page and a login method to simulate login.

    visit() { cy.visit('http://example.com/login');}
    login(email, password) { cy.get(this.userInput).type(email); cy.get(this.passwordInput).type(password); cy.get(this.loginButton).click();}
  4. Export and initialization of the page object: This allows the class to be used in testing.

    export const loginPage = new LoginPage();

Creating tests with POM

  1. Write readable and scalable tests: Use the methods defined in the classes to perform actions in the tests. This not only makes the code easier to read and understand, but also makes tests less error-prone when element identifiers change.

    describe('Login Tests', () => { beforeEach(() => { loginPage.visit(); });
     it('Login Erroneous', () => { loginPage.login('[email protected]', 'passwordIncorrect'); loginPage.validateErrorLogin(); });
     it('Login Successful', () => { loginPage.login('[email protected]', 'passwordCorrect'); loginPage.validateSuccessLogin(); });});

What are the benefits and challenges of POM in Cypress?

The use of the Page Object Model in Cypress offers several benefits:

  • Maintainability: It centralizes element location logic, which makes updates simple when identifiers change.
  • Reusability: Methods and elements are defined only in their respective classes, allowing their constant reuse without code duplication.
  • Clarity and Simplicity: It facilitates the reading and understanding of the test flow, being more evident what action is being carried out in each part of the tests.

However, it is important to consider the challenges as well:

  • Some developers argue that Cypress, due to its nature, does not require following the POM rigorously, which can pose a dilemma about whether to always use this pattern.
  • Cypress offers native alternatives such as "Custom Commands", which allow you to further simplify testing without strictly adhering to POM.

I encourage you to explore both options and decide which one best suits your needs and testing style. Continue learning and acquiring new skills will open many doors for you in the future. Go ahead, and good coding!

Contributions 3

Questions 1

Sort by:

Want to see more contributions, questions and answers from the community?

La URL de prueba que usa el profesor en esta clase es

http://zero.webappsecurity.com/login.html

El constructor de la clase es el siguiente:

export class LoginPage {
    constructor() {
        this.userInput = "#user_login";
        this.passwordInput = "#user_password";
        this.loginButton = "#login_form > div.form-actions > input";
        this.tabs = {
            account_summary_tab: "#account_summary_tab",
            account_activity_tab: "#account_activity_tab",
            transfer_founds_tab: "#transfer_funds_tab",
        };
        this.error = ".alert.alert-error";
    }
}

Dejo de aporte mi solucion, agregue algunas cosas a fin de parametrizar el test y tener datos reutilizables.

//login.cy.js
import LoginWebPage from '../pages/LoginPage'; //import del POM
const loginData = require('../fixtures/loginData'); //data guardada
let loginWebPage, data;

describe('Test de Login', () => {
  beforeEach(() => {
    loginWebPage = new LoginWebPage();
    loginWebPage.visit();
    loginWebPage.isLoadPage();
  });
  it('Do wrong login', () => {
    data = loginData.wrong;
    loginWebPage.doLogin(data.username, data.password);
    loginWebPage.isErrorDisplayed();
  });
  it('Do correct login', () => {
    data = loginData.correct;
    loginWebPage.doLogin(data.username, data.password);
    loginWebPage.validateSuccessfulLogin();
  });
});

Aparte, tengo un archivo con datos que podria reutilizar y cambiar en un solo lugar si estos fueran modificados.

//loginData.js
module.exports = {
  correct: {
    username: 'username',
    password: 'password',
  },
  wrong: {
    username: 'lalala',
    password: 'lalala',
  },
};

Por ultimo, un ejemplo de como deje el POM, agregue la URL para no cambiarla en varios lugares si lo necesitara.

export default class LoginWebPage {
  constructor() {
    this.URL = 'https://zero.webappsecurity.com/login.html';
    this.userInput = '#user_login';
    this.passwordInput = '#user_password';
    this.loginButton = '#login_form > div.form-actions > input';
    this.tabs = {
      account_summary_tab: '#account_summary_tab',
      account_activity_tab: '#account_activity_tab',
      transfer_founds_tab: '#transfer_funds_tab',
    };
    this.error = '.alert.alert-error';
  }

  visit() {
    cy.visit(this.URL);
  }

  isLoadPage() {
    cy.get(this.loginButton).should('be.visible');
    cy.get(this.passwordInput).should('be.visible');
    cy.get(this.userInput).should('be.visible');
  }

  validateSuccessfulLogin() {
    cy.get(this.tabs.account_activity_tab).should('be.visible');
    cy.get(this.tabs.account_summary_tab).should('be.visible');
    cy.get(this.tabs.transfer_founds_tab).should('be.visible');
  }

  doLogin(username, password) {
    cy.get(this.userInput).type(username);
    cy.get(this.passwordInput).type(password);
    cy.get(this.loginButton).click();
  }

  isErrorDisplayed() {
    cy.get(this.error).should('be.visible');
  }
}

todo es mejor con POO!