cypress-visited-urls
TypeScript icon, indicating that this package has built-in type declarations

2.1.5 • Public • Published

cypress-visited-urls

A plugin to collect all visited urls across all specs

Learn more

Install

Add this plugin as a dev dependency

# using NPM
$ npm i -D cypress-visited-urls
# using Yarn
$ yarn add -D cypress-visited-urls

Include in the E2E support file

// cypress/support/e2e.js

// https://glebbahmutov.com/blog/collect-tested-urls/
import { configureVisitedUrls } from 'cypress-visited-urls'

configureVisitedUrls()

Note: since the component specs do not visit meaningful URLs, we only configure this plugin in the E2E tests.

Include in the plugins file

// cypress.config.mjs

// https://github.com/bahmutov/cypress-visited-urls
import visitedUrlsPlugin from 'cypress-visited-urls/src/plugin'
export default defineConfig({
  e2e: {
    env: {
      visitedUrls: {
        // collect each URL the test runner visits
        // https://glebbahmutov.com/blog/collect-tested-urls/
        collect: true,
        urlsFilename: 'cypress-visited-urls.json',
      },
    },
    setupNodeEvents(on, config) {
      visitedUrlsPlugin(on, config)
      // IMPORTANT to return the config object
      // with the any changed environment variables
      return config
    }
  },
})

Run in the collection mode

If you are using collect: true in the Cypress config file, you can turn the collection via environment variable by looking at the environment

e2e: {
  // baseUrl, etc
  env: {
    visitedUrls: {
      // by default, do not collect any URLS
      collect: false,
    },
  },

  setupNodeEvents(on, config) {
    // only collect visited URLs on CI
    if (process.env.CI) {
      console.log('setting to collect visited urls on CI')
      config.env.visitedUrls.collect = true
    }
    cypressVisitedUrls(on, config)
    // return the config object
    return config
  },
},

Features

The saved JSON file will have information for each spec and test. For each test, it saves a list of visited pages sorted by the total time spent on the page. Each test also counts how many Cypress commands were executed at that page. See cypress-visited-urls.json for example.

{
  "cypress/e2e/about.cy.js": {
    "The about page / does something else": [],
    "The about page / goes using the link": [
      {
        "url": "/public/index.html",
        "duration": 136,
        "commandsCount": 6
      },
      {
        "url": "/public/about.html",
        "duration": 54,
        "commandsCount": 2
      }
    ]
  }
}

Specs and test titles are sorted alphabetically. Durations are only updated if the difference with the previous value is > 500ms.

filterUrl

Often the visited URLs have dynamic or random parts to them. To "normalize" the URLs before saving them you can pass your own filterUrl function to the plugin via config function.

// cypress/support/e2e.js

// https://glebbahmutov.com/blog/collect-tested-urls/
import { configureVisitedUrls } from 'cypress-visited-urls'

configureVisitedUrls({
  filterUrl(url) {
    // remove all query parameters
    return url.split('?')[0]
  },
})

The returned URL will be stored in the JSON file. If you return a falsy value, the URL won't be added.

preSaveFilterUrls

Once the test finishes and the plugin prepares to save the updated visited URLs file, you can prefilter / modify all URLs for the current test. You are given a list of urls + durations and should return filtered / modified list.

// cypress/support/e2e.js

// https://glebbahmutov.com/blog/collect-tested-urls/
import { configureVisitedUrls } from 'cypress-visited-urls'

configureVisitedUrls({
  // currentUrls and previousUrls are two arrays
  // with the current test run and the previously saved URLs for this test
  // currentUrls: {url: string, duration: number}[]
  // previousUrls: {url: string, duration: number}[]
  // specName: string relative spec name
  // testName: string full test title
  preSaveFilterUrls(currentUrls, previousUrls, specName, testName) {
    // remove all urls that point at the /?callback_ for example
    // and are not in the previously saved list
    return currentUrls.filter(
      ({ url, duration }) =>
        url.startsWith('/?callback_') && previousUrls.includes(url),
    )
  },
})

test events

You can send custom events to be stored with the test information using the static method call

Cypress.addVisitedTestEvent({
  label: 'string event name',
  data: {}, // any serializable object or a string or a number
})

Note: duplicate events will be skipped, but the count will be incremented

