5 MIN READ
   //   Jun 11, 2020

Cypress Automation for e-commerce site

Divya Sejekan

The e-commerce wave of conducting business online is growing day by day. And with that, delivering the best user experience is their utmost priority. Our team recently developed a Decoupled e-commerce site - 'Shop the Area' powered by Drupal as its backend and Gatsby as frontend. The website carries several independent boutiques. The user can buy products from the boutiques which are within their 15-mile radius. Since an e-commerce site demands numerous functional and end to end tests, automating this was cumbersome. So, we decided to implement Cypress for automating the testing process for our e-commerce site.

Cypress

Cypress is an end to end JS-based web-testing framework which is an excellent tool for an end to end testing, resulting in easy implementation of Functional test scenarios in websites. Cypress is easy to understand and adopt. It has an awesome GUI, runs on the browser, Automatic waits, fast response, easy debugging etc.

Installing Cypress

I installed Cypress using npm, the npm must be pre-installed in the system. Then, create a project folder, set this folder as the root folder in the terminal and install Cypress using the code given below.

1. Download Cypress

npm install cypress

2. Mention base URL pointing at the domain which we are going to test in  cypress.json file. Since we are referring to ‘Shop the area’ website, I will enter “https://shopthearea.netlify.app/”. We can also set viewport in which we want to test.

{
"baseUrl": "https://shopthearea.netlify.app/"
}

3. So let's try out a simple test script. Create a .js file in the integration folder Write a scenario that needs to be tested. 

For example in our site, I create header.js script to check the menu link and their landing page in the header.

Spec file: Header.js

import Header from "../Page/header";
var menu = require("../Data/header");

