DEV Community

Cover image for How to test that cache works with Cypress
Walmyr
Walmyr

Posted on • Edited on

How to test that cache works with Cypress

Learn how to verify that a search result came from the cache instead of an HTTP request with Cypress.io

Here we go with another "Pinch of Cypress." I hope you enjoy it!

In the advanced course of testing automation with Cypress from the Talking About Testing School, I challenge my students to put the knowledge they got into practice with an application similar to that of the course. This is a searching application that integrates with the Hackernews API. In this application's version (the one for the challenge), when a search has already happened, the results are stored in a cache, avoiding a new request to the API when a search for the same term occurs again.

How do we test that?

🤔

I'll explain with an example.

describe('Hacker News Search', () => {
  const term = 'cypress.io'

  beforeEach(() => {
    cy.intercept(
      '**/search?query=redux&page=0&hitsPerPage=100',
      { fixture: 'empty'}
    ).as('empty')
    cy.intercept(
      `**/search?query=${term}&page=0&hitsPerPage=100`,
      { fixture: 'stories'}
    ).as('stories')

    cy.visit('/')
    cy.wait('@empty')
  })

  it('correctly caches the results', () => {
    const faker = require('@faker-js/faker')
    const randomWord =faker.random.word()
    let count = 0

    cy.intercept(`**/search?query=${randomWord}**`, req => {
      count +=1
      req.reply({fixture: 'empty'})
    }).as('random')

    cy.search(randomWord).then(() => {
      expect(count, `network calls to fetch ${randomWord}`).to.equal(1)

      cy.wait('@random')

      cy.search(term)
      cy.wait('@stories')

      cy.search(randomWord).then(() => {
        expect(count, `network calls to fetch ${randomWord}`).to.equal(1)
      })
    })
  })
})
Enter fullscreen mode Exit fullscreen mode

In the code above, what happens is the following:

  1. We have a test suite for the search functionality for the Hacker Stories application
  2. We defined a variable called term for code reuse reasons
  3. So we have a function that runs before each test (beforeEach)
    1. In the beforeEach function, we defined two routes (which use fixtures) so that we don't depend on the Hackernews API. In the first route, which occurs as soon as the application is rendered, the fixtures will return an empty list of stories, and in the second, they will return two stories
    2. We then visit the home page of the application
    3. And finally, we wait for the initial request to end (the one that returns the empty list of stories)
  4. Hence, we have the test itself to ensure that the cache works
    1. The test uses the faker library to generate random words for the search that the app will store in the cache
    2. Right at the beginning, we define a variable called count, which is initialized to zero (0). This variable's value will increase each time a request occurs for the same search term.
    3. Then we have the definition of another cy.intercept, which intercepts a search request by the random word, performs a function that increments the counter, and finally, responds to that request with the fixture that returns an empty list of stories. Here's the secret, when a request for such a term occurs, the counter will be incremented
    4. There's a search for a random word, and we soon assert that the counter has been incremented correctly. Now, instead of 0, it's 1.
    5. A search for another term is done with their respective waiting. In this case, as it's another term, the counter is not incremented. This other term falls into another cy.intercept (created in beforeEach).
    6. Finally, a new search happens for the random word previously searched, with the verification that the counter has not increased, that is, it continues with a value of 1, demonstrating that a new request did not occur for such a route, proving that the cache works. Note: if the cache weren't working, a new request would occur, which would increase the counter to 2, and the final test assertion would fail.

This is an alternative to test how well a search cache works when talking about automated tests with Cypress. I hope you find it useful.

Reference: https://glebbahmutov.com/blog/cypress-intercept-problems/

See the implementation details of the search custom command:

// cypress/support/commands.js

Cypress.Commands.add('search', term => {
  cy.get('input[type="text"]')
    .should('be.visible')
    .clear()
    .type(`${term}{enter}`)
})
Enter fullscreen mode Exit fullscreen mode

And of the fixtures:

// cypress/fixtures/empty.json

{
  "hits": []
}

Enter fullscreen mode Exit fullscreen mode
// cypress/fixtures/stories.json

{
  "hits": [
    {
      "title": "Sample 1",
      "url": "https://example.com/1",
      "author": "Author 1",
      "num_comments": 34,
      "points": 91,
      "objectID": 0
    },
    {
      "title": "Sample 2",
      "url": "https://example.com/2",
      "author": "Author 2",
      "num_comments": 55,
      "points": 98,
      "objectID": 1
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

That's it!


So, did you like this “Pinch of Cypress“?

Leave a comment.


Are you curious and want to learn more about testing automation with Cypress? I was hoping you could get to know my Cypress courses on Udemy.


This post was originally published in Portuguese on the Talking About Testing blog.


👋 Until next time and happy testing!

Top comments (2)

Collapse
 
paulharshit profile image
Harshit Paul

Thoroughly enjoyed this read! For those looking to delve deeper, I came across this intriguing implementation of cache methods with Cypress. Thought it might be beneficial for the community here!

Collapse
 
walmyrlimaesilv profile image
Walmyr

Thanks for sharing.