supaguardsupaguardDocs
Playwright

Network Mocking & Interception

Use Playwright's network interception to isolate your monitors from third-party flakes, simulate errors, and test edge cases without real API calls.

Synthetic monitoring is often victim to "Third-Party Flakiness." If an analytics script or a non-critical chat widget fails, you don't want your Critical Alert to fire. Playwright's page.route() allows you to intercept, modify, or block network requests to ensure your monitors focus on what matters.

Blocking Unnecessary Requests

To speed up your checks and reduce noise, you can block non-essential scripts like Google Analytics or Intercom.

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

test.beforeEach(async ({ page }) => {
  // Block analytics and ads
  await page.route('**/*.{google-analytics.com,googletagmanager.com}/**', route => route.abort());
});

Mocking API Responses

If you want to monitor a specific UI state (like an "Empty State" or an "Account Expired" banner) without actually modifying your production data, you can mock the API response.

test('displays empty state when no projects exist', async ({ page }) => {
  // Intercept the projects API and return an empty array
  await page.route('**/api/projects', async route => {
    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify([])
    });
  });

  await page.goto('/dashboard');
  await expect(page.getByText('No projects found')).toBeVisible();
});

Simulating Edge Cases

1. Slow API Responses

Test how your application handles high latency. Does it show a loading spinner or just a blank screen?

await page.route('**/api/data', async route => {
  await new Promise(f => setTimeout(f, 5000)); // Delay 5 seconds
  await route.continue();
});

2. API Errors (500 Internal Server Error)

Ensure your app shows a graceful error message to users instead of crashing.

await page.route('**/api/user/profile', route => {
  route.fulfill({
    status: 500,
    body: 'Internal Server Error'
  });
});

Modifying Requests/Responses

Sometimes you want the real data, but with one small tweak for testing purposes.

await page.route('**/api/user', async route => {
  const response = await route.fetch();
  const json = await response.json();
  
  // Inject a 'Pro' flag to test the premium UI
  json.isPro = true;
  
  await route.fulfill({ response, json });
});

Best Practices

  • Isolate the Cause: Use mocking to determine if a failure is caused by your frontend logic or a flaky backend dependency.
  • Don't Mock Everything: In synthetic monitoring, you usually want to test the real production API. Save heavy mocking for specialized "UI-only" checks.
  • Use routeFromHAR: For complex scenarios, you can record a "Happy Path" and replay it to ensure the UI behaves consistently.

Next Steps

On this page