describe("Check the header of the website", () => {
  const header = new Header();
  beforeEach(() => {
      cy.visit('/');
  });

  it('Check menu links and their landing pages', function () {
      header.getMenu().contains("CLOTHING").click();
      cy.url().should('contain', "/products" + menu.header["CLOTHING"]);
      header.getMenu().contains("JEWELLERY").click();
      cy.url().should('contain', "/products" + menu.header["JEWELLERY"]);
      header.getMenu().contains("SHOES").click();
      cy.url().should('contain', "/products" + menu.header["SHOES"]);
      header.getMenu().contains("BOUTIQUES").click();
      cy.url().should('contain', menu.header["BOUTIQUES"]);
  });
}

Since I have implemented POM in my tests, I have created a function for pointing on to the menu and a JSON file for storing user data like the URLs for this test. 

Let’s import these 2 files in the test file.

POM file: header.js

class Header {
  getMenu(){
      return cy.get(".main-navigation .menu-item .menu-item-link");
  };
export default Header

Data file: header.json

{
"header": {
  "CLOTHING": "/clothing",
  "JEWELLERY": "/jewellery",
  "SHOES": "/shoes",
  "BOUTIQUES": "/boutiques"
}
}

4. Open the GUI through the terminal.

./node_modules/.bin/cypress open

5. Run test

Cypress Automation

Test Organisation

Organising the Test folder is essential for easy maintenance. 

  1. Test files are in cypress/integration under the Spec folder. The execution test scripts are created here.
  2. POM files are in the Page folder. POM enables us to write the tests using objects that are relevant to the application; limit the use of selectors and other page-specific code, making the test code clean and easy to understand
  3. User data in Data folder. Static data can be stored in this folder.

To understand the structure to the image below.

Cypress Automation

Functional testing can be done for the following using Cypress:

  • Homepage components - Testing header, footer 
  • Listing pages such as product listing, boutiques listing pages
  • Detail pages like - Boutique detail pages, product detail pages
  • Login page, Sign up page
  • Cart and checkout pages
  • End to End test of buying products

Example scripts

| Feature: Verify Cart

Test scenarios example:

  1. Adding a product to the cart, checking the components of a product in the cart such as image, name, quantity widgets.
  2. Check removal of products from the cart. 
  3. Check for an empty message when all the products are removed

Since this website has a location feature, the script includes setting location before each test section.

Spec File: Cart.js 

import CartPage from "../Page/cartPage";
import Locations from "../Location/location";

var product = require('../Data/product_Data');
var placeName = require("../Location/locationData");

describe('Verify Add to cart', function () {
  const cart = new CartPage();
  const location = new Locations();

  beforeEach(function () {
      cy.visit(product.Basic_detail["url"]);
      location.setLocation(placeName.locations["location_inside"]);
  });
it("Check the components of a product card in cart", function () {
  cart.clickOnAddToCartButton();
  cart.goToCartPage();
  cart.getProductImage().should("be.visible");
  cart.getProductBoutiqueName().should("have.text", product.Basic_detail["boutiqueName"]);
  cart.getProductName().should("have.text", product.Basic_detail["productSKU"]);
  cart.getProductQuantity().should("be.visible");
  cart.getQuantity().should("have.text", "1.00");
  cart.clickPlusQuantity();
  cart.getQuantity().should("have.text", "2.00");
  cart.clickMinusQuantity();
  cart.getQuantity().should("have.text", "1.00");
});

it('To check product removal using cancel', function () {
  cart.clickOnAddToCartButton();
  cart.goToCartPage();
  cart.clickCancel();
  cart.getProductInCart().should("not.exist");
});
it("To check empty message when all the products are removed", function () {
  cart.clickOnAddToCartButton();
  cart.goToCartPage();
  cart.clickCancel();
  cy.contains("Your cart is currently empty!");
  cart.getContinueShoppingButton().should("have.text", "Start Shopping!").click();
  cy.url().should("contain", Cypress.config().baseUrl + "products");
});

POM file: cart.js

var location = require('../Location/location');
class CartPage {
  goToProductPage(link) {
      cy.visit(link)
  };

  clickOnAddToCartButton() {
      return cy.get(".product-detail-info .product-detail-button .add-cart-button").click();
  };

  goToCartPage() {
      cy.wait(4000);
      return cy.get('.cart-icon-desktop').click({timeout:60000});
  };

  getProductInCart() {
      return cy.get(".cart-product",{timeout:60000});
  }

  getProductImage() {
      return cy.get(".cart-product-image img",{timeout:60000})
  };

  getProductBoutiqueName() {
      return cy.get(".cart-boutique-title")
  };

  getProductName() {
      return cy.get(".cart-product-name")
  };

  getProductQuantity() {
      return cy.get(".cart-quantity-value")
  };

  clickCancel() {
      cy.get(".cart-remove-item").click();
  };


  getQuantity() {
      return cy.get(".cart-quantity span");
  };

  clickPlusQuantity(){
      return cy.get(".cart-quantity > button:nth-child(3)").click();
  };

  clickMinusQuantity(){
      return cy.get(".cart-quantity > button:nth-child(1)").click();
  };

Cypress Automation

| Feature: Search Functionality

Example Scenarios:

  1. To check if products are displayed when the user enters a keyword in the Search field, and check if the search keyword is displayed in the search field on the result page.
  2. To check “No product found” message is displayed when the user enters a random keyword in the Search field.
  3. To check if the drop-down of the search field displays suggestions related to the searched keyword

Spec File: search.js

import Search from "../Page/search";
import Locations from "../Location/location";

var placeName = require("../Location/locationData");

describe("Verify search functionality", function () {
  const search = new Search();
  const location = new Locations();
  var searchKeywordProduct = "Dress";
  var noProduct = "asdfghjkl";

  beforeEach(function () {
      cy.visit("/");
      location.setLocation(placeName.locations["location_inside"]);
  });

  it("To check products are displayed when user enters a keyword in Search field", function () {
      search.getSearchField().type(searchKeywordProduct).type('{enter}');
      search.getProduct().should("be.visible");
      search.getSearchField().should("have.text", searchKeywordProduct);
  });

  it("To check No product message is displayed when user enters a random keyword in Search field", function () {
      search.getSearchField().type(noProduct).type('{enter}');
      search.getErrorMessage().should("contain.text", "No products are available related to your search");
      search.getContinueShoppingButton().should("have.text", "Continue Shopping!").click();
      cy.url().should("eq", Cypress.config().baseUrl + "products")
  });

  it("To check the drop down of the search field has suggestion related to the searched keyword",function () {
      search.getSearchField().type(searchKeywordProduct)
      search.getDropdown().contains(searchKeywordProduct, { matchCase: false });
  });
});

Cypress Automation

In the first scenario, the search term display in the search field of the result page failed, this is clearly highlighted in the Cypress test runs. This feature is helpful in debugging such issues.

Conclusion

Cypress test runner is fast and easy to write-run end-to-end tests. Cypress has numerous plus points like easy debugging, simple cypress GUI, automatic waits, supports different browsers, saves screenshots and videos, consistent tests, etc. All these features make it a user-friendly testing tool. 

Few points to be kept in mind while automating an e-commerce website: 

  1. Decide on Test scenarios which can be automated, or needs automation.
  2. Think of implementing test cases with inbuilt functions and use minimum coding.
  3.  Maintain organised Test folder structure and naming conventions. This helps avoid confusion. For starters, the POM model can be followed.
  4. Since Cypress mainly detects elements using selectors. Get accustomed to identifying CSS, Xpath selectors of elements. This will save a lot of time in implementations of tests.
  5. Sometimes elements are missed out in automatic waits. This issue can be solved by applying timeouts, implicit waits for the element.

Happy Testing :)