1

I want to use a workflow similar to the Page Object Pattern that exists in frameworks like Selenium. I want to use my login.spec.js in my editSettings.spec.js, because it requires a user to be logged in.

How do I achieve this in Cypress? Can I export a function from one test file to use in another?

kuceb
  • 16,573
  • 7
  • 42
  • 56

3 Answers3

6

Yes, Cypress supports the ability to create and reuse actions in your UI, such as logging in as a user would.

However, Cypress also allows you to control the state of the browser more powerfully than a user would.

For example: I create a test that a "user can log in with valid username and password"- Cypress navigates to the login page, types in the user field, types in the password field and clicks the "Log in" button. The Page Object Pattern would have you reuse this action on every test that requires a user to be logged in (most of the tests)

Cypress supports this; however, this is slower than it has to be. It takes a considerable amount of time to navigate to a login page, type in the information, handle the response, and navigate to the page under test. Instead, Cypress's API allows the following:

  • use cy.request() to directly hit your server with the login credentials. This requires no state of your app, no typing in fields, no clicking buttons, or page directs
  • Any cookies your site uses are automatically set, or you can set localStorage using the response
  • Make this a custom command, call it before every test, and boom- you've generated your user's state almost instantly and most importantly flake-free
kuceb
  • 16,573
  • 7
  • 42
  • 56
1

I actually came up with these two examples, one using JavaScript and another one with Typescript.

https://github.com/antonyfuentes/cypress-typescript-page-objects https://github.com/antonyfuentes/cypress-javascript-page-objects

Hopefully, this helps someone else.

Antony Fuentes
  • 1,013
  • 9
  • 13
-2

Create a SearchProduct.js file in fixtures folder (You can create it anywhere).Then create a class in it and define your all the methods in it something like this:

class ProductPage {
    getSearchClick() {
        return cy.get('.noo-search');
    }
    getSearchTextBox(){
        return cy.get('.form-control');
    }
    getProductsName() {
        return cy.get('.noo-product-inner h3');
    }
    getSelectSize() {
        return cy.get('#pa_size');
    }
    getSelectColor() {
        return cy.get('#pa_color');
    }
    getAddtoCartButton() {
        return cy.get('.single_add_to_cart_button');
    }
    }

export default ProductPage

After creating the class, let's import it in the command.js file. After that, let's create a new object of it to access all the methods mentioned above in commands.js.

import ProductPage from '../support/PageObjects/ProductPage';

Cypress.Commands.add("selectProduct", (productName, size , color) => { 
    // Creating Object for ProductPage
    const productPage=new ProductPage();

    // Doing the search part for Shirts.
    productPage.getSearchClick().click()
    productPage.getSearchTextBox().type('Shirt');
    productPage.getSearchTextBox().type('{enter}')
    
    productPage.getProductsName().each(($el , index , $list) => {
        //cy.log($el.text());
        if($el.text().includes(productName)) {
            cy.get($el).click();
        }
    })

    // Selecting the size and color and then adding to cart button. 
    productPage.getSelectColor().select(color);
    productPage.getSelectSize().select(size);
    productPage.getAddtoCartButton().click();
 })

So, here actually the custom command's class is importing and using the Page class. Additionally, the test script will use the same command.js to perform the needed action. So, the test script will still be the same and will look as below:

// type definitions for Cypress object "cy"
// <reference types="cypress" />
 
describe('Cypress Page Objects and Custom Commands', function() {
    
    //Mostly used for Setup Part
    before(function(){
    cy.fixture('example').then(function(data)
    {
        this.data=data ;
    })
    })
    
    it('Cypress Test Case', function() {
  
    //Registration on the site
    cy.visit('https://shop.demoqa.com/my-account/');
    cy.get('#reg_username').type(this.data.Username);
    cy.get('#reg_email').type(this.data.Email);
    cy.get('#reg_password').type(this.data.NewPassword);
    cy.get('.woocommerce-Button').click();
 
    //Checking whether the Registration is successful and whether UserName is populated under login section
    cy.get('#username').should('have.value',this.data.Username);
    })
 
    // For Loop for Accessing productName array from Features File and Using the custom command
    this.data.productName.forEach(function(element){
        // Invoke the Custom command selectProduct
        cy.selectProduct(element[0],element[1],element[2]);
    })
})

You can also directly import the class in Test File by skipping Command.js file.

For that go to the following link:

Courtesy: https://softans.com/cypress-page-object-model/

GHULAM NABI
  • 498
  • 5
  • 15