Cypress
Cypress is a wonderful tool for testing multi-layered Vue components that exceed the capacity of the Vue test library.
We'll provide insight into what Cypress is all about and how to avoid unexpected behavior during your very first integration tests.
Query selectors and variable declarations
If you've ever had to deal with JavaScript or even jQuery in the past, you'll probably feel a desire to store selectors like
cy.get("[data-testid=my-important-button]")
in a variable right away.
You should not follow this intention, because Cypress functions are asynchronous. Yes, even cy.get
! Instead, use an alias to access your stored DOM selectors.
// Via .as('mainButton') we can cache the value.
cy.get('select[data-testid=button-that-i-want-to-use-again]').as('mainButton')
// We can use an "@" to call our cached value.
cy.get('@mainButton').scrollIntoView().click()
// ... more code
// The button is pressed again
cy.get('@mainButton').scrollIntoView().click()
Navigate through the application
Waiver is not easy, yet it makes sense to avoid cy.visit
as much as possible. Think like a user in your tests. Start with cy.visit('/')
on the start page of your application and move to the different pages by pressing navigation points with cy.get("[data-testid=my-navigation-point]").click()
. This provides passive testing of the corresponding buttons and understandable behavior in the test flow.
Do not an set egg timer
Often, especially during the first integration tests, the idea comes up to use cy.wait(10000)
for interface queries. The motto "Think like a user" applies here as well. Rather test with cy.get("[data-testid=my-load-symbol]")
for a visible load indicator. Alternatively, you can listen for the response of an XHR request or check for a filled cart with should("have.length.at.least", 1)
.
This will speed up your tests! While with cy.wait(10000)
you always hope for ten seconds for an answer. You can use cy.get('[data-testid=entry-in-basket]', %7B timeout: 10000 %7D).should('have.length.at.least', 1)
to set a maximum wait time until the element is available in the DOM.
This will save you the difference between the return of the request and the ten defined seconds each time.
Add commands
Extend the cy
context to provide useful functions for all tests.
As an example of a possible extension we would like to introduce the any
function that often accompanies us in our integration tests.
// The first parameter defines the name of the command.
// This is followed by an option object in which we define,
// that we expect a DOM element in our function.
// The last thing is the main function, where you define your
// command.
Cypress.Commands.add('any', %7B prevSubject: 'element' %7D, (subject, size = 1) => %7B
cy.wrap(subject).then((elementList) => %7B
// We create a copy of the passed elements.
const newElementList = [...elementList]
// Then we reshuffle all the items.
newElementList.sort(() => Math.random() - 0.5)
// Finally we pass the desired element length
cy.wrap(newElementList.slice(0, size))
%7D)
%7D)
This allows us to access five random elements in our tests and click them, for example.
cy.get('[data-testid=my-buttons]').any(5).click(%7B multiple: true %7D)
In summary, Cypress is an indispensable tool that we at sum.cumo, a Sapiens company, would not want to miss. The time of annoying manual tests is long gone, long live automation!