π₯ SDET Interview Scenario of the Day:
How do you measure and assert Core Web Vitals (FCP, LCP) inside a Playwright E2E test without flaky timing?
π Problem Statement
β’ Core Web Vitals reveal realβuser performance but are hidden inside the browser.
β’ NaΓ―ve page.waitForTimeout() or relying on domcontentloaded misses paint events.
β’ β Relying on arbitrary delays leads to flaky tests and false regressions.
π‘ Solution & Code Walkthrough
β
Use a PerformanceObserver injected via page.evaluate() to capture FCP and LCP as they fire.
β
Collect metrics into a global variable, then read them after navigation.
β
Assert against thresholds with Playwrightβs expect.
// performanceUtils.ts
import { Page, expect } from '@playwright/test';
export async function collectCoreVitals(page: Page): Promise<{ fcp: number; lcp: number }> {
// Inject observer before navigation
await page.addInitScript(() => {
const vitals: { fcp?: number; lcp?: number } = {};
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.name === 'first-contentful-paint') vitals.fcp = entry.startTime;
if (entry.name === 'largest-contentful-paint') vitals.lcp = entry.startTime;
}
}).observe({ entryTypes: ['paint'] });
// expose for test
(window as any).__VITALS__ = vitals;
});
// Navigate to target page
await page.goto('https://example.com');
// Retrieve metrics
const vitals = await page.evaluate(() => (window as any).__VITALS__);
expect(vitals.fcp).toBeLessThan(2000); // 2s threshold example
expect(vitals.lcp).toBeLessThan(2500);
return { fcp: vitals.fcp!, lcp: vitals.lcp! };
}
π Key Takeaways
β’ Inject observer before navigation to catch early paints.
β’ Use addInitScript or page.evaluate() to run once per context.
β’ β
Assert with realistic thresholds; adjust perβproject.
β’ β Avoid waitForTimeout β it hides real performance issues.
β Quick Summary Q&A
Q: Do I need to wait for networkidle?
A: No. The observer captures paint events independently of network state.
Q: Can I collect CLS or TTFB?
A: Yes β extend the observer with layout-shift and navigation entry types.
Q: Is this reliable across browsers?
A: Playwright uses the same Chromium/WebKit/Firefox APIs; the observer works in all supported browsers.
TAGS: playwright, typescript, web-vitals, performance-testing
ββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββ
π² π
πππ ππππππ πππ β πππ+ ππππ π&ππ¬
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_20261002
π ππ©π© πππ¨π«π (π’ππ):
https://apps.apple.com/app/id6786760948?pt=128640464&ct=devto_selenium_20261002&mt=8
ββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββ
Top comments (0)