I recently started working on Cypress and I see a lot of assertions inside of helper functions/automation steps, this seems to me like it would be a bit of an anti-pattern since it would repeat these assertions in every and any other test that is also using that automation step, e.g. logging in,
Having this should in the helper function/step will cause every other test which is logged in to also have unnecessary assertions I would think, and longer functional tests would begin to have a lot of assertions which aren't needed for a specific test. Am I overthinking this issue, or is it valid? I also was interested if there were any performance impacts of this, I assume it's pretty fine for a simple one like this, but for much longer multi-step tests, would this begin to be a concern? I couldn't find any other resources on this specifically, so I would love any insight or direction if I'm overthinking it, or it is something to refactor and consider. (For reference as well, app actions and component testing are not in use here, and not currently an option)
cy.get('[data-cy="login-email"]').type('username')
cy.get('[data-cy="login-password"]').type('password')
cy.get('[data-cy="login-btn"]').click()
cy.get('[data-cy="profile-btn"]').should('exist').and('contain', 'username')
My fix would be to put assertions into the respective test case's IT/Specify block, instead of the helper functions.
Your question is valid. You can create a custom action for login, and indeed when working on bigger applications the impact of performing the login as an assertion gets more noticeable as we might cause some performance issues and make our test suites more time-consuming, plus this would mean that we have a dependency between our tests which is generally a bad practice:
Tests should always be able to be run independently from one another and still pass.
So that's why the documentation suggested this talk: https://youtu.be/5XQOK0v_YRE?t=512
Which talked about these recommendations:
Don't use the UI to build up the state, use it directly
Don't share page objects to share UI knowledge, write specs in isolation
Don't limit yourself to trying to act like a user, you have native access to everything
So basically you might make your login command use your authentication API endpoints and save the JWT tokens in your state and then just pull it from there instead of re-running your login assertions and actions.
Cypress.Commands.add('login', () => {
cy.request({
method: 'POST',
url: 'BASE_URL/login',
body: {
user: {
email: '[email protected]',
password: 'a_pwd',
}
}
})
.then((resp) => {
// if your application loads the jwt from localstorage for example
window.localStorage.setItem('jwt', resp.body.user.token)
})
})
Then in your tests:
beforeEach(() => {
cy.login()
})
This might be challenging if you want to test social logins, for that please have a closer look at: