Search code examples
typescriptperformancetestingcypressplaywright

Cannot use PerformanceObserver in Cypress


Is the a way to use the PerformanceObserver in Cypress? For me, it does not seem to fire.

I have done it in playwright

const { chromium } = require('playwright')

(async () => {
  const browser = await chromium.launch()
  const page = await browser.newPage()
  await page.goto('website')

  const totalBlockingTime = await page.evaluate(() => {
    return new Promise((resolve) => {
      let totalBlockingTime = 0
      new PerformanceObserver(function (list) {
        const perfEntries = list.getEntries()
        for (const perfEntry of perfEntries) {
          totalBlockingTime += perfEntry.duration - 50
        }
        resolve(totalBlockingTime)
      }).observe({ type: 'longtask', buffered: true })

      // Resolve promise if there haven't been long tasks
      setTimeout(() => resolve(totalBlockingTime), 5000)
    })
  })

  console.log(parseFloat(totalBlockingTime)) // 0

  await browser.close()
})()

Here is what I tried but it does not seem to fire

let totalBlockingTime = 1;
cy.window().then((win) => {
  const o = new win.PerformanceObserver((list) => {
    const entries = list.getEntries();
    entries.forEach((entry) => {
      if (entry.entryType === "longtask") {
        totalBlockingTime += entry.duration;
      }
    });
  });
  o.observe({
    entryTypes: ["longtask"],
    buffered: true,
  });
});


Solution

  • I think the code you have is basically correct, but the timing of adding the observer is critical with Cypress.

    Ideally, you want to add it just after the test runner has set up the window and is about to load the page, so onBeforeLoad event.

    I don't know much about longtask, except it's marked experimental, but here is a proof-of-concept test that uses the mark and measure

    cy.visit("http://example.com", {
      onBeforeLoad: (win) => {
        const o = new win.PerformanceObserver((list) => {
          list.getEntries().forEach(entry => {
            console.log("Name: "       + entry.name      +
                        ", Type: "     + entry.entryType +
                        ", Start: "    + entry.startTime +
                        ", Duration: " + entry.duration  + "\n");
          })
        });
        o.observe({
          entryTypes: ['measure', 'mark', 'longtask'],
          // buffered: true,                           // see note
        });
        win.performance.mark('registered-observer')    // issue mark
      },
    })
      
    cy.wait(1000)                 // vary this wait to see performance duration change
    
    cy.window().then(win => {
      console.log('measuring...')
      win.performance.measure('after waiting');
    })
    

    Note

    The buffer:true entry throws a warning

    The PerformanceObserver does not support buffered flag with the entryTypes argument.

    enter image description here

    Console log

    Name: registered-observer, Type: mark, Start: 48.900000005960464, Duration: 0
    
    measuring...
    Name: after waiting, Type: measure, Start: 0, Duration: 1093.199999988079
    
    Name: same-origin-ancestor, Type: longtask, Start: 1103.800000011921, Duration: 98