DEV Community

Osibajo Inioluwa
Osibajo Inioluwa

Posted on

What Automated Slow-3G Testing Reveals About Frontend Assumptions

What Automated Slow‑3G Testing Reveals About Frontend Assumptions

Testing in a clean CI pipeline gives you green checks, but it also gives you a false sense of security. When I throttled my app to a real‑world slow‑3G connection, I uncovered race conditions and asset‑loading failures that never appeared in synthetic benchmarks. Below is a short guide to reproducing those findings and a few concrete patterns you’ll likely run into.


Why the default CI setup lies

  • CI runners run on fast, wired networks.
  • Most test frameworks assume instant responses when they mock APIs or serve static assets from a local server.
  • The browser’s networking stack is rarely exercised under realistic latency and bandwidth constraints.

The result? Code that works in CI can break for users on a congested mobile network.


Adding real‑world throttling to your test suite

1. Cypress + Chrome DevTools Protocol

// cypress/plugins/index.js
module.exports = (on, config) => {
  on('before:browser:launch', (browser = {}, launchOptions) => {
    if (browser.name === 'chrome') {
      launchOptions.args.push(
        '--disable-features=NetworkService',
        '--disable-features=NetworkServiceInProcess',
        '--network-emulation',
        '--netem',
        '--latency=200',            // 200 ms RTT
        '--download=400',           // 400 kbps down
        '--upload=200'              // 200 kbps up
      );
    }
    return launchOptions;
  });
};
Enter fullscreen mode Exit fullscreen mode
  • The flags above emulate the “Slow 3G” profile used by Chrome DevTools.
  • Run cypress run as usual; the browser now respects those limits.

2. Playwright’s built‑in throttling

// tests/slow3g.spec.ts
import { test, expect } from '@playwright/test';

test.use({
  // Emulate the official "Slow 3G" preset
  viewport: { width: 375, height: 667 },
  network: {
    offline: false,
    download: 500 * 1024,   // 500 KB/s
    upload: 500 * 1024,
    latency: 400,           // ms
  },
});

test('home page loads critical assets', async ({ page }) => {
  await page.goto('https://myapp.example');
  await expect(page.locator('img.logo')).toBeVisible();
});
Enter fullscreen mode Exit fullscreen mode

Playwright applies the throttling automatically, so you don’t need extra CLI flags.


What actually broke

Symptom Why it’s easy to miss in CI Fix
Image flicker / placeholder Images load instantly from localhost, so onload fires before layout calculations. Add a fallback CSS rule that hides the element until naturalWidth > 0.
Missing analytics ping Mocked XHR resolves instantly; the sendBeacon call is dropped when the network is congested. Queue the beacon and retry with exponential back‑off.
Stale UI after race condition Two parallel fetches resolve in order on fast connections, but the slower one overwrites newer data on 3G. Use a version token (e.g., ETag) and discard responses older than the latest request.
CSS‑in‑JS injection delay Inline style injection runs after component mount; on slow networks the component renders before the style arrives, causing a flash of unstyled content. Insert a <style> tag synchronously or use requestAnimationFrame to delay mount until styles are ready.

These issues were reproduced consistently across Chrome, Firefox, and Safari when throttled to the “Slow 3G” preset. No synthetic benchmark caught them because they rely on timing assumptions that only hold on high‑speed links.


Takeaway

  • Never trust passing tests alone. Add a “slow‑network” job to your CI pipeline and treat failures as real regressions.
  • Instrument your code for network variability. Explicitly handle out‑of‑order responses, timeouts, and asset‑load failures.
  • Run a sanity check on production‑like hardware. Even a cheap Android device on a 3G hotspot can surface bugs that a desktop VM never will.

If you haven’t yet added network throttling to your automated suite, start with the snippets above. In my experience, a single nightly “slow‑3G” run catches more bugs than a full suite of unit tests.

Source: I throttled my app to slow 3G – here’s what my tests never caught

Top comments (0)