Testing localStorage & Persistent UI State with Playwright
A practical guide to ensuring your web app's state persists exactly as users expect — even after they refresh the page.
Ever clicked a "Hide this section" button on a website, only to have it magically reappear after refreshing? That's exactly the kind of bug that drives users crazy — and it's surprisingly common in modern web apps.
Here's the thing: most developers test the happy path (click button → element hides), but they forget to test what happens when users refresh the page. That's where localStorage testing comes in, and honestly, it's one of the most overlooked aspects of end-to-end testing.
In this guide, I'll walk you through exactly how I test persistent UI state using Playwright and TypeScript. We'll cover everything from reading localStorage values with page.evaluate() to ensuring hidden elements stay hidden after a page reload.
This isn't just theory — I'll show you a real-world scenario where we test a mission panel that needs to stay hidden permanently once a user dismisses it. It's the exact type of test you'd write in a professional QA role.
Why This Matters More Than You Think
Picture this: You're building an e-commerce site with a "Don't show this promotion again" button. A user clicks it, continues shopping, then refreshes the page. If that promotion pops back up, you've just lost a potential customer to frustration.
Modern web applications rely heavily on localStorage to remember user preferences, dismissed notifications, collapsed sections, and personalized settings. When this persistence breaks, the user experience falls apart.
What happens when localStorage testing is skipped:
- User frustration: Dismissed elements keep coming back
- Lost personalization: Settings reset on every page load
- Broken workflows: Multi-step processes lose their state
- Support tickets: Users report "bugs" that seem random
- Revenue impact: Poor UX leads to higher bounce rates
The good news? Testing localStorage with Playwright is straightforward once you know the right techniques. Let me show you how I approach it.
What We'll Build Together
I'll walk you through testing a real scenario: a mission panel that users can permanently dismiss. Once they click "Hide this mission," it should stay hidden forever — even if they refresh, close their browser, or come back next week.
Here's our testing roadmap:
- Start with the basics: Automate clicking the dismiss button
- Verify the immediate change: Confirm the element disappears from the DOM
- Check the storage: Use
page.evaluate()to read localStorage values - Test the persistence: Refresh the page and verify the element stays hidden
- Handle edge cases: Use
expect.poll()for reliable async testing - Real-world validation: Test the complete user journey
By the end of this tutorial, you'll have a solid understanding of localStorage testing that you can apply to any web application. Plus, you'll have a great example for your portfolio that shows you understand both UI testing and client-side state management.
The Secret Sauce: Reading localStorage
Here's where things get interesting. Most testers only check if an element is visible or hidden, but they never verify that the underlying data was actually saved. That's like checking if a door is closed without confirming it's locked.
Playwright's page.evaluate() method lets us execute JavaScript directly in the browser context, which means we can access localStorage just like the application does:
// Read the localStorage value to confirm it was saved
const storedValue = await page.evaluate(() => {
return localStorage.getItem("mission7PersistentHide");
});
// Verify it contains the expected value
expect(storedValue).toBe("true");This is crucial because sometimes the UI might look correct, but the data isn't actually persisted. By checking both the visual state and the stored data, we catch bugs that would otherwise slip through.
The Complete Test Journey
Let me break down the exact steps we'll automate. This mirrors how a real user would interact with the feature, plus the behind-the-scenes validation that ensures everything works correctly:
Our testing workflow:
- Initial state check: Confirm the mission panel is visible by default
- User action: Click the "Hide this mission" button
- Immediate validation: Verify the element disappears from the UI
- Data verification: Check that localStorage was updated correctly
- Persistence test: Refresh the page to simulate a real user scenario
- Final validation: Confirm the element stays hidden and data persists
This approach catches three types of bugs: UI bugs (element doesn't hide), storage bugs (data isn't saved), and persistence bugs (state doesn't survive page reloads). Most test suites only catch the first one.
Who Is This Tutorial For?
This Playwright testing tutorial is perfect for:
- QA Engineers
- SDETs
- Test Automation Beginners
- JavaScript/TypeScript testers
- Anyone building a Playwright portfolio
- Students preparing for QA or automation interviews
If you're learning Playwright, this is the exact type of test hiring managers expect you to know.
Watch the Full Video
👉 https://youtu.be/scBKNnRScEQ
In the video, I show every step in real time so you can follow along.
Wrapping Up
localStorage testing might seem like a small detail, but it's these details that separate good testers from great ones. When you can confidently say "I've verified that user preferences persist across sessions," you're demonstrating a level of thoroughness that employers value.
The techniques we've covered here — using page.evaluate(), expect.poll(), and testing persistence across page reloads — are applicable to any web application that uses client-side storage.
💼 Portfolio tip:
This type of test makes an excellent addition to your GitHub portfolio. It shows you understand:
- End-to-end user workflows
- Client-side state management
- Async testing patterns
- Real-world edge cases
Remember, great testing isn't just about finding bugs — it's about building confidence that your application works exactly as users expect, even in scenarios they might not think to test.
Questions about localStorage testing or Playwright in general? I'm always happy to help fellow testers level up their automation skills. Feel free to reach out!