Why Your Checkout Dies When Intercom is Down
(and How to Fix It)
The silent killer of performance: Unmanaged Third-Party Scripts.
The Problem: The "External" Trap πΈοΈ
Modern web apps are 20% your code and 80% other people's code (Analytics, Chat, Pixels). We assume these giants never fail. But when they hang, they can block your entire application from rendering.
Standard App
- Dependency:Hangs (Timeout)
- Strategy:Tightly Coupled
- UX:β³ White Screen
Resilient App
- Dependency:Hangs (Timeout)
- Strategy:Isolated / Async
- UX:β App Interactive
Under the Hood: Why it breaks?
It's not just about document.write. Even with async tags, third-party scripts utilize the Main Thread for parsing and execution. In modern frameworks (React/Next.js), if a widget fails to initialize during hydration or throws an unhandled exception, it can crash the entire Component Tree, leaving your user with a blank page.
The Solution: The "Bouncer" (Domain Blocking)
Don't test with a perfect internet
In your Dev environment, Google and Facebook are always up. You never see what happens when they hang.
RECOMMENDED: Do use Domain Blackholing
Intentionally "kill" your vendors during the test. Block traffic to specific domains (like *.google-analytics.com or *.intercom.io) and verify that your Critical Path (Login -> Checkout) still functions perfectly without them.
The Code (Python + Playwright)
Note: The logic below is identical for Playwright Node.js/TypeScript.
def test_chaos_dependency_hang(page):
# 1. Define the "Vampire" Dependencies
# Domains that must NOT crash the app if they fail.
vampires = [
"**/*google-analytics.com*",
"**/*intercom.io*",
"**/*facebook.net*"
]
# 2. πͺ INJECT CHAOS: The Black Hole
# We abort requests immediately to simulate a DNS failure or Server Down.
# Pro Tip: Use route.fulfill(status=200, body="") if your app
# throws Uncaught Exceptions on network errors.
for vampire in vampires:
page.route(vampire, lambda route: route.abort())
# 3. Verify Vital Signs
try:
page.goto("/checkout", timeout=5000) # Strict 5s timeout
except Exception:
assert False, "π¨ App crashed because a 3rd party was blocked!"
# 4. Success Condition
# Chat widget is GONE, but Checkout Button is VISIBLE.
expect(page.locator("#intercom-frame")).not_to_be_visible()
expect(page.locator("#pay-button")).to_be_visible()But what about Mobile Apps?
On iOS/Android, native SDKs (like Facebook Login) often initialize synchronously on the Main Thread. If they can't phone home on launch, the OS "Watchdog" kills your app immediately (ANR/Crash).
Debuggo lets you block these domains at the System Proxy level on real physical devices to catch these crashes.
No setup required
Why this matters
Your SLA is only as good as your worst dependency.This test forces developers to wrap external calls in error boundaries and ensures that 3rd party failures act as "Graceful Degradation" rather than "Catastrophic Failure".