DEV Community

Cover image for Mastering Advanced Cypress.io Test Automation [Part 4/4]: Writing Custom Functions
Ahsan Bilal
Ahsan Bilal

Posted on • Updated on • Originally published at Medium

Mastering Advanced Cypress.io Test Automation [Part 4/4]: Writing Custom Functions

By the end of this part, you’ll be proficient in writing custom functions for your Cypress.io test suite, paving the way to advanced test automation. So, let’s get started!

Understanding Custom Functions in Cypress.io

Before we dive into the code, let’s first understand what custom functions are in the context of Cypress.io.

While Cypress.io provides many built-in commands to interact with web elements, there may be situations where you need to perform more complex actions or write custom assertions. Fortunately, Cypress.io allows you to create your own custom functions that extend the functionality of Cypress.io. They can be used to perform specific tasks that are not natively supported by Cypress.io, or to simplify the code and make it more readable.

Writing a Custom Function in Cypress.io [Example-1]

Now that we understand what custom functions are, let’s move on to writing one. In this example, we’ll create a custom function to generate random usernames.

function generateRandomUsername() {
  let text = "";
  let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

  for (let i = 0; i < 8; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }

  return "user_" + text;
}
Enter fullscreen mode Exit fullscreen mode

Let’s break down the code above. The generateRandomUsername function takes no parameters and returns a string value. It starts by declaring two variables text and possible.

text is initially an empty string, and possible contains all the possible characters that can be used to generate the random string.

Next, a for loop is used to iterate 8 times, and in each iteration, a random character is selected from the possible string using the Math.random() function. The selected character is then appended to the text string.

Finally, the function returns a string value by concatenating the text string with the prefix “user_”.

Using the Custom Function [Example-1] in a Test Case

Now that we have our custom function, let’s use it in a test case. In this example, we’ll use the custom function to generate a random username and fill it in a registration form.

it('registers a new user with a random username', () => {
  const username = generateRandomUsername();

  cy.visit('https://example.com/register')
  cy.get('#username').type(username)
  cy.get('#email').type('test@example.com')
  cy.get('#password').type('password123')
  cy.get('#submit').click()

  cy.contains('Registration successful!')
})
Enter fullscreen mode Exit fullscreen mode

The test case above starts by generating a random username using our custom function generateRandomUsername(). We then visit the registration page and use the cy.get() command to select the #username, #email, #password, and #submit elements on the page. We fill in the form fields with our test data and click the submit button.

Finally, we assert that the registration was successful by checking for the presence of the success message.

Writing a Custom Function in Cypress.io [Example-2]

Let’s say you need to check that a particular element is visible on the page and has a certain size. You could write a custom function that encapsulates this logic:

Cypress.Commands.add('assertElementIsVisibleAndHasSize', (selector, width, height) => {
  cy.get(selector).should('be.visible').and(($el) => {
    expect($el.width()).to.equal(width)
    expect($el.height()).to.equal(height)
  })
})
Enter fullscreen mode Exit fullscreen mode

Here, we’re defining a custom command using the Cypress.Commands.add() method. Our command takes three parameters: the selector for the element, the expected width, and the expected height. We then use the cy.get() command to select the element and chain the .should() method to check that it is visible. Finally, we use the .and() method to perform additional assertions on the element’s width and height.

Now, you can use this custom command in your tests just like any other Cypress.io command:

it('Checks the size of a visible element', () => {
  cy.visit('https://www.example.com')
  cy.assertElementIsVisibleAndHasSize('.my-element', 100, 200)
})
Enter fullscreen mode Exit fullscreen mode

Summary: Here we’ve seen how to write custom functions in Cypress.io to extend the functionality of the framework and tackle complex test automation scenarios. We’ve provided a detailed explanation of each line of code, how it differs from basic test-case examples, and how to overcome common complications. By using custom functions, you can make your test code more readable, maintainable, and reusable. Custom functions can help you simplify complex test cases, handle dynamic data, and reduce code duplication.


If you liked this, click ❤ so other people will also notice here.


Real-world Examples

While the examples we’ve provided in this series of advanced and complicated topics are useful for learning how to handle iframes, network stubbing, promise resolving, and custom functions, they are somewhat contrived. To truly master these techniques, it’s important to see how they can be applied in real-world scenarios.

For example, let’s say you’re testing an e-commerce website that uses iframes to display product information from a third-party vendor. You might need to test that the correct product information is being displayed in the iframe, and that users can interact with the product options and add the product to their cart.

Similarly, let’s say you’re testing a social media application that relies heavily on network requests to display user content. You might need to use network stubbing to simulate slow network connections or error responses, and test how the application handles these situations.

Finally, let’s say you’re testing a financial application that requires complex interactions with web elements. You might need to write custom functions to perform calculations or validate that certain financial data is being displayed correctly.

By incorporating real-world scenarios into your test automation strategy, you can ensure that your tests are relevant and effective at catching real-world issues. Keep in mind that these advanced techniques are just tools in your testing arsenal — the key is to use them wisely and strategically to achieve your testing goals.

Conclusive Remarks

In this series of topics, we’ve explored some advanced techniques for Cypress.io test automation, including handling iframes, network stubbing, promise resolving, and custom functions. We’ve provided code examples and explained each concept in detail, and we’ve also highlighted the importance of incorporating real-world scenarios into your testing strategy.

By mastering these techniques, you’ll be able to write more efficient and effective automated tests, and catch bugs before they make it to production. With Cypress.io’s powerful testing capabilities and your newfound skills, you’ll be able to take your testing game to the next level. Happy testing!

Top comments (0)