1.5.1 • Published 6 months ago

cypress-performance v1.5.1

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

Concept

The cypress-performance plugin introduces a powerful way to measure and assert on web performance metrics directly in your Cypress tests. Unlike traditional end-to-end testing that focuses on functionality, this plugin enables teams to catch performance regressions early and maintain high performance standards through automated testing.

This plugin does not have external dependencies.

Comparison with @cypress-audit/lighthouse

Both plugins focus on performance testing, but they serve different purposes:

cypress-performance

  • Real-time metrics during test execution
  • Lower overhead - no need for separate Lighthouse runs
  • Less configuration - minimal setup required for basic usage
  • Specific metric focus - Core Web Vitals and key timings
  • Test integration - natural fit in existing test flows
  • Retry capability - built-in retriability mechanisms to ensure the metrics are collected
  • Resource timing - detailed resource-level metrics
  • Total bytes - size of all resources
  • Time to first byte - detailed time to first byte metrics
  • Network throttling - support for throttling network conditions with presets or custom options

@cypress-audit/lighthouse

  • Comprehensive audits including SEO, accessibility
  • Scoring system aligned with Lighthouse
  • Static analysis of best practices
  • Recommendations for improvements
  • Performance simulation under various conditions
  • Broader metrics beyond just performance

Key Features

  • Real-time performance metrics collection during test execution
  • Built-in retry mechanisms for reliable measurements
  • Support for Core Web Vitals and other key performance indicators
  • Seamless integration with existing Cypress tests
  • Type definitions for TypeScript support
  • Configurable thresholds and timing options
  • Support for throttling network conditions with presets or custom options
The "cy.performance" command provided by the plugin is chainable and returns the object containing the collected performance metrics:
  PerformanceMetrics {
      pageloadTiming: number
      domCompleteTiming: number | null
      resourceTiming: (resource: string) => PerformanceResourceTiming | undefined
      largestContentfulPaint: number
      totalBlockingTime: number
      paint: { firstContentfulPaint: number; firstPaint: number }
      cumulativeLayoutShift: number
      totalBytes: number
      timeToFirstByte: {
        total: number
        redirect: number
        dns: number
        connection: number
        tls: number
        wait: number
      }
    }
The "cy.setNetworkConditions" command provided by the plugin accepts the name of a network condition preset or custom options and applies it to the current test run.

Available Presets:

  • REGULAR_4G
  • SLOW_3G
  • FAST_3G
  • FAST_WIFI
  cy.setNetworkConditions('FAST_WIFI');
  // or custom options
  cy.setNetworkConditions({
    downloadThroughput: 32768, // 32KB/s
    uploadThroughput: 16384,   // 16KB/s
    latency: 200              // 200ms
  })
The "cy.resetNetworkConditions" command provided by the plugin resets the network conditions to their default values.

This command normally should be placed at the end of the test suite or in the after hook to ensure that the network conditions are reset to their default values after each test.

Available Metrics

MetricDescriptionTypical Threshold
largestContentfulPaintTime until largest content element is visible< 2500ms
totalBlockingTimeSum of blocking time for long tasks< 300ms
cumulativeLayoutShiftMeasure of visual stability< 0.1
paint.firstContentfulPaintTime until first meaningful content appears< 1800ms
paint.firstPaintTime until first pixel is painted< 1000ms
pageloadTimingTotal page load time< 3000ms
domCompleteTimingTime until DOM is fully loaded< 2500ms
resourceTimingTime until resource is fully loaded< 500ms
totalBytesSize of all resources< 1.5 MB
timeToFirstByte.totalTime to first byte< 500ms
timeToFirstByte.dnsDNS time< 20ms
timeToFirstByte.waitWait time< 50ms
timeToFirstByte.redirectRedirect time< 50ms
timeToFirstByte.tlsTLS time< 50ms
timeToFirstByte.connectionConnection time< 50ms

Install

First things first, there's always something before you can start.

To make our life easier, we use NPM a lot. Make sure you have it installed.

Add this package as a dev dependency:

$ npm i -D cypress-performance
# or using Yarn
$ yarn add -D cypress-performance

Include this package in your spec or support file to use all custom query commands

import 'cypress-performance'

API

Usage

Known issues

  • It is recommended to wait for the complete page load before using the performance command.
  1. cy.setNetworkConditions doesn't work properly in headed mode (only the first test run with the emulated network conditions). It works fine in headless mode using npx cypress run command.

Default options for the command cy.performance():

    MetricsOptions{
      startMark?: keyof PerformanceTiming // Default: 'navigationStart'
      endMark?: keyof PerformanceTiming // Default: 'loadEventEnd'
      timeout?: number // Timeout in milliseconds (default: 10000)
      initialDelay?: number // Initial delay in milliseconds (default: 1000)
      retryTimeout?: number // Retry timeout in milliseconds (default: 5000)
    }

Possible options for the command cy.setNetworkConditions():

Presets:

  • REGULAR_4G - 4 Mbps
  • SLOW_3G - 500 Kbps
  • FAST_3G - 1.5 Mbps
  • FAST_WIFI - 400 Mbps

Options:

NetworkConditions {
  offline: boolean
  downloadThroughput: number // bits per second
  uploadThroughput: number // bits per second
  latency: number // milliseconds
}

Usage example:

     // with custom options values
     cy.visit('https://example.com');
     cy.performance({ startMark: 'navigationStart', endMark: 'loadEventEnd', timeout: 10000, initialDelay: 1000, retryTimeout: 5000 })
       .then(results => {
         expect(results.pageloadTiming).to.be.lessThan(2000);
         expect(results.domCompleteTiming).to.be.lessThan(2000);
         const logoResourceTiming = results.resourceTiming('.svg');
         expect(logoResourceTiming.duration, 'Resource timing is less than 500ms').to.be.lessThan(500);
         expect(results.totalBytes, 'Total bytes is less than 500kb').to.be.lessThan(500000);
       });

    // or with default options values

     cy.visit('https://example.com').performance().then(results => { // the command is chainable
       expect(results.largestContentfulPaint).to.be.lessThan(500);
       expect(results.totalBlockingTime).to.be.lessThan(500);
       expect(results.paint.firstContentfulPaint).to.be.lessThan(500);
       expect(results.paint.firstPaint).to.be.lessThan(500);
       expect(results.cumulativeLayoutShift).to.be.lessThan(0.1);
       expect(metrics.timeToFirstByte.total, 'Time to first byte is less than 500ms').to.be.lessThan(500);
       expect(metrics.timeToFirstByte.dns, 'DNS time is less than 20ms').to.be.lessThan(20);
       expect(metrics.timeToFirstByte.wait, 'Wait time is less than 50ms').to.be.lessThan(50);
       expect(metrics.timeToFirstByte.redirect, 'Redirect time is less than 50ms').to.be.lessThan(50);
       expect(metrics.timeToFirstByte.tls, 'TLS time is less than 50ms').to.be.lessThan(50);
       expect(metrics.timeToFirstByte.connection, 'Connection time is less than 50ms').to.be.lessThan(50);
     });

    it(`using preset SLOW_3G`, () => {
      // Using setNetworkConditions should be called first before navigating to the page
      cy.setNetworkConditions('SLOW_3G')
      cy.visit(url)
      cy.performance().then((metrics) => {
        expect(metrics.pageloadTiming).to.be.greaterThan(12000)
        expect(metrics.domCompleteTiming).to.be.greaterThan(12000)
      })
      cy.resetNetworkConditions()
  })

Command Retryability

The cy.performance() command implements two levels of reliability:

  1. Command Level Retry
    • Built into Cypress's command chain
    • Retries until valid metrics are available
    • Configurable via retryTimeout
    • Handles race conditions and timing issues
  2. Measurement Reliability
    • Initial delay ensures stable measurements
    • Buffered performance entries capture early events
    • Multiple samples for metrics like CLS
    • Automatic fallbacks for missing metrics

Types

This package includes TypeScript command definitions for its custom commands in the file src/commands/performance.d.ts. To use it from your JavaScript specs:

/// <reference types="cypress-performance" />

If you are using TypeScript, include this module in your types list

{
  "compilerOptions": {
    "types": ["cypress", "cypress-performance"]
  }
}

Contributions

Contributions are welcome! To contribute:

1.Fork the repository.

2.Create a feature branch:

  git checkout -b feature/your-feature-name

3.Commit your changes and push:

  git commit -m "Add new feature"
  git push origin feature/your-feature-name

4.Open a pull request:

5. License

This project is licensed under the MIT License.

6. Feedback

If you encounter any issues or have suggestions, please open an issue on GitHub.

1.5.1

6 months ago

1.5.0

6 months ago

1.4.0

6 months ago

1.2.0

6 months ago

1.1.0

6 months ago

1.3.0

6 months ago

1.0.0

7 months ago