DEV Community

Styrow.dev
Styrow.dev

Posted on Originally published at styrow.dev

Designing E2E Validation for Highly Dynamic Dashboards with N Asynchronous Widgets

🤯 Playwright Hard Mode: Testing Dynamic Dashboards with N Async Widgets!
Imagine an analytics dashboard with 50+ independent widgets, each fetching and updating data asynchronously. How do you reliably test global filter changes?

📌 Problem Statement
Testing dashboards with N independent, async-loading widgets is a core E2E challenge. A global filter triggers all N widgets to concurrently re-fetch and update. We need a robust Playwright strategy to:
• Apply filter efficiently.
• Wait for all widgets to load.
• Verify all display correct, filtered data.
• Ensure resilience against UI transients.

💡 Solution & Code Walkthrough
The core is Promise.all for parallel waiting and robust data-testid locators for targeting.

✅ 1. Apply Global Filter
This is a standard Playwright interaction.

await page.getByRole('button', { name: 'Apply Filter' }).click();
Enter fullscreen mode Exit fullscreen mode

✅ 2. Efficiently Wait for All Widgets
Identify a "ready" state for each widget (e.g., loading spinners hidden, data content visible).

async function waitForAllWidgets(page) {
  const spinners = await page.locator('[data-testid$="-spinner"]').all();
  await Promise.all(
    spinners.map(s => s.waitFor({ state: 'hidden', timeout: 30000 }))
  );
  // Optional: wait for data areas to be visible if no spinner
  // const dataAreas = await page.locator('[data-testid$="-data"]').all();
  // await Promise.all(dataAreas.map(d => d.waitFor({ state: 'visible' })));
}
// Usage: await waitForAllWidgets(page);
Enter fullscreen mode Exit fullscreen mode

❌ Avoid: page.waitForTimeout() or waiting for only one widget. These lead to flakiness.

✅ 3. Validate All Widgets' Data
Iterate through each widget container and assert its content based on the applied filter.

async function validateAllWidgets(page, expectedValue) {
  const widgets = await page.locator('[data-testid^="widget-card-"]').all();
  for (const widget of widgets) {
    await expect(widget.locator('.widget-title')).toHaveText(
      expect.stringContaining(expectedValue)
    );
    // Add more granular assertions per widget if needed (e.g., table data)
  }
}
// Usage: await validateAllWidgets(page, 'Q4 2023');
Enter fullscreen mode Exit fullscreen mode

🔑 Key Takeaways
• Promise.all is crucial for concurrent, efficient waiting for N asynchronous UI updates.
• Robust data-testid locators prevent flakiness and enable precise targeting.
• Granular, widget-specific waits and validations ensure full UI state correctness.
• Playwright's auto-waiting combined with explicit waitFor() handles most race conditions.

❓ Quick Summary Q&A
Q: How to wait for N async widgets to load?
A: Use Promise.all with locator.waitFor({ state: 'hidden' }) on loading indicators.
Q: How to validate N widgets' data?
A: Iterate through widget containers (using all()) and apply expect().toHaveText() assertions for each.
Q: What's the best locator strategy for dynamic UIs?
A: data-testid attributes are ideal for stability and readability.

TAGS: playwright, e2e testing, automation, web testing, async ui, javascript, typescript

────────────────────────────────────────
Level up your testing skills on the go! Download our app:
App Store: ────────────────────────────────────────

📲 𝐅𝐑𝐄𝐄 𝐌𝐎𝐁𝐈𝐋𝐄 𝐀𝐏𝐏 — 𝟔𝟎𝟎+ 𝐒𝐃𝐄𝐓 𝐐&𝐀𝐬
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_20261001

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

────────────────────────────────────────
Play Store: ────────────────────────────────────────

📲 𝐅𝐑𝐄𝐄 𝐌𝐎𝐁𝐈𝐋𝐄 𝐀𝐏𝐏 — 𝟔𝟎𝟎+ 𝐒𝐃𝐄𝐓 𝐐&𝐀𝐬
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_20261001

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

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

Top comments (0)