With the techniques covered in this part, you’ll have a grasp on promise resolution in Cypress.io and be closer to mastering advanced test automation with Cypress. Let’s begin!
Promise-Resolving
JavaScript is an asynchronous language and often relies on promises to handle async operations. Cypress.io offers powerful tools for handling promises in tests. In this article, we will cover how to resolve promises in Cypress.io tests with an advanced-level example.
Promise-Resolving with Cypress.io: Promises are a fundamental part of modern JavaScript, and they enable asynchronous operations in a non-blocking manner. In Cypress.io, we can use the .then()
method to resolve promises. However, sometimes we may encounter situations where we need to resolve promises before executing further test cases.
Consider a scenario where we need to log in to a website and then perform some actions on the dashboard. Cypress.io offers powerful tools for handling such situations.
Here’s an example code:
describe('Promise-Resolving', () => {
it('Logs in and performs actions on dashboard', () => {
cy.visit('https://example.com')
cy.get('#username').type('testuser')
cy.get('#password').type('testpassword')
cy.get('#login-button').click()
cy.url().then((url) => {
if (url.includes('/dashboard')) {
cy.get('#dashboard-actions').click()
cy.get('#dashboard-action-1').click()
cy.get('#dashboard-action-2').click()
}
else {
cy.log('User is not logged in')
}
})
})
})
In the code above, we first visit the website and enter the login credentials. After clicking on the login button, we resolve the promise by using the .then()
method. We then check if the user is redirected to the dashboard page. If yes, we perform some actions on the dashboard. If not, we log a message saying that the user is not logged in.
Here is a step-by-step breakdown of the code example:
- We start by visiting the website using the
cy.visit()
method. - We then use the
cy.get()
method to locate the username and password fields and enter the login credentials. - We click on the login button using the
cy.get()
method and the.click()
method. - After clicking on the login button, we use the
cy.url()
method to get the current URL and resolve the promise using the.then()
method. - We then check if the URL includes ‘/dashboard’. If yes, we perform some actions on the dashboard using the
cy.get()
and.click()
methods. - If the URL does not include ‘/dashboard’, we log a message saying that the user is not logged in.
Complications and Possible Solutions:
One common issue with resolving promises in Cypress.io tests is that it can lead to flaky tests. Flaky tests are tests that sometimes pass and sometimes fail without any obvious reason. This can happen when the promise resolution takes longer than expected, and the test fails because it times out. To avoid flaky tests, we can use the cy.wrap()
method to wrap the promise and ensure that the test waits until the promise is resolved before proceeding.
it('Resolves promises using cy.wrap()', () => {
// Promise that resolves after 2 seconds
const promise = new Promise(resolve => {
setTimeout(() => {
resolve('Promise resolved!')
}, 2000)
})
// Wrapping the promise with cy.wrap() ensures that the test waits for it to resolve
cy.wrap(promise).should('equal', 'Promise resolved!')
})
In the example above;
- We define a promise that resolves after 2 seconds using the
setTimeout()
method. - We then wrap the promise with the
cy.wrap()
method, which ensures that the test waits for the promise to resolve before proceeding. - We use the
.should()
method to assert that the resolved value of the promise is equal to ‘Promise resolved!’.
In this way, we can ensure that our tests wait for promises to resolve and avoid flakiness in our Cypress.io tests. But another complication is when we encounter nested promises. In such cases, we can use the Promise.all()
method to resolve multiple promises at once.
it('Resolves nested promises using Promise.all()', () => {
cy.visit('https://example.com')
cy.get('#my-element').then(element => {
// Perform an action that returns a promise
const promise1 = element.click()
// Perform another action that returns a promise
const promise2 = cy.get('#my-other-element').click()
// Use Promise.all() to wait for both promises to resolve
Promise.all([promise1, promise2]).then(() => {
// Assert that the expected behavior has occurred
cy.get('#my-element').should('have.class', 'active')
cy.get('#my-other-element').should('be.visible')
})
})
})
In this example, we’re visiting a website and then selecting an element with the ID #my-element
. We're then performing two actions on this element that return promises: a .click()
action and a cy.get()
action to select another element. We're using Promise.all()
to wait for both of these promises to resolve before asserting that the expected behaviour has occurred.
Here’s a step-by-step breakdown of what’s happening in this code:
- We visit the website using
cy.visit()
. - We select an element with the ID
#my-element
usingcy.get()
. - We perform an action on this element that returns a promise by calling
element.click()
. We store this promise in a variable calledpromise1
. - We perform another action that returns a promise by calling
cy.get('#my-other-element').click()
. We store this promise in a variable calledpromise2
. - We use
Promise.all()
to wait for both promises to resolve by passing an array of promises as an argument. When both promises have resolved, the.then()
callback is executed. - Inside the
.then()
callback, we assert that the expected behaviour has occurred by usingcy.get()
and.should()
to check that the#my-element
element has the classactive
and that the#my-other-element
element is visible.
Using Promise.all()
in this way ensures that all promises are resolved before the test continues, helping to prevent flaky tests caused by promise resolution taking longer than expected.
Summary: Handling promises in Cypress.io tests is a critical skill for test automation engineers. It enables us to write more robust tests and handle complex scenarios. In this article, we covered how to resolve promises in Cypress.io tests with an advanced-level example. We also discussed the complications and possible solutions to ensure reliable tests. With these techniques, you can create more robust and efficient tests that can handle complex async scenarios.
If you liked this, click ❤ so other people will also notice here.
Top comments (0)