DEV Community

Styrow.dev
Styrow.dev

Posted on Originally published at styrow.dev

How do you manage and assert complex page state across multiple test runs or components in Playwright without relying so

🤯 Playwright State Management Nightmare?
How do you assert and manage complex UI state across test runs without just using APIs or BrowserContext.storageState()?


📌 Problem Statement

Testing UIs that rely on dynamic, custom-structured local storage data or intricate session objects presents a unique challenge. Standard Playwright state persistence often falls short, impacting test repeatability and isolation for deeply nested application-specific states.

💡 Solution & Code Walkthrough

The core challenge is maintaining test isolation while achieving state persistence for non-standard UI data.

• The BrowserContext.storageState() Trade-Off:
✅ Excellent for quick persistence of standard browser state (cookies, basic localStorage key/values, sessionStorage).
❌ Limited if application state relies on complex internal memory structures or custom JavaScript objects, not just simple key-value pairs.

• Custom Granular Mechanism (The Playwright Power-Up):
For complex UI states (e.g., a JavaScript object stored as a string in localStorage), we leverage Playwright's page.evaluate() API. This allows direct execution of JavaScript within the browser context to serialize, inject, retrieve, and deserialize your complex data.

import { test, expect } from '@playwright/test';

test('validates complex user preferences saved in localStorage', async ({ page }) => {
  // 1. Serialize & Inject Complex UI State BEFORE navigation
  const complexAppState = {
    user: { id: 'USR-789', settings: { theme: 'dark', notifications: true } },
    cart: { items: [], total: 0, currency: 'USD' }
  };
  await page.evaluate((state) => {
    localStorage.setItem('appData', JSON.stringify(state));
  }, complexAppState); // Pass JS object directly to evaluate

  await page.goto('/dashboard'); // Navigate after state is set

  // 2. Interact with UI / Perform actions (optional)
  // await page.locator('button', { hasText: 'Edit Profile' }).click();

  // 3. Deserialize & Assert UI or Backend State
  const retrievedState = await page.evaluate(() => {
    const data = localStorage.getItem('appData');
    return data ? JSON.parse(data) : {};
  });

  // ✅ Assert deeply nested structure for correctness
  expect(retrievedState.user.settings.theme).toBe('dark');
  expect(retrievedState.cart.total).toBe(0);
  expect(retrievedState.cart.currency).toBe('USD');

  // X Avoid brittle selectors that break on minor UI changes.
  // ✅ Focus on asserting the underlying state or visible effects.
});
Enter fullscreen mode Exit fullscreen mode

• Key Implementation Strategy:

  1. Serialization: Use JSON.stringify() to convert your complex JavaScript object into a string.
  2. Injection: Use await page.evaluate(jsFunction, dataToPass) to execute JavaScript that sets this string in localStorage (or sessionStorage). This should often happen before page.goto() to ensure the app loads with the desired state.
  3. Retrieval & Deserialization: Use another page.evaluate() call to get the string from localStorage and JSON.parse() it back into an object for assertions.
  4. Isolation: Each test sets up its own state, ensuring tests are independent.

🔑 Key Takeaways

• BrowserContext.storageState(): Best for simple, browser-level state like cookies.
• page.evaluate(): Essential for manipulating complex, application-specific JavaScript objects in localStorage or sessionStorage.
• JSON.stringify() / JSON.parse(): Your tools for reliable data interchange between Playwright's Node.js context and the browser's JavaScript context.
• This approach ensures strong test isolation and repeatability for even the most intricate UI state scenarios.

❓ Quick Summary Q&A

• Q: When should I use BrowserContext.storageState()?
A: For persisting standard browser state like authentication cookies or simple localStorage key-value pairs.
• Q: When is page.evaluate() necessary for state management?
A: When dealing with complex JavaScript objects stored in localStorage, non-standard session data, or needing to execute arbitrary JS in the browser.

TAGS: playwright, testing, automation, javascript, web testing, state management, e2e, frontend testing

────────────────────────────────────────
Enhance your coding skills on the go!
────────────────────────────────────────

📲 𝐅𝐑𝐄𝐄 𝐌𝐎𝐁𝐈𝐋𝐄 𝐀𝐏𝐏 — 𝟔𝟎𝟎+ 𝐒𝐃𝐄𝐓 𝐐&𝐀𝐬
Practice real-world interview scenarios offline on the free QA Automation & SDET Prep app:

🤖 𝐆𝐨𝐨𝐠𝐥𝐞 𝐏𝐥𝐚𝐲 (𝐀𝐧𝐝𝐫𝐨𝐢𝐝):
https://play.google.com/store/apps/details?id=com.app.seleniuminterviewquestions&referrer=utm_source%3Ddevto%26utm_medium%3Darticle%26utm_campaign%3Dselenium_20260921

🍎 𝐀𝐩𝐩 𝐒𝐭𝐨𝐫𝐞 (𝐢𝐎𝐒):
https://apps.apple.com/app/id6786760948?pt=128640464&ct=devto_selenium_20260921&mt=8

────────────────────────────────────────
────────────────────────────────────────

Top comments (0)