DEV Community

Cover image for How to read the browser's localStorage with Cypress
Walmyr
Walmyr

Posted on • Edited on

How to read the browser's localStorage with Cypress

In today's “Pinch of Cypress”, learn how to get values saved in your browser's localStorage and then make assertions on them

Not everything that happens at the front end of a web application is visible to the end-user.

When we use different tools on the web, a lot happens behind the scenes, and the browser plays a big role in that.

Imagine a search application that remembers the last searched term.

Let's say one requirement for this functionality is that when the browser is closed and reopened, or when a page reloads, the last searched term is the default value in the search text field.

One way to solve this problem is to save this information in the browser's localStorage to know what to present to the user on the first visit or after a refresh. This logic must be implemented in the frontend, of course.

With graphical user interface (GUI) tests, we can verify that such elements (such as text input fields) are visible on the screen. However, with Cypress, we can go beyond and access the localStorage directly using the getAllLocalStorage command.

Let's go back to the example of the search application that remembers the last searched term.

A possible implementation for the test would be as follows.

// cypress/e2e/search.cy.js

describe('Last searched terms', () => {
  it('shows the last three searched terms for quick searching', () => {
    const url = 'https://wlsf82-hacker-stories.web.app'
    const termsToSearchFor = [
      'foo',
      'bar',
      'baz'
    ]

    cy.visit(url)

    termsToSearchFor.forEach(term => {
      cy.get('#search')
        .clear()
        .should('be.visible')
        .type(`${term}{enter}`)
    })

    cy.reload()

    cy.getAllLocalStorage()
      .then(localStorage => {
        expect(localStorage).to.have.keys(url)
        expect(localStorage[url]['search']).to.eq(termsToSearchFor[2])
      })

    cy.get('#search')
      .should('have.value', termsToSearchFor[2])
  })
})
Enter fullscreen mode Exit fullscreen mode

Let's break it down.

Preparing the Test Data

The test starts by defining the target URL and an array of search terms: foo, bar, and baz. Storing the URL in a variable makes the subsequent assertions much cleaner.

const url = 'https://wlsf82-hacker-stories.web.app'
const termsToSearchFor = ['foo', 'bar', 'baz']
Enter fullscreen mode Exit fullscreen mode

Navigation and Interaction

After visiting the application, the code iterates through each term using a forEach loop. For every term, it:

  • Locates the search input (via #search).
  • Clears any existing text.
  • Types the new term and hits "Enter".
termsToSearchFor.forEach(term => {
  cy.get('#search')
    .clear()
    .should('be.visible')
    .type(`${term}{enter}`)
})
Enter fullscreen mode Exit fullscreen mode

Simulating a Page Reload

To prove that the data is truly persistent (and not just stored in the component's temporary memory), the test triggers a page reload with cy.reload(). This forces the app to re-initialize and fetch saved data from storage.

Validating Local Storage

This is where the magic happens. The test uses cy.getAllLocalStorage() to inspect the browser's storage. By using the url variable defined earlier, the assertions are now more direct:

Key Check: It verifies that a key matching the application URL exists in Local Storage.

Value Check: It confirms that the search key within that storage entry matches the last term searched (baz).

cy.getAllLocalStorage()
  .then(localStorage => {
    expect(localStorage).to.have.keys(url)
    expect(localStorage[url]['search']).to.eq(termsToSearchFor[2])
  })
Enter fullscreen mode Exit fullscreen mode

Final UI Affirmation

Finally, the test circles back to the UI. It checks the search input one last time to ensure it is automatically populated with the last searched term (baz) after the reload.

cy.get('#search')
  .should('have.value', termsToSearchFor[2])
Enter fullscreen mode Exit fullscreen mode

By combining UI interactions with low-level storage assertions, this test provides high confidence that the application's "quick search" history feature is working exactly as intended!


Did you like this content, or do you think your fellow frontend developer will?

Please share it on your networks. I'll be grateful!


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


Would you like to learn about test automation with Cypress? Get to know my online courses on Udemy. Happy testing! 🎉

Top comments (2)

Collapse
 
berns_churches profile image
Berns Fire Death

Awesome. Going to try this library you used for one of my projects where I can test the localStorage using window.localStorage.getItem('session.user') and my test passesbut when I run this in a docker testing automation set-up I get back a null. Any ideas on that or reasons?

Collapse
 
walmyrlimaesilv profile image
Walmyr

I'd have to read the code to reason about it.
I'm glad you liked it though