Hello 👋

I'm Alejandro

A Web Engineer from Málaga, Spain based in London, UK

Mocking a Server Error with cypress

When doing cypress end-to-end tests, it is very tempting to only be testing the happy path most of the time.

The happy path, is the one we think users will follow, the ideal journey that will take a user from state A to B. But users have unexpected behaviour, or even worse, things don't work out the way we think and the API that is communicating with our application is down and cannot respond.

Your tests, needs to give you the confidence that you need to ship your product in the best shape possible, for that I'm going to show you how to also cover the sad path in the case your API or service is not responding.

The happy path

We have a login test that passes. It's testing that a user can login with an existing email and password, which is ideal, and we need to definitely cover that case.

describe('Login', () => {
  it('should login with an existing user', () => {
    cy.visit('/login')

    cy.get('#email').type('username@example.com')
    cy.get('#password').type('mysecretpassword')
    cy.get('form').submit()

    cy.url().should('eq', `${Cypress.config().baseUrl}/`)
  })
})

When cypress is submitting the form with cy.get('form').submit(), it is calling an API endpoint called /api/login and it's sending across the email and password we have provided, and then redirecting to our homepage.

With this test above, we should have enough confidence that this user journey is cover.

The sad path

But what if our endpoint is not responding or there is a problem on the server. Then, our application should inform the user we are experiencing difficulties with login them in, and to cover that case we want to write the following test.

describe('Login', () => {
  it('should show an error when login does not respond', () => {
    cy.visit('/login')

    cy.server().route({
      method: 'POST',
      url: 'https://mywebsite.com/api/login',
      status: 500,
      response: {
        message: 'Something went wrong, please try again later',
      },
    })

    cy.get('#email').type('username@example.com')
    cy.get('#password').type('mysecretpassword')
    cy.get('form').submit()

    cy.url().should('eq', `${Cypress.config().baseUrl}/login`)
    cy.get('#error').contains(/something went wrong, please try again later/i)
  })
})

The important part which we will need to focus in this case is here:

cy.server().route({
  method: 'POST',
  url: 'https://mywebsite.com/api/login',
  status: 500,
  response: {
    message: 'Something went wrong, please try again later',
  },
})

Which is telling cypress, in your server, create an interceptor which will intercept any route matching the method POST and url https://mywebsite.com/api/login, and for that route, cypress will respond with status 500 and a response of a message saying Something went wrong, please try again later.

After that, we should assert that we are not getting redirected and our message is appearing on our UI.

If you re-run your test with that and open the dev-tools in the Network tab, you can even see that your login attempt fails with a 500, so that actually cypress is handling your API route and making it fail.

And hopefully, all your tests are green.

Share this post

Read more about