Cypress.addVisitedTestEvent({
  label: 'user info',
  data: {
    name: 'Joe',
  },
})
// some time later
Cypress.addVisitedTestEvent({
  label: 'user info',
  data: {
    name: 'Joe',
  },
})
// only a single event "user info" with the { name: 'Joe' } is stored

Find specs

You can find all specs with tests that visit a particular URL using partial string match

$ npx find-specs-by-url -f cypress-visited-urls.json -u index.html
# prints the list of comma-separated specs filenames

For example, run npm run demo-find command in this repo.

You can feed this list to Cypress

$ npx cypress run --spec $(npx find-specs-by-url -f cypress-visited-urls.json -u about.html)
# runs a single spec in this repo

sort by the number of commands

By default, this plugin keep track of how many Cypress commands executed on each page. The list of found specs that visit a specific page is sorted by the total number of commands executed on that page by all tests in that spec. You can be explicit:

$ npx find-specs-by-url -f cypress-visited-urls.json -u about.html --metric commands

sort by duration

This plugin keeps track of how long each test spends on every URL, and you can see found specs are sorted by the total duration spent on the page:

$ npx find-specs-by-url -f cypress-visited-urls.json -u about.html --metric duration

Tip: I suggest using the commands counts as a better metric for deciding which test covers the page. For example, the following test spends a long time on the page, yet simply executes one command there:

cy.visit('/about')
cy.wait(10_000)

The second test spends less time on the About page, but at least it verifies some elements

cy.visit('/about')
cy.get('body.loaded')
cy.contains('h1', 'About')
cy.title().should('equal', 'About us')

cutoff

You can filter out all specs where the metric is below a cutoff threshold. For example, to only consider the specs that spend 100ms or longer at the /about page

# duration cutoff, ms
$ npx find-specs-by-url -f cypress-visited-urls.json -u '/about' --metric duration --cutoff 100
# commands cutoff, at least 10 commands on the About page
$ npx find-specs-by-url -f cypress-visited-urls.json -u '/about' --cutoff 10

n

You can keep just the first N specs using the -n <number> argument

# first 5 specs with at least 10 commands on the About page
$ npx find-specs-by-url -f cypress-visited-urls.json -u '/about' --cutoff 10 -n 5

set GitHub Actions outputs

Add flag --set-gha-outputs to save the list of found specs and their number in the outputs visitedSpecs and visitedSpecsN

output CLI table

You can add --table CLI argument to print the found specs together with the totals. For example, to see found specs sorted by commands:

$ npx find-specs-by-url -f cypress-visited-urls.json -u about.html --table

=== Specs testing page "about.html" sorted by commands ===
┌─────────┬────────────────────────────────────────┬──────────┐
│ (index) │ spec                                   │ commands │
├─────────┼────────────────────────────────────────┼──────────┤
│ 0       │ 'cypress/e2e/timestamps.cy.js'         │ 3        │
│ 1       │ 'cypress/e2e/about.cy.js'              │ 2        │
│ 2       │ 'cypress/e2e/command-counts.cy.js'     │ 2        │
│ 3       │ 'cypress/e2e/filter-before-save.cy.js' │ 0        │
└─────────┴────────────────────────────────────────┴──────────┘

Merge visited URLs JSON files

If you have multiple JSON files with visited URLs, you can merge them into a single JSON file

$ npx merge-visited-urls --files 'folder/*.json' --output 'visited-urls.json'

Tip: visited urls are updated only when the test is successful. To avoid "losing" visited URL information if a test fails, you can merge the existing JSON urls file together with new updates by passing it first

$ npx merge-visited-urls --files 'visited-urls.json,folder/*.json' --output 'visited-urls.json'

Debugging

This plugin uses the debug module to output verbose logs. Run Node commands with the environment variable DEBUG=cypress-visited-urls set

$ DEBUG=cypress-visited-urls npx find-specs-by-url -f cypress-visited-urls.json -u about.html

Small print

Author: Gleb Bahmutov <gleb.bahmutov@gmail.com> © 2025

License: MIT - do anything with the code, but don't blame me if it does not work.

Support: if you find any problems with this module, email / tweet / open issue on Github

Readme

Keywords

Package Sidebar

Install

npm i cypress-visited-urls

Weekly Downloads

3,079

Version

2.1.5

License

MIT

Unpacked Size

35.9 kB

Total Files

11

Last publish

Collaborators

  • bahmutov