{
  "doc": {
    "id": "ui-coverage/results-api",
    "title": "UI Coverage Results API: enforce coverage in CI",
    "description": "Programmatically fetch UI Coverage results in CI with @cypress/extract-cloud-results, then block pull requests or fail the build when coverage drops below your thresholds.",
    "section": "ui-coverage",
    "source_path": "/llm/markdown/ui-coverage/results-api.md",
    "version": "e6c8d867c21227247f14714fb5690c7c018983c5",
    "updated_at": "2026-08-08T12:39:37.868Z",
    "headings": [
      {
        "id": "ui-coverage/results-api#results-api",
        "text": "Results API",
        "level": 1
      },
      {
        "id": "ui-coverage/results-api#how-it-works",
        "text": "How it works",
        "level": 2
      },
      {
        "id": "ui-coverage/results-api#supported-ci-providers-at-a-glance",
        "text": "Supported CI providers at a glance",
        "level": 2
      },
      {
        "id": "ui-coverage/results-api#installation",
        "text": "Installation",
        "level": 2
      },
      {
        "id": "ui-coverage/results-api#usage",
        "text": "Usage",
        "level": 2
      },
      {
        "id": "ui-coverage/results-api#write-your-verification-script",
        "text": "Write your verification script",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#basic-example",
        "text": "Basic example",
        "level": 4
      },
      {
        "id": "ui-coverage/results-api#getuicoverageresults-reference",
        "text": "getUICoverageResults reference",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#arguments",
        "text": "Arguments",
        "level": 4
      },
      {
        "id": "ui-coverage/results-api#result-properties",
        "text": "Result properties",
        "level": 4
      },
      {
        "id": "ui-coverage/results-api#reading-the-applied-configuration",
        "text": "Reading the applied configuration",
        "level": 4
      },
      {
        "id": "ui-coverage/results-api#handling-errors",
        "text": "Handling errors",
        "level": 4
      },
      {
        "id": "ui-coverage/results-api#add-the-verification-step-to-ci",
        "text": "Add the verification step to CI",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#example-workflow-updates",
        "text": "Example workflow updates",
        "level": 4
      },
      {
        "id": "ui-coverage/results-api#recording-multiple-runs-in-one-ci-build",
        "text": "Recording multiple runs in one CI build",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#examples",
        "text": "Examples",
        "level": 2
      },
      {
        "id": "ui-coverage/results-api#enforce-coverage-thresholds",
        "text": "Enforce coverage thresholds",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#report-coverage-on-the-pull-request",
        "text": "Report coverage on the pull request",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#fail-on-untested-navigation-links",
        "text": "Fail on untested navigation links",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#track-coverage-trends-over-time",
        "text": "Track coverage trends over time",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#skip-enforcement-for-partial-or-non-passing-runs",
        "text": "Skip enforcement for partial or non-passing runs",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#assert-the-applied-configuration",
        "text": "Assert the applied configuration",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#raise-the-threshold-as-coverage-improves",
        "text": "Raise the threshold as coverage improves",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#compare-against-a-baseline",
        "text": "Compare against a baseline",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#required-ci-environment-variables",
        "text": "Required CI environment variables",
        "level": 2
      },
      {
        "id": "ui-coverage/results-api#prerequisites",
        "text": "Prerequisites",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#environment-variables-by-ci-provider",
        "text": "Environment variables by CI provider",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#local-development-example",
        "text": "Local development example",
        "level": 3
      },
      {
        "id": "ui-coverage/results-api#see-also",
        "text": "See also",
        "level": 2
      }
    ]
  },
  "chunks": [
    {
      "id": "ui-coverage/results-api#how-it-works",
      "doc_id": "ui-coverage/results-api",
      "heading": "How it works",
      "heading_level": 2,
      "content_markdown": "## How it works\n\nWhen you call `getUICoverageResults` inside a CI job, the helper:\n\n1.  **Identifies the Cypress run** for the current CI build by cross-referencing the CI environment variables present when the run was recorded. See [Required CI environment variables](#Required-CI-environment-variables) for details.\n2.  **Waits for the UI Coverage report to finish processing.** If the report is still processing, the helper polls Cypress Cloud (up to 30 attempts at 30-second intervals, roughly 15 minutes) before returning.\n3.  **Returns the results** as a structured object you can assert against, or **throws a descriptive error** if no matching run or report can be found.\n\nBecause the helper matches the run from the current CI context, call it **after `cypress run --record` completes within the same CI build**, so the run it should report on already exists.\n\nAs it runs, the helper logs its progress to the console so you can follow along in your CI logs:\n\n```\nCypress found run #68086 (https://cloud.cypress.io/projects/ypt4pf/runs/68086) associated with this CI workflow.Cypress is fetching the UI Coverage report for run #68086.Cypress found a UI Coverage report for run #68086 that is still processing. 8 of 12 specs have been processed. Cypress will fetch again in 30 seconds [Attempt 1 of 30]Cypress found a UI Coverage report for run #68086 (https://cloud.cypress.io/projects/ypt4pf/runs/68086/ui-coverage).\n```\n\nA run must also meet a few conditions before a report can be found, including Test Replay being enabled and a supported Cypress version. See the [Results API FAQ](/llm/markdown/ui-coverage/faq.md#Results-API-and-CI) for the full list.\n",
      "section": "ui-coverage",
      "anchors": [
        "how-it-works"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 329
    },
    {
      "id": "ui-coverage/results-api#supported-ci-providers-at-a-glance",
      "doc_id": "ui-coverage/results-api",
      "heading": "Supported CI providers at a glance",
      "heading_level": 2,
      "content_markdown": "## Supported CI providers at a glance\n\nThe Results API supports the following CI providers:\n\n*   Azure\n*   CircleCI\n*   GitHub Actions\n*   GitLab\n*   Jenkins\n*   AWS CodeBuild\n*   Drone\n*   Bitbucket\n*   Buildkite\n\nFor other CI providers, contact Cypress Support at [support@cypress.io](mailto:support@cypress.io) to request support.\n",
      "section": "ui-coverage",
      "anchors": [
        "supported-ci-providers-at-a-glance"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 63
    },
    {
      "id": "ui-coverage/results-api#installation",
      "doc_id": "ui-coverage/results-api",
      "heading": "Installation",
      "heading_level": 2,
      "content_markdown": "## Installation\n\nInstall the `@cypress/extract-cloud-results` module in your install step in CI.\n\n*   npm\n*   Yarn\n*   pnpm\n\n```\nnpm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz\n```\n\n```\nyarn add --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz\n```\n\n```\npnpm add --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz\n```\n\nDo not check this module in as a dependency. We recommend you install it separately, outside of your normal module installation, and use `--force` to get the latest version.\n\nThe `v1` in the URL is the major-version line. Installing with `--force` always fetches the latest `1.x` release, so you receive fixes and improvements without changing the URL.\n",
      "section": "ui-coverage",
      "anchors": [
        "installation"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 124
    },
    {
      "id": "ui-coverage/results-api#usage",
      "doc_id": "ui-coverage/results-api",
      "heading": "Usage",
      "heading_level": 2,
      "content_markdown": "## Usage\n\n### Write your verification script\n\nWrite a script to fetch UI Coverage results and assert your coverage criteria. This script runs in CI.\n\n#### Basic example\n\nThis snippet uses the `getUICoverageResults()` helper to log out the results. It assumes your Project ID and Record Key are set as environment variables. It works in any of the supported CI providers out of the box:\n\nscripts/verifyUICoverageResults.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults()  .then((results) => {    // use `console.dir` instead of `console.log` because the data is nested    console.dir(results, { depth: Infinity })  })  .catch((error) => {    console.error(error.message)    process.exit(1)  })\n```\n\nOnce you can read the results, add your own logic to act on them. See [Examples](#Examples) for a worked script behind each supported use case, from enforcing thresholds to reporting on the pull request.\n\n### `getUICoverageResults` reference\n\nThe arguments the helper accepts, the data it returns, and how it behaves on errors.\n\n#### Arguments\n\n`getUICoverageResults` accepts the following arguments:\n\n```\ngetUICoverageResults({  // The Cypress project ID.  // Optional if the CYPRESS_PROJECT_ID env var is set.  projectId: string  // The project's record key.  // Optional if the CYPRESS_RECORD_KEY env var is set.  recordKey: string  // The run tags associated with the run.  // Required IF you record multiple Cypress runs from a single CI build.  // Pass the same tags you used when recording each run.  runTags: string[]})\n```\n\n#### Result properties\n\n`getUICoverageResults` resolves with the following data. A **link** is a navigational element (such as an anchor) that points at another view; **elements** are the interactive controls counted toward coverage.\n\n```\n{  runNumber: number  runUrl: 'https://cloud.cypress.io/projects/:project_id/runs/:run_number'  runStatus: 'passed' | 'failed' | 'errored' | 'timedOut' | 'cancelled' | 'noTests' | 'running' | 'overLimit'  uiCoverageReportUrl: 'https://cloud.cypress.io/[...]'  summary: {    // Whether a complete UI Coverage report was generated.    // For example, if a run was cancelled and the report was expected to    // cover 20 specs but only 10 ran, this would be a partial report.    isPartialReport: boolean    // The report coverage from 0-100 with 2-decimal precision (e.g. 92.45).    coverage: number    viewCount: number    testedElementsCount: number    untestedElementsCount: number    testedLinksCount: number    untestedLinksCount: number  }  views: [{    // The sanitized URL pattern shown in the report.    displayName: string    // The view coverage from 0-100 with 2-decimal precision (e.g. 92.45).    coverage: number    testedElementsCount: number    untestedElementsCount: number    testedLinksCount: number    untestedLinksCount: number    uiCoverageReportUrl: 'https://cloud.cypress.io/[...]'  }]  // The App Quality configuration that produced this report.  // Present when configuration exists for the project.  config: {    // ISO 8601 timestamp of when the configuration was last updated.    updatedAt: string    // The resolved configuration value, including any Profile applied    // to this run via run tags. See the example below.    value: object  }}\n```\n\nAn example of a returned result:\n\n```\n{  runNumber: 68086,  runUrl: 'https://cloud.cypress.io/projects/ypt4pf/runs/68086',  runStatus: 'passed',  uiCoverageReportUrl:    'https://cloud.cypress.io/projects/ypt4pf/runs/68086/ui-coverage',  summary: {    isPartialReport: false,    coverage: 87.42,    viewCount: 12,    testedElementsCount: 145,    untestedElementsCount: 21,    testedLinksCount: 34,    untestedLinksCount: 8,  },  views: [    {      displayName: '/checkout',      coverage: 94.12,      testedElementsCount: 32,      untestedElementsCount: 2,      testedLinksCount: 5,      untestedLinksCount: 0,      uiCoverageReportUrl:        'https://cloud.cypress.io/projects/ypt4pf/runs/68086/ui-coverage/view/checkout',    },    {      displayName: '/products/*',      coverage: 78.95,      testedElementsCount: 15,      untestedElementsCount: 4,      testedLinksCount: 9,      untestedLinksCount: 3,      uiCoverageReportUrl:        'https://cloud.cypress.io/projects/ypt4pf/runs/68086/ui-coverage/view/products',    },  ],  config: {    updatedAt: '2026-05-14T18:22:03.000Z',    value: {      /* App Quality Config, see below */    },  },}\n```\n\n#### Reading the applied configuration\n\nThe `config` property returns the **App Quality Config** that Cypress Cloud used to generate the report, resolved with any [Profile](/llm/markdown/ui-coverage/configuration/profiles.md) that matched the run's tags. This lets your script confirm exactly which rules were in effect, which is useful when different runs use different profiles.\n\nApp Quality Config\n\n```\n{  \"viewFilters\": [{ \"pattern\": \"/admin/*\", \"include\": false }],  \"uiCoverage\": {    \"elementFilters\": [{ \"selector\": \".cookie-banner *\", \"include\": false }]  },  \"profiles\": [    {      \"name\": \"production\",      \"config\": {        \"viewFilters\": [{ \"pattern\": \"/internal/*\", \"include\": false }]      }    }  ]}\n```\n\n#### Handling errors\n\n`getUICoverageResults` returns a promise that rejects with a descriptive `Error` when it can't return results. For example, this happens when no matching run is found for the CI context, when the run was recorded with Test Replay disabled, or when the report is still processing after the poll window elapses. Decide whether that should fail your build (let the rejection surface, as in the examples above) or be tolerated (catch it and exit cleanly), depending on how strict you want the check to be.\n\nscripts/verifyUICoverageResults.js\n\n```\ngetUICoverageResults()  .then((results) => {    // assert against results  })  .catch((error) => {    console.error(`Could not verify UI Coverage results: ${error.message}`)    // Fail the build...    process.exit(1)    // ...or treat the check as non-blocking by returning without a non-zero exit.  })\n```\n\n### Add the verification step to CI\n\nIn the CI workflow that runs your Cypress tests:\n\n1.  Update your install step to install the `@cypress/extract-cloud-results` module.\n2.  Pass any necessary arguments to `getUICoverageResults`.\n3.  Add a step, after your Cypress run, that executes your verification script.\n\n#### Example workflow updates\n\n*   GitHub Actions\n*   GitLab\n*   Jenkins\n*   Azure\n*   CircleCI\n*   AWS CodeBuild\n*   Drone\n*   Bitbucket\n*   Buildkite\n\ntest\\_cypress.yaml\n\n```\nname: My Workflowon: pushenv:  CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}jobs:  run-tests:    runs-on: ubuntu-24.04    steps:      - name: Checkout        uses: actions/checkout@v7      - name: install        run: npm install      - name: Run Cypress tests        run: npx cypress run --record+     - name: Get Cypress UI Coverage+       run: |+          npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+          node ./scripts/verifyUICoverageResults.js\n```\n\n.gitlab-ci.yml\n\n```\nimage: node:lateststages:  - testrun-tests:  stage: test  secrets:    CYPRESS_RECORD_KEY:      vault: vault/cypressRecordKey  script:    - npm install    - npx cypress run --record+   - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+   - node ./scripts/verifyUICoverageResults.js\n```\n\nJenkinsfile\n\n```\npipeline {  agent {    docker {      image 'cypress/base:22.15.0'    }  }  environment {    CYPRESS_PROJECT_ID = 'xxxx'    CYPRESS_RECORD_KEY = credentials('cypress-record-key')  }  stages {    stage('Run Cypress tests') {      steps {        sh 'npm ci'        sh 'npx cypress run --record'      }    }+   stage('Get Cypress UI Coverage') {+     steps {+       sh 'npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz'+       sh 'node ./scripts/verifyUICoverageResults.js'+     }+   }  }}\n```\n\nazure-pipelines.yml\n\n```\njobs:  - job: run_tests    pool:      vmImage: 'ubuntu-latest'    steps:      - task: NodeTool@0        inputs:          versionSpec: '20.x'          displayName: 'Install Node.js'      - script: npm i        displayName: 'Install npm dependencies'      - script: npx cypress run --record        displayName: 'Run Cypress tests'        env:          # avoid warnings about terminal          TERM: xterm          CYPRESS_RECORD_KEY: $(CYPRESS_RECORD_KEY)+     - script: |+           npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+           node ./scripts/verifyUICoverageResults.js+       displayName: 'Get Cypress UI Coverage'+       env:+         CYPRESS_PROJECT_ID: $(CYPRESS_PROJECT_ID)+         CYPRESS_RECORD_KEY: $(CYPRESS_RECORD_KEY)\n```\n\n.circleci/config.yml\n\n```\nversion: 2.1jobs:  run-tests:    docker:      - image: cypress/base:22.15.0    working_directory: ~/repo    steps:      - checkout      - run: npm install      - run: npx cypress run --record+     - run: npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+     - run: node ./scripts/verifyUICoverageResults.jsworkflows:  version: 2  tests:    jobs:      - run-tests\n```\n\nbuildspec.yaml\n\n```\nphases:  install:    runtime-versions:      nodejs: latest    commands:      # Set COMMIT_INFO variables to send Git specifics to Cypress Cloud when recording      # https://docs.cypress.io/app/continuous-integration/overview#Git-information      - export COMMIT_INFO_BRANCH=\"$(git rev-parse HEAD | xargs git name-rev |        cut -d' ' -f2 | sed 's/remotes\\/origin\\///g')\"      - export COMMIT_INFO_MESSAGE=\"$(git log -1 --pretty=%B)\"      - export COMMIT_INFO_EMAIL=\"$(git log -1 --pretty=%ae)\"      - export COMMIT_INFO_AUTHOR=\"$(git log -1 --pretty=%an)\"      - export COMMIT_INFO_SHA=\"$(git log -1 --pretty=%H)\"      - export COMMIT_INFO_REMOTE=\"$(git config --get remote.origin.url)\"      - npm ci  pre_build:    commands:      - npm run cypress:verify  build:    commands:      - CYPRESS_PROJECT_ID=[slug] npx cypress run --record --key [KEY]+  post_build:+    commands:+      - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+      - CYPRESS_PROJECT_ID=[slug] CYPRESS_RECORD_KEY=[KEY] node ./scripts/verifyUICoverageResults.js\n```\n\n.drone.yml\n\n```\nkind: pipelinename: defaultsteps:  - name: Run Cypress tests    image: node:latest    commands:      - npm install      - npx cypress run --record+  - name: Get Cypress UI Coverage+    image: node:latest+    commands:+      - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+      - node ./scripts/verifyUICoverageResults.js\n```\n\nbitbucket-pipelines.yml\n\n```\nimage: node:latestpipelines:  default:    - step:        name: Run Cypress tests        script:          - npm install          - npx cypress run --record+         - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+         - node ./scripts/verifyUICoverageResults.js\n```\n\npipeline.yml\n\n```\nsteps:  - label: \"Run Cypress tests\"    command:      - npm install      - npx cypress run --record+     - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+     - node ./scripts/verifyUICoverageResults.js\n```\n\n### Recording multiple runs in one CI build\n\nIf you record multiple runs in a single CI build, you must record each run with the `--tag` parameter and then call `getUICoverageResults` with the matching `runTags` argument for each run. This is how each run is uniquely identified so the correct results are returned. Tags can also activate [Profiles](/llm/markdown/ui-coverage/configuration/profiles.md) that apply different configuration to different runs.\n\nFor example, imagine that within a single CI build you call `cypress run --record` twice, once against a `staging` environment and once against `production`.\n\nPass a different `--tag` to each Cypress run:\n\n*   npm\n*   Yarn\n*   pnpm\n*   Bun\n\n```\nnpx cypress run --record --tag stagingnpx cypress run --record --tag production\n```\n\n```\nyarn cypress run --record --tag stagingyarn cypress run --record --tag production\n```\n\n```\npnpm cypress run --record --tag stagingpnpm cypress run --record --tag production\n```\n\n```\nbunx cypress run --record --tag stagingbunx cypress run --record --tag production\n```\n\nWhen calling `getUICoverageResults`, pass the same tags to get the results for each run:\n\n```\ngetUICoverageResults({ runTags: ['staging'] })getUICoverageResults({ runTags: ['production'] })\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "usage"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 1916
    },
    {
      "id": "ui-coverage/results-api#write-your-verification-script",
      "doc_id": "ui-coverage/results-api",
      "heading": "Write your verification script",
      "heading_level": 3,
      "content_markdown": "### Write your verification script\n\nWrite a script to fetch UI Coverage results and assert your coverage criteria. This script runs in CI.\n\n#### Basic example\n\nThis snippet uses the `getUICoverageResults()` helper to log out the results. It assumes your Project ID and Record Key are set as environment variables. It works in any of the supported CI providers out of the box:\n\nscripts/verifyUICoverageResults.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults()  .then((results) => {    // use `console.dir` instead of `console.log` because the data is nested    console.dir(results, { depth: Infinity })  })  .catch((error) => {    console.error(error.message)    process.exit(1)  })\n```\n\nOnce you can read the results, add your own logic to act on them. See [Examples](#Examples) for a worked script behind each supported use case, from enforcing thresholds to reporting on the pull request.\n",
      "section": "ui-coverage",
      "anchors": [
        "write-your-verification-script"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 176
    },
    {
      "id": "ui-coverage/results-api#basic-example",
      "doc_id": "ui-coverage/results-api",
      "heading": "Basic example",
      "heading_level": 4,
      "content_markdown": "#### Basic example\n\nThis snippet uses the `getUICoverageResults()` helper to log out the results. It assumes your Project ID and Record Key are set as environment variables. It works in any of the supported CI providers out of the box:\n\nscripts/verifyUICoverageResults.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults()  .then((results) => {    // use `console.dir` instead of `console.log` because the data is nested    console.dir(results, { depth: Infinity })  })  .catch((error) => {    console.error(error.message)    process.exit(1)  })\n```\n\nOnce you can read the results, add your own logic to act on them. See [Examples](#Examples) for a worked script behind each supported use case, from enforcing thresholds to reporting on the pull request.\n",
      "section": "ui-coverage",
      "anchors": [
        "basic-example"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 145
    },
    {
      "id": "ui-coverage/results-api#getuicoverageresults-reference",
      "doc_id": "ui-coverage/results-api",
      "heading": "getUICoverageResults reference",
      "heading_level": 3,
      "content_markdown": "### `getUICoverageResults` reference\n\nThe arguments the helper accepts, the data it returns, and how it behaves on errors.\n\n#### Arguments\n\n`getUICoverageResults` accepts the following arguments:\n\n```\ngetUICoverageResults({  // The Cypress project ID.  // Optional if the CYPRESS_PROJECT_ID env var is set.  projectId: string  // The project's record key.  // Optional if the CYPRESS_RECORD_KEY env var is set.  recordKey: string  // The run tags associated with the run.  // Required IF you record multiple Cypress runs from a single CI build.  // Pass the same tags you used when recording each run.  runTags: string[]})\n```\n\n#### Result properties\n\n`getUICoverageResults` resolves with the following data. A **link** is a navigational element (such as an anchor) that points at another view; **elements** are the interactive controls counted toward coverage.\n\n```\n{  runNumber: number  runUrl: 'https://cloud.cypress.io/projects/:project_id/runs/:run_number'  runStatus: 'passed' | 'failed' | 'errored' | 'timedOut' | 'cancelled' | 'noTests' | 'running' | 'overLimit'  uiCoverageReportUrl: 'https://cloud.cypress.io/[...]'  summary: {    // Whether a complete UI Coverage report was generated.    // For example, if a run was cancelled and the report was expected to    // cover 20 specs but only 10 ran, this would be a partial report.    isPartialReport: boolean    // The report coverage from 0-100 with 2-decimal precision (e.g. 92.45).    coverage: number    viewCount: number    testedElementsCount: number    untestedElementsCount: number    testedLinksCount: number    untestedLinksCount: number  }  views: [{    // The sanitized URL pattern shown in the report.    displayName: string    // The view coverage from 0-100 with 2-decimal precision (e.g. 92.45).    coverage: number    testedElementsCount: number    untestedElementsCount: number    testedLinksCount: number    untestedLinksCount: number    uiCoverageReportUrl: 'https://cloud.cypress.io/[...]'  }]  // The App Quality configuration that produced this report.  // Present when configuration exists for the project.  config: {    // ISO 8601 timestamp of when the configuration was last updated.    updatedAt: string    // The resolved configuration value, including any Profile applied    // to this run via run tags. See the example below.    value: object  }}\n```\n\nAn example of a returned result:\n\n```\n{  runNumber: 68086,  runUrl: 'https://cloud.cypress.io/projects/ypt4pf/runs/68086',  runStatus: 'passed',  uiCoverageReportUrl:    'https://cloud.cypress.io/projects/ypt4pf/runs/68086/ui-coverage',  summary: {    isPartialReport: false,    coverage: 87.42,    viewCount: 12,    testedElementsCount: 145,    untestedElementsCount: 21,    testedLinksCount: 34,    untestedLinksCount: 8,  },  views: [    {      displayName: '/checkout',      coverage: 94.12,      testedElementsCount: 32,      untestedElementsCount: 2,      testedLinksCount: 5,      untestedLinksCount: 0,      uiCoverageReportUrl:        'https://cloud.cypress.io/projects/ypt4pf/runs/68086/ui-coverage/view/checkout',    },    {      displayName: '/products/*',      coverage: 78.95,      testedElementsCount: 15,      untestedElementsCount: 4,      testedLinksCount: 9,      untestedLinksCount: 3,      uiCoverageReportUrl:        'https://cloud.cypress.io/projects/ypt4pf/runs/68086/ui-coverage/view/products',    },  ],  config: {    updatedAt: '2026-05-14T18:22:03.000Z',    value: {      /* App Quality Config, see below */    },  },}\n```\n\n#### Reading the applied configuration\n\nThe `config` property returns the **App Quality Config** that Cypress Cloud used to generate the report, resolved with any [Profile](/llm/markdown/ui-coverage/configuration/profiles.md) that matched the run's tags. This lets your script confirm exactly which rules were in effect, which is useful when different runs use different profiles.\n\nApp Quality Config\n\n```\n{  \"viewFilters\": [{ \"pattern\": \"/admin/*\", \"include\": false }],  \"uiCoverage\": {    \"elementFilters\": [{ \"selector\": \".cookie-banner *\", \"include\": false }]  },  \"profiles\": [    {      \"name\": \"production\",      \"config\": {        \"viewFilters\": [{ \"pattern\": \"/internal/*\", \"include\": false }]      }    }  ]}\n```\n\n#### Handling errors\n\n`getUICoverageResults` returns a promise that rejects with a descriptive `Error` when it can't return results. For example, this happens when no matching run is found for the CI context, when the run was recorded with Test Replay disabled, or when the report is still processing after the poll window elapses. Decide whether that should fail your build (let the rejection surface, as in the examples above) or be tolerated (catch it and exit cleanly), depending on how strict you want the check to be.\n\nscripts/verifyUICoverageResults.js\n\n```\ngetUICoverageResults()  .then((results) => {    // assert against results  })  .catch((error) => {    console.error(`Could not verify UI Coverage results: ${error.message}`)    // Fail the build...    process.exit(1)    // ...or treat the check as non-blocking by returning without a non-zero exit.  })\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "getuicoverageresults-reference"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 815
    },
    {
      "id": "ui-coverage/results-api#arguments",
      "doc_id": "ui-coverage/results-api",
      "heading": "Arguments",
      "heading_level": 4,
      "content_markdown": "#### Arguments\n\n`getUICoverageResults` accepts the following arguments:\n\n```\ngetUICoverageResults({  // The Cypress project ID.  // Optional if the CYPRESS_PROJECT_ID env var is set.  projectId: string  // The project's record key.  // Optional if the CYPRESS_RECORD_KEY env var is set.  recordKey: string  // The run tags associated with the run.  // Required IF you record multiple Cypress runs from a single CI build.  // Pass the same tags you used when recording each run.  runTags: string[]})\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "arguments"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 101
    },
    {
      "id": "ui-coverage/results-api#result-properties",
      "doc_id": "ui-coverage/results-api",
      "heading": "Result properties",
      "heading_level": 4,
      "content_markdown": "#### Result properties\n\n`getUICoverageResults` resolves with the following data. A **link** is a navigational element (such as an anchor) that points at another view; **elements** are the interactive controls counted toward coverage.\n\n```\n{  runNumber: number  runUrl: 'https://cloud.cypress.io/projects/:project_id/runs/:run_number'  runStatus: 'passed' | 'failed' | 'errored' | 'timedOut' | 'cancelled' | 'noTests' | 'running' | 'overLimit'  uiCoverageReportUrl: 'https://cloud.cypress.io/[...]'  summary: {    // Whether a complete UI Coverage report was generated.    // For example, if a run was cancelled and the report was expected to    // cover 20 specs but only 10 ran, this would be a partial report.    isPartialReport: boolean    // The report coverage from 0-100 with 2-decimal precision (e.g. 92.45).    coverage: number    viewCount: number    testedElementsCount: number    untestedElementsCount: number    testedLinksCount: number    untestedLinksCount: number  }  views: [{    // The sanitized URL pattern shown in the report.    displayName: string    // The view coverage from 0-100 with 2-decimal precision (e.g. 92.45).    coverage: number    testedElementsCount: number    untestedElementsCount: number    testedLinksCount: number    untestedLinksCount: number    uiCoverageReportUrl: 'https://cloud.cypress.io/[...]'  }]  // The App Quality configuration that produced this report.  // Present when configuration exists for the project.  config: {    // ISO 8601 timestamp of when the configuration was last updated.    updatedAt: string    // The resolved configuration value, including any Profile applied    // to this run via run tags. See the example below.    value: object  }}\n```\n\nAn example of a returned result:\n\n```\n{  runNumber: 68086,  runUrl: 'https://cloud.cypress.io/projects/ypt4pf/runs/68086',  runStatus: 'passed',  uiCoverageReportUrl:    'https://cloud.cypress.io/projects/ypt4pf/runs/68086/ui-coverage',  summary: {    isPartialReport: false,    coverage: 87.42,    viewCount: 12,    testedElementsCount: 145,    untestedElementsCount: 21,    testedLinksCount: 34,    untestedLinksCount: 8,  },  views: [    {      displayName: '/checkout',      coverage: 94.12,      testedElementsCount: 32,      untestedElementsCount: 2,      testedLinksCount: 5,      untestedLinksCount: 0,      uiCoverageReportUrl:        'https://cloud.cypress.io/projects/ypt4pf/runs/68086/ui-coverage/view/checkout',    },    {      displayName: '/products/*',      coverage: 78.95,      testedElementsCount: 15,      untestedElementsCount: 4,      testedLinksCount: 9,      untestedLinksCount: 3,      uiCoverageReportUrl:        'https://cloud.cypress.io/projects/ypt4pf/runs/68086/ui-coverage/view/products',    },  ],  config: {    updatedAt: '2026-05-14T18:22:03.000Z',    value: {      /* App Quality Config, see below */    },  },}\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "result-properties"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 397
    },
    {
      "id": "ui-coverage/results-api#reading-the-applied-configuration",
      "doc_id": "ui-coverage/results-api",
      "heading": "Reading the applied configuration",
      "heading_level": 4,
      "content_markdown": "#### Reading the applied configuration\n\nThe `config` property returns the **App Quality Config** that Cypress Cloud used to generate the report, resolved with any [Profile](/llm/markdown/ui-coverage/configuration/profiles.md) that matched the run's tags. This lets your script confirm exactly which rules were in effect, which is useful when different runs use different profiles.\n\nApp Quality Config\n\n```\n{  \"viewFilters\": [{ \"pattern\": \"/admin/*\", \"include\": false }],  \"uiCoverage\": {    \"elementFilters\": [{ \"selector\": \".cookie-banner *\", \"include\": false }]  },  \"profiles\": [    {      \"name\": \"production\",      \"config\": {        \"viewFilters\": [{ \"pattern\": \"/internal/*\", \"include\": false }]      }    }  ]}\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "reading-the-applied-configuration"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 121
    },
    {
      "id": "ui-coverage/results-api#handling-errors",
      "doc_id": "ui-coverage/results-api",
      "heading": "Handling errors",
      "heading_level": 4,
      "content_markdown": "#### Handling errors\n\n`getUICoverageResults` returns a promise that rejects with a descriptive `Error` when it can't return results. For example, this happens when no matching run is found for the CI context, when the run was recorded with Test Replay disabled, or when the report is still processing after the poll window elapses. Decide whether that should fail your build (let the rejection surface, as in the examples above) or be tolerated (catch it and exit cleanly), depending on how strict you want the check to be.\n\nscripts/verifyUICoverageResults.js\n\n```\ngetUICoverageResults()  .then((results) => {    // assert against results  })  .catch((error) => {    console.error(`Could not verify UI Coverage results: ${error.message}`)    // Fail the build...    process.exit(1)    // ...or treat the check as non-blocking by returning without a non-zero exit.  })\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "handling-errors"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 171
    },
    {
      "id": "ui-coverage/results-api#add-the-verification-step-to-ci",
      "doc_id": "ui-coverage/results-api",
      "heading": "Add the verification step to CI",
      "heading_level": 3,
      "content_markdown": "### Add the verification step to CI\n\nIn the CI workflow that runs your Cypress tests:\n\n1.  Update your install step to install the `@cypress/extract-cloud-results` module.\n2.  Pass any necessary arguments to `getUICoverageResults`.\n3.  Add a step, after your Cypress run, that executes your verification script.\n\n#### Example workflow updates\n\n*   GitHub Actions\n*   GitLab\n*   Jenkins\n*   Azure\n*   CircleCI\n*   AWS CodeBuild\n*   Drone\n*   Bitbucket\n*   Buildkite\n\ntest\\_cypress.yaml\n\n```\nname: My Workflowon: pushenv:  CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}jobs:  run-tests:    runs-on: ubuntu-24.04    steps:      - name: Checkout        uses: actions/checkout@v7      - name: install        run: npm install      - name: Run Cypress tests        run: npx cypress run --record+     - name: Get Cypress UI Coverage+       run: |+          npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+          node ./scripts/verifyUICoverageResults.js\n```\n\n.gitlab-ci.yml\n\n```\nimage: node:lateststages:  - testrun-tests:  stage: test  secrets:    CYPRESS_RECORD_KEY:      vault: vault/cypressRecordKey  script:    - npm install    - npx cypress run --record+   - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+   - node ./scripts/verifyUICoverageResults.js\n```\n\nJenkinsfile\n\n```\npipeline {  agent {    docker {      image 'cypress/base:22.15.0'    }  }  environment {    CYPRESS_PROJECT_ID = 'xxxx'    CYPRESS_RECORD_KEY = credentials('cypress-record-key')  }  stages {    stage('Run Cypress tests') {      steps {        sh 'npm ci'        sh 'npx cypress run --record'      }    }+   stage('Get Cypress UI Coverage') {+     steps {+       sh 'npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz'+       sh 'node ./scripts/verifyUICoverageResults.js'+     }+   }  }}\n```\n\nazure-pipelines.yml\n\n```\njobs:  - job: run_tests    pool:      vmImage: 'ubuntu-latest'    steps:      - task: NodeTool@0        inputs:          versionSpec: '20.x'          displayName: 'Install Node.js'      - script: npm i        displayName: 'Install npm dependencies'      - script: npx cypress run --record        displayName: 'Run Cypress tests'        env:          # avoid warnings about terminal          TERM: xterm          CYPRESS_RECORD_KEY: $(CYPRESS_RECORD_KEY)+     - script: |+           npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+           node ./scripts/verifyUICoverageResults.js+       displayName: 'Get Cypress UI Coverage'+       env:+         CYPRESS_PROJECT_ID: $(CYPRESS_PROJECT_ID)+         CYPRESS_RECORD_KEY: $(CYPRESS_RECORD_KEY)\n```\n\n.circleci/config.yml\n\n```\nversion: 2.1jobs:  run-tests:    docker:      - image: cypress/base:22.15.0    working_directory: ~/repo    steps:      - checkout      - run: npm install      - run: npx cypress run --record+     - run: npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+     - run: node ./scripts/verifyUICoverageResults.jsworkflows:  version: 2  tests:    jobs:      - run-tests\n```\n\nbuildspec.yaml\n\n```\nphases:  install:    runtime-versions:      nodejs: latest    commands:      # Set COMMIT_INFO variables to send Git specifics to Cypress Cloud when recording      # https://docs.cypress.io/app/continuous-integration/overview#Git-information      - export COMMIT_INFO_BRANCH=\"$(git rev-parse HEAD | xargs git name-rev |        cut -d' ' -f2 | sed 's/remotes\\/origin\\///g')\"      - export COMMIT_INFO_MESSAGE=\"$(git log -1 --pretty=%B)\"      - export COMMIT_INFO_EMAIL=\"$(git log -1 --pretty=%ae)\"      - export COMMIT_INFO_AUTHOR=\"$(git log -1 --pretty=%an)\"      - export COMMIT_INFO_SHA=\"$(git log -1 --pretty=%H)\"      - export COMMIT_INFO_REMOTE=\"$(git config --get remote.origin.url)\"      - npm ci  pre_build:    commands:      - npm run cypress:verify  build:    commands:      - CYPRESS_PROJECT_ID=[slug] npx cypress run --record --key [KEY]+  post_build:+    commands:+      - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+      - CYPRESS_PROJECT_ID=[slug] CYPRESS_RECORD_KEY=[KEY] node ./scripts/verifyUICoverageResults.js\n```\n\n.drone.yml\n\n```\nkind: pipelinename: defaultsteps:  - name: Run Cypress tests    image: node:latest    commands:      - npm install      - npx cypress run --record+  - name: Get Cypress UI Coverage+    image: node:latest+    commands:+      - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+      - node ./scripts/verifyUICoverageResults.js\n```\n\nbitbucket-pipelines.yml\n\n```\nimage: node:latestpipelines:  default:    - step:        name: Run Cypress tests        script:          - npm install          - npx cypress run --record+         - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+         - node ./scripts/verifyUICoverageResults.js\n```\n\npipeline.yml\n\n```\nsteps:  - label: \"Run Cypress tests\"    command:      - npm install      - npx cypress run --record+     - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+     - node ./scripts/verifyUICoverageResults.js\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "add-the-verification-step-to-ci"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 683
    },
    {
      "id": "ui-coverage/results-api#example-workflow-updates",
      "doc_id": "ui-coverage/results-api",
      "heading": "Example workflow updates",
      "heading_level": 4,
      "content_markdown": "#### Example workflow updates\n\n*   GitHub Actions\n*   GitLab\n*   Jenkins\n*   Azure\n*   CircleCI\n*   AWS CodeBuild\n*   Drone\n*   Bitbucket\n*   Buildkite\n\ntest\\_cypress.yaml\n\n```\nname: My Workflowon: pushenv:  CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}jobs:  run-tests:    runs-on: ubuntu-24.04    steps:      - name: Checkout        uses: actions/checkout@v7      - name: install        run: npm install      - name: Run Cypress tests        run: npx cypress run --record+     - name: Get Cypress UI Coverage+       run: |+          npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+          node ./scripts/verifyUICoverageResults.js\n```\n\n.gitlab-ci.yml\n\n```\nimage: node:lateststages:  - testrun-tests:  stage: test  secrets:    CYPRESS_RECORD_KEY:      vault: vault/cypressRecordKey  script:    - npm install    - npx cypress run --record+   - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+   - node ./scripts/verifyUICoverageResults.js\n```\n\nJenkinsfile\n\n```\npipeline {  agent {    docker {      image 'cypress/base:22.15.0'    }  }  environment {    CYPRESS_PROJECT_ID = 'xxxx'    CYPRESS_RECORD_KEY = credentials('cypress-record-key')  }  stages {    stage('Run Cypress tests') {      steps {        sh 'npm ci'        sh 'npx cypress run --record'      }    }+   stage('Get Cypress UI Coverage') {+     steps {+       sh 'npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz'+       sh 'node ./scripts/verifyUICoverageResults.js'+     }+   }  }}\n```\n\nazure-pipelines.yml\n\n```\njobs:  - job: run_tests    pool:      vmImage: 'ubuntu-latest'    steps:      - task: NodeTool@0        inputs:          versionSpec: '20.x'          displayName: 'Install Node.js'      - script: npm i        displayName: 'Install npm dependencies'      - script: npx cypress run --record        displayName: 'Run Cypress tests'        env:          # avoid warnings about terminal          TERM: xterm          CYPRESS_RECORD_KEY: $(CYPRESS_RECORD_KEY)+     - script: |+           npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+           node ./scripts/verifyUICoverageResults.js+       displayName: 'Get Cypress UI Coverage'+       env:+         CYPRESS_PROJECT_ID: $(CYPRESS_PROJECT_ID)+         CYPRESS_RECORD_KEY: $(CYPRESS_RECORD_KEY)\n```\n\n.circleci/config.yml\n\n```\nversion: 2.1jobs:  run-tests:    docker:      - image: cypress/base:22.15.0    working_directory: ~/repo    steps:      - checkout      - run: npm install      - run: npx cypress run --record+     - run: npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+     - run: node ./scripts/verifyUICoverageResults.jsworkflows:  version: 2  tests:    jobs:      - run-tests\n```\n\nbuildspec.yaml\n\n```\nphases:  install:    runtime-versions:      nodejs: latest    commands:      # Set COMMIT_INFO variables to send Git specifics to Cypress Cloud when recording      # https://docs.cypress.io/app/continuous-integration/overview#Git-information      - export COMMIT_INFO_BRANCH=\"$(git rev-parse HEAD | xargs git name-rev |        cut -d' ' -f2 | sed 's/remotes\\/origin\\///g')\"      - export COMMIT_INFO_MESSAGE=\"$(git log -1 --pretty=%B)\"      - export COMMIT_INFO_EMAIL=\"$(git log -1 --pretty=%ae)\"      - export COMMIT_INFO_AUTHOR=\"$(git log -1 --pretty=%an)\"      - export COMMIT_INFO_SHA=\"$(git log -1 --pretty=%H)\"      - export COMMIT_INFO_REMOTE=\"$(git config --get remote.origin.url)\"      - npm ci  pre_build:    commands:      - npm run cypress:verify  build:    commands:      - CYPRESS_PROJECT_ID=[slug] npx cypress run --record --key [KEY]+  post_build:+    commands:+      - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+      - CYPRESS_PROJECT_ID=[slug] CYPRESS_RECORD_KEY=[KEY] node ./scripts/verifyUICoverageResults.js\n```\n\n.drone.yml\n\n```\nkind: pipelinename: defaultsteps:  - name: Run Cypress tests    image: node:latest    commands:      - npm install      - npx cypress run --record+  - name: Get Cypress UI Coverage+    image: node:latest+    commands:+      - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+      - node ./scripts/verifyUICoverageResults.js\n```\n\nbitbucket-pipelines.yml\n\n```\nimage: node:latestpipelines:  default:    - step:        name: Run Cypress tests        script:          - npm install          - npx cypress run --record+         - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+         - node ./scripts/verifyUICoverageResults.js\n```\n\npipeline.yml\n\n```\nsteps:  - label: \"Run Cypress tests\"    command:      - npm install      - npx cypress run --record+     - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz+     - node ./scripts/verifyUICoverageResults.js\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "example-workflow-updates"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 621
    },
    {
      "id": "ui-coverage/results-api#recording-multiple-runs-in-one-ci-build",
      "doc_id": "ui-coverage/results-api",
      "heading": "Recording multiple runs in one CI build",
      "heading_level": 3,
      "content_markdown": "### Recording multiple runs in one CI build\n\nIf you record multiple runs in a single CI build, you must record each run with the `--tag` parameter and then call `getUICoverageResults` with the matching `runTags` argument for each run. This is how each run is uniquely identified so the correct results are returned. Tags can also activate [Profiles](/llm/markdown/ui-coverage/configuration/profiles.md) that apply different configuration to different runs.\n\nFor example, imagine that within a single CI build you call `cypress run --record` twice, once against a `staging` environment and once against `production`.\n\nPass a different `--tag` to each Cypress run:\n\n*   npm\n*   Yarn\n*   pnpm\n*   Bun\n\n```\nnpx cypress run --record --tag stagingnpx cypress run --record --tag production\n```\n\n```\nyarn cypress run --record --tag stagingyarn cypress run --record --tag production\n```\n\n```\npnpm cypress run --record --tag stagingpnpm cypress run --record --tag production\n```\n\n```\nbunx cypress run --record --tag stagingbunx cypress run --record --tag production\n```\n\nWhen calling `getUICoverageResults`, pass the same tags to get the results for each run:\n\n```\ngetUICoverageResults({ runTags: ['staging'] })getUICoverageResults({ runTags: ['production'] })\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "recording-multiple-runs-in-one-ci-build"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 240
    },
    {
      "id": "ui-coverage/results-api#examples",
      "doc_id": "ui-coverage/results-api",
      "heading": "Examples",
      "heading_level": 2,
      "content_markdown": "## Examples\n\nEach example below assumes you have written a script that calls `getUICoverageResults` and wired it into CI.\n\n### Enforce coverage thresholds\n\nFail the build when overall coverage drops below a floor, and hold critical flows like login and checkout to a higher standard:\n\nscripts/verifyUICoverageResults.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults({  projectId: process.env.CYPRESS_PROJECT_ID, // optional if set from env  recordKey: process.env.CYPRESS_RECORD_KEY, // optional if set from env  runTags: ['production'], // required if recording multiple runs in one CI build}).then((results) => {  const { runNumber, uiCoverageReportUrl, summary, views } = results  console.log(    `Received ${summary.isPartialReport ? 'partial ' : ''}results for run #${runNumber}.`  )  console.log(`See the full report at ${uiCoverageReportUrl}`)  // Fail the build if overall coverage is below 80%.  if (summary.coverage < 80) {    throw new Error(      `Project coverage is ${summary.coverage}%, below the minimum threshold of 80%.`    )  }  // Hold critical flows to a higher standard.  const criticalViews = [/login/, /checkout/]  views.forEach((view) => {    const { displayName, coverage, uiCoverageReportUrl } = view    if (      criticalViews.some((pattern) => pattern.test(displayName)) &&      coverage < 95    ) {      throw new Error(        `Critical view \"${displayName}\" coverage is ${coverage}%, below the required 95%. See: ${uiCoverageReportUrl}`      )    }  })  console.log('UI Coverage meets all thresholds.')})\n```\n\n### Report coverage on the pull request\n\nEvery result carries the coverage numbers and deep-link report URLs, so you can surface a summary where your team reviews code instead of only passing or failing. This example writes a Markdown summary that GitHub Actions renders on the job:\n\nscripts/reportUICoverage.js\n\n```\nconst fs = require('fs')const { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults().then(({ summary, views, uiCoverageReportUrl }) => {  const rows = views    .map((view) => `| ${view.displayName} | ${view.coverage}% |`)    .join('\\n')  const markdown = `## UI Coverage: ${summary.coverage}%[View the full report](${uiCoverageReportUrl})| View | Coverage || ---- | -------- |${rows}`  fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, markdown)})\n```\n\n### Fail on untested navigation links\n\nUI Coverage counts links (navigational elements that point at another view) separately from interactive elements. Use the link counts to catch pages that are linked but never visited:\n\nscripts/checkUntestedLinks.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults().then(({ summary, views }) => {  if (summary.untestedLinksCount === 0) {    return  }  console.log(    `${summary.untestedLinksCount} linked page(s) were never visited:`  )  views    .filter((view) => view.untestedLinksCount > 0)    .forEach((view) => {      console.log(        `  ${view.displayName}: ${view.untestedLinksCount} untested link(s)`      )    })  throw new Error(    'New navigation paths are untested. Add tests that follow them.'  )})\n```\n\n### Track coverage trends over time\n\nA baseline compares one run to one prior run. To trend coverage across many runs and teams, push each run's numbers to a dashboard or data warehouse:\n\nscripts/trackCoverageTrends.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults().then(({ runNumber, summary }) => {  const metrics = {    runNumber,    coverage: summary.coverage,    testedElements: summary.testedElementsCount,    untestedElements: summary.untestedElementsCount,    viewCount: summary.viewCount,  }  // Send to your metrics service, warehouse, or observability tool.  return fetch('https://metrics.example.com/ui-coverage', {    method: 'POST',    headers: { 'content-type': 'application/json' },    body: JSON.stringify(metrics),  })})\n```\n\n### Skip enforcement for partial or non-passing runs\n\nA run can be cancelled, time out, or produce a partial report. Check the run state first so an incomplete run warns instead of failing the build for the wrong reason:\n\nscripts/skipIncompleteRuns.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults().then((results) => {  const { runStatus, summary } = results  if (runStatus !== 'passed' && runStatus !== 'failed') {    console.warn(      `Run status is \"${runStatus}\". Skipping UI Coverage enforcement.`    )    return  }  if (summary.isPartialReport) {    console.warn('Report is partial. Skipping UI Coverage enforcement.')    return  }  // ...enforce your thresholds here.})\n```\n\n### Assert the applied configuration\n\nThe `config` property returns the App Quality Config that produced the report, resolved with any [Profile](/llm/markdown/ui-coverage/configuration/profiles.md) that matched the run's tags. Assert that required rules are in effect so a misconfigured run doesn't silently change what's measured:\n\nscripts/assertCoverageConfig.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults().then(({ config }) => {  if (!config) {    throw new Error('No App Quality Config was applied to this run.')  }  const elementFilters = config.value.uiCoverage?.elementFilters ?? []  const hasCookieBannerFilter = elementFilters.some((filter) =>    filter.selector?.includes('cookie-banner')  )  if (!hasCookieBannerFilter) {    throw new Error('Expected the cookie-banner element filter to be applied.')  }  console.log(`Configuration last updated ${config.updatedAt}.`)})\n```\n\n### Raise the threshold as coverage improves\n\nStore the last run's coverage and require the next run to meet or beat it, so the bar rises automatically as coverage improves. Commit the floor file so it travels with your code:\n\nscripts/raiseCoverageFloor.js\n\n```\nconst fs = require('fs')const { getUICoverageResults } = require('@cypress/extract-cloud-results')const FLOOR_FILE = 'ui-coverage-floor.json'const floor = fs.existsSync(FLOOR_FILE)  ? JSON.parse(fs.readFileSync(FLOOR_FILE, 'utf8')).coverage  : 0getUICoverageResults().then(({ summary }) => {  if (summary.coverage < floor) {    throw new Error(      `Coverage dropped to ${summary.coverage}%, below the previous floor of ${floor}%.`    )  }  fs.writeFileSync(FLOOR_FILE, JSON.stringify({ coverage: summary.coverage }))})\n```\n\n### Compare against a baseline\n\nComparing untested-element counts against a stored baseline fails a build only when **new** gaps are introduced, letting you pay down existing gaps over time instead of blocking on them all at once. For complete code, the baseline structure, and best practices, see the [Block pull requests and set policies](/llm/markdown/ui-coverage/guides/block-pull-requests.md#comparing-against-a-baseline) guide.\n",
      "section": "ui-coverage",
      "anchors": [
        "examples"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 1089
    },
    {
      "id": "ui-coverage/results-api#enforce-coverage-thresholds",
      "doc_id": "ui-coverage/results-api",
      "heading": "Enforce coverage thresholds",
      "heading_level": 3,
      "content_markdown": "### Enforce coverage thresholds\n\nFail the build when overall coverage drops below a floor, and hold critical flows like login and checkout to a higher standard:\n\nscripts/verifyUICoverageResults.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults({  projectId: process.env.CYPRESS_PROJECT_ID, // optional if set from env  recordKey: process.env.CYPRESS_RECORD_KEY, // optional if set from env  runTags: ['production'], // required if recording multiple runs in one CI build}).then((results) => {  const { runNumber, uiCoverageReportUrl, summary, views } = results  console.log(    `Received ${summary.isPartialReport ? 'partial ' : ''}results for run #${runNumber}.`  )  console.log(`See the full report at ${uiCoverageReportUrl}`)  // Fail the build if overall coverage is below 80%.  if (summary.coverage < 80) {    throw new Error(      `Project coverage is ${summary.coverage}%, below the minimum threshold of 80%.`    )  }  // Hold critical flows to a higher standard.  const criticalViews = [/login/, /checkout/]  views.forEach((view) => {    const { displayName, coverage, uiCoverageReportUrl } = view    if (      criticalViews.some((pattern) => pattern.test(displayName)) &&      coverage < 95    ) {      throw new Error(        `Critical view \"${displayName}\" coverage is ${coverage}%, below the required 95%. See: ${uiCoverageReportUrl}`      )    }  })  console.log('UI Coverage meets all thresholds.')})\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "enforce-coverage-thresholds"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 240
    },
    {
      "id": "ui-coverage/results-api#report-coverage-on-the-pull-request",
      "doc_id": "ui-coverage/results-api",
      "heading": "Report coverage on the pull request",
      "heading_level": 3,
      "content_markdown": "### Report coverage on the pull request\n\nEvery result carries the coverage numbers and deep-link report URLs, so you can surface a summary where your team reviews code instead of only passing or failing. This example writes a Markdown summary that GitHub Actions renders on the job:\n\nscripts/reportUICoverage.js\n\n```\nconst fs = require('fs')const { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults().then(({ summary, views, uiCoverageReportUrl }) => {  const rows = views    .map((view) => `| ${view.displayName} | ${view.coverage}% |`)    .join('\\n')  const markdown = `## UI Coverage: ${summary.coverage}%[View the full report](${uiCoverageReportUrl})| View | Coverage || ---- | -------- |${rows}`  fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, markdown)})\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "report-coverage-on-the-pull-request"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 129
    },
    {
      "id": "ui-coverage/results-api#fail-on-untested-navigation-links",
      "doc_id": "ui-coverage/results-api",
      "heading": "Fail on untested navigation links",
      "heading_level": 3,
      "content_markdown": "### Fail on untested navigation links\n\nUI Coverage counts links (navigational elements that point at another view) separately from interactive elements. Use the link counts to catch pages that are linked but never visited:\n\nscripts/checkUntestedLinks.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults().then(({ summary, views }) => {  if (summary.untestedLinksCount === 0) {    return  }  console.log(    `${summary.untestedLinksCount} linked page(s) were never visited:`  )  views    .filter((view) => view.untestedLinksCount > 0)    .forEach((view) => {      console.log(        `  ${view.displayName}: ${view.untestedLinksCount} untested link(s)`      )    })  throw new Error(    'New navigation paths are untested. Add tests that follow them.'  )})\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "fail-on-untested-navigation-links"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 125
    },
    {
      "id": "ui-coverage/results-api#track-coverage-trends-over-time",
      "doc_id": "ui-coverage/results-api",
      "heading": "Track coverage trends over time",
      "heading_level": 3,
      "content_markdown": "### Track coverage trends over time\n\nA baseline compares one run to one prior run. To trend coverage across many runs and teams, push each run's numbers to a dashboard or data warehouse:\n\nscripts/trackCoverageTrends.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults().then(({ runNumber, summary }) => {  const metrics = {    runNumber,    coverage: summary.coverage,    testedElements: summary.testedElementsCount,    untestedElements: summary.untestedElementsCount,    viewCount: summary.viewCount,  }  // Send to your metrics service, warehouse, or observability tool.  return fetch('https://metrics.example.com/ui-coverage', {    method: 'POST',    headers: { 'content-type': 'application/json' },    body: JSON.stringify(metrics),  })})\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "track-coverage-trends-over-time"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 112
    },
    {
      "id": "ui-coverage/results-api#skip-enforcement-for-partial-or-non-passing-runs",
      "doc_id": "ui-coverage/results-api",
      "heading": "Skip enforcement for partial or non-passing runs",
      "heading_level": 3,
      "content_markdown": "### Skip enforcement for partial or non-passing runs\n\nA run can be cancelled, time out, or produce a partial report. Check the run state first so an incomplete run warns instead of failing the build for the wrong reason:\n\nscripts/skipIncompleteRuns.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults().then((results) => {  const { runStatus, summary } = results  if (runStatus !== 'passed' && runStatus !== 'failed') {    console.warn(      `Run status is \"${runStatus}\". Skipping UI Coverage enforcement.`    )    return  }  if (summary.isPartialReport) {    console.warn('Report is partial. Skipping UI Coverage enforcement.')    return  }  // ...enforce your thresholds here.})\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "skip-enforcement-for-partial-or-non-passing-runs"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 127
    },
    {
      "id": "ui-coverage/results-api#assert-the-applied-configuration",
      "doc_id": "ui-coverage/results-api",
      "heading": "Assert the applied configuration",
      "heading_level": 3,
      "content_markdown": "### Assert the applied configuration\n\nThe `config` property returns the App Quality Config that produced the report, resolved with any [Profile](/llm/markdown/ui-coverage/configuration/profiles.md) that matched the run's tags. Assert that required rules are in effect so a misconfigured run doesn't silently change what's measured:\n\nscripts/assertCoverageConfig.js\n\n```\nconst { getUICoverageResults } = require('@cypress/extract-cloud-results')getUICoverageResults().then(({ config }) => {  if (!config) {    throw new Error('No App Quality Config was applied to this run.')  }  const elementFilters = config.value.uiCoverage?.elementFilters ?? []  const hasCookieBannerFilter = elementFilters.some((filter) =>    filter.selector?.includes('cookie-banner')  )  if (!hasCookieBannerFilter) {    throw new Error('Expected the cookie-banner element filter to be applied.')  }  console.log(`Configuration last updated ${config.updatedAt}.`)})\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "assert-the-applied-configuration"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 135
    },
    {
      "id": "ui-coverage/results-api#raise-the-threshold-as-coverage-improves",
      "doc_id": "ui-coverage/results-api",
      "heading": "Raise the threshold as coverage improves",
      "heading_level": 3,
      "content_markdown": "### Raise the threshold as coverage improves\n\nStore the last run's coverage and require the next run to meet or beat it, so the bar rises automatically as coverage improves. Commit the floor file so it travels with your code:\n\nscripts/raiseCoverageFloor.js\n\n```\nconst fs = require('fs')const { getUICoverageResults } = require('@cypress/extract-cloud-results')const FLOOR_FILE = 'ui-coverage-floor.json'const floor = fs.existsSync(FLOOR_FILE)  ? JSON.parse(fs.readFileSync(FLOOR_FILE, 'utf8')).coverage  : 0getUICoverageResults().then(({ summary }) => {  if (summary.coverage < floor) {    throw new Error(      `Coverage dropped to ${summary.coverage}%, below the previous floor of ${floor}%.`    )  }  fs.writeFileSync(FLOOR_FILE, JSON.stringify({ coverage: summary.coverage }))})\n```\n",
      "section": "ui-coverage",
      "anchors": [
        "raise-the-threshold-as-coverage-improves"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 123
    },
    {
      "id": "ui-coverage/results-api#compare-against-a-baseline",
      "doc_id": "ui-coverage/results-api",
      "heading": "Compare against a baseline",
      "heading_level": 3,
      "content_markdown": "### Compare against a baseline\n\nComparing untested-element counts against a stored baseline fails a build only when **new** gaps are introduced, letting you pay down existing gaps over time instead of blocking on them all at once. For complete code, the baseline structure, and best practices, see the [Block pull requests and set policies](/llm/markdown/ui-coverage/guides/block-pull-requests.md#comparing-against-a-baseline) guide.\n",
      "section": "ui-coverage",
      "anchors": [
        "compare-against-a-baseline"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 73
    },
    {
      "id": "ui-coverage/results-api#required-ci-environment-variables",
      "doc_id": "ui-coverage/results-api",
      "heading": "Required CI environment variables",
      "heading_level": 2,
      "content_markdown": "## Required CI environment variables\n\nThe `@cypress/extract-cloud-results` helper detects the correct Cloud run by matching environment variables from where it runs against those present when the run was recorded, which is why it works automatically from the same CI context (as in the examples above).\n\nKnowing which variables it looks for helps with more complex setups and with local iteration: set them to match what was present in CI to pull a specific run (recorded within the last 7 days) from your machine.\n\n### Prerequisites\n\nTwo prerequisites apply to every provider:\n\n1.  Record the Cypress run and run your validation script within the same CI run (the same build, workflow, or pipeline).\n2.  Run the validation script _after_ the run has been recorded, either in a separate job that depends on the recording job (using your provider's dependency option, such as `needs`, `dependsOn`, or `requires`), or serially after the recording step in the same job.\n\n### Environment variables by CI provider\n\nEach CI provider has a unique combination of components, patterns, and environment variables that must be interpreted by this module. Expand a provider below for its essential environment variables.\n\nGitHub Actions\n\nReferences: [Understanding GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) | [GitHub Actions default environment variables](https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables)\n\n**Essential environment variables**\n\n*   `GITHUB_ACTIONS` - Presence identifies the environment as a GitHub Actions environment.\n*   `GITHUB_RUN_ID` - Value uniquely identifies a GitHub Actions workflow instance. Value does not change as jobs in the workflow are re-executed.\n*   `GITHUB_RUN_ATTEMPT` - Value identifies the workflow instance's attempt index. Value is incremented each time jobs are re-executed.\n\nGitLab\n\nReferences: [GitLab CI/CD pipelines](https://docs.gitlab.com/ee/ci/pipelines/) | [GitLab predefined variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)\n\n**Essential environment variables**\n\n*   `GITLAB_CI` - Presence identifies the environment as a GitLab CI environment\n*   `CI_PIPELINE_ID` - Value uniquely identifies a GitLab pipeline workflow. This value does not change as jobs in the pipeline are retried.\n*   `CI_JOB_NAME` - Value uniquely identifies a single job name within a pipeline. Ex. `run-e2e`\n*   `CI_JOB_ID` - Value uniquely identifies an execution instance of a job. This value will change each time a job is executed/re-executed.\n\nJenkins\n\nReferences: [Jenkins documentation](https://www.jenkins.io/doc/) | [Jenkins environment variables](https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables)\n\nJenkins is heavily customizable through the usage of plugins, which limits the amount of assumptions we can make about available environment variables and overall behavior.\n\nWe have implemented Jenkins support within this module using the broadest set of available default values. For the purposes of this documentation, though, we will discuss terms related to [Jenkins Pipeline support](https://www.jenkins.io/doc/book/pipeline/getting-started/).\n\n**Essential environment variables**\n\n*   `JENKINS_HOME` - Presence identifies the environment as a Jenkins environment\n*   `BUILD_URL` - Value uniquely identifies a Jenkins job execution, including name and id characteristics.\n\nAzure\n\nReferences: [Azure Pipelines key concepts](https://learn.microsoft.com/en-us/azure/devops/pipelines/get-started/key-pipelines-concepts?view=azure-devops) | [Azure Pipelines predefined variables](https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml)\n\n> Note: Cypress v13.13.1 is the earliest Cypress release that records the environment variables necessary for this module to identify runs in an Azure environment. Previous Cypress versions are not supported in Azure pipelines.\n\n**Essential environment variables**\n\n*   `TF_BUILD` and `AZURE_HTTP_USER_AGENT` - Combined presence identifies the environment as an Azure pipeline environment.\n*   `SYSTEM_PLANID` - Value uniquely identifies a pipeline run. Value does not change as jobs within the pipeline are retried from failure.\n*   `SYSTEM_JOBID` - Value uniquely identifies a job execution. Value changes each time a job is retried from failure, in conjunction with the `SYSTEM_JOBATTEMPT` being incremented.\n*   `SYSTEM_JOBATTEMPT` - Value identifies the pipelines shared attempt index. Value is incremented when jobs are retried from failure.\n\nCircleCI\n\nReferences: [About CircleCI](https://circleci.com/docs/about-circleci/) | [CircleCI built-in environment variables](https://circleci.com/docs/variables/#built-in-environment-variables)\n\n> Note: Cypress v13.13.1 is the earliest Cypress release that records the environment variables necessary for this module to identify runs in an CircleCI environment. Previous Cypress versions are not supported in CircleCI pipelines.\n\n**Essential environment variables**\n\n*   `CIRCLECI` - Presence identifies the environment as a CircleCI environment\n*   `CIRCLE_PIPELINE_ID` - Value uniquely identifies a CircleCI pipeline, created on push or manually triggered through the UI. This value does not change as workflows within the pipeline are re-executed.\n*   `CIRCLE_WORKFLOW_ID` - Value uniquely identifies an instance of a workflow's execution within a pipeline. This value will be updated upon each workflow execution; in other words, retrying a workflow from failure from the Circle UI will create a new workflow with a new `CIRCLE_WORKFLOW_ID` value available to the jobs executed within it.\n*   `CIRCLE_WORKFLOW_JOB_ID` - Value uniquely identifies an execution instance of a named job within a workflow instance.\n\nAWS CodeBuild\n\nReferences: [AWS CodeBuild documentation](https://docs.aws.amazon.com/codebuild/) | [AWS CodeBuild environment variables](https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html)\n\n**Essential environment variables**\n\n*   `CODEBUILD_BUILD_ID` - Presence identifies the environment as an AWS CodeBuild environment. Value uniquely identifies a build.\n\nDrone\n\nReferences: [Drone pipeline overview](https://docs.drone.io/pipeline/overview/) | [Drone environment reference](https://docs.drone.io/pipeline/environment/reference/)\n\n**Essential environment variables**\n\n*   `DRONE` - Presence identifies the environment as a Drone environment.\n*   `DRONE_BUILD_NUMBER` - Value uniquely identifies a Drone build.\n\nBitbucket\n\nReferences: [Bitbucket Cloud documentation](https://support.atlassian.com/bitbucket-cloud/docs/) | [Bitbucket variables and secrets](https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/)\n\n**Essential environment variables**\n\n*   `BITBUCKET_BUILD_NUMBER` - Presence identifies the environment as a Bitbucket environment. Value uniquely identifies a build.\n*   `BITBUCKET_STEP_RUN_NUMBER` - Value indicates a build step execution index and increments when a step is retried. Initial value of 1.\n\nBuildkite\n\nReferences: [Buildkite documentation](https://buildkite.com/docs) | [Buildkite environment variables](https://buildkite.com/docs/pipelines/environment-variables)\n\n**Essential environment variables**\n\n*   `BUILDKITE` - Presence identifies the environment as a Buildkite environment.\n*   `BUILDKITE_BUILD_ID` - Value uniquely identifies a build. This value does not change across different jobs within the same build.\n*   `BUILDKITE_JOB_ID` - Value uniquely identifies a job execution. Each job in a build has a unique job ID.\n*   `BUILDKITE_RETRY_COUNT` - Value indicates the retry attempt for a job. Default value of 0.\n\n### Local development example\n\nTo iterate on your verification script and see everything working without putting code into your CI environment, simulate the CI context for a specific Cypress run locally. This can save a lot of time when getting started.\n\nIf you executed a run in GitHub Actions and it was recorded to Cypress Cloud, you would set these 4 environment variables to replicate the context of that run locally and execute your local handler script. This is a great way to iterate on your script and verify everything is working as expected, without having to integrate anything in CI. It's also useful for debugging.\n\n```\nCYPRESS_PROJECT_ID=AAACYPRESS_RECORD_KEY=BBBGITHUB_ACTIONS=trueGITHUB_RUN_ID=111GITHUB_RUN_ATTEMPT=1node verifyResults.js\n```\n\nThe Results API will then look for the Cypress Cloud run that matches this run ID. If there is more than one Cypress Cloud run found for that GitHub Actions Run, you can pass run tags to narrow down to one run's report.\n",
      "section": "ui-coverage",
      "anchors": [
        "required-ci-environment-variables"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 1417
    },
    {
      "id": "ui-coverage/results-api#prerequisites",
      "doc_id": "ui-coverage/results-api",
      "heading": "Prerequisites",
      "heading_level": 3,
      "content_markdown": "### Prerequisites\n\nTwo prerequisites apply to every provider:\n\n1.  Record the Cypress run and run your validation script within the same CI run (the same build, workflow, or pipeline).\n2.  Run the validation script _after_ the run has been recorded, either in a separate job that depends on the recording job (using your provider's dependency option, such as `needs`, `dependsOn`, or `requires`), or serially after the recording step in the same job.\n",
      "section": "ui-coverage",
      "anchors": [
        "prerequisites"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 96
    },
    {
      "id": "ui-coverage/results-api#environment-variables-by-ci-provider",
      "doc_id": "ui-coverage/results-api",
      "heading": "Environment variables by CI provider",
      "heading_level": 3,
      "content_markdown": "### Environment variables by CI provider\n\nEach CI provider has a unique combination of components, patterns, and environment variables that must be interpreted by this module. Expand a provider below for its essential environment variables.\n\nGitHub Actions\n\nReferences: [Understanding GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) | [GitHub Actions default environment variables](https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables)\n\n**Essential environment variables**\n\n*   `GITHUB_ACTIONS` - Presence identifies the environment as a GitHub Actions environment.\n*   `GITHUB_RUN_ID` - Value uniquely identifies a GitHub Actions workflow instance. Value does not change as jobs in the workflow are re-executed.\n*   `GITHUB_RUN_ATTEMPT` - Value identifies the workflow instance's attempt index. Value is incremented each time jobs are re-executed.\n\nGitLab\n\nReferences: [GitLab CI/CD pipelines](https://docs.gitlab.com/ee/ci/pipelines/) | [GitLab predefined variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)\n\n**Essential environment variables**\n\n*   `GITLAB_CI` - Presence identifies the environment as a GitLab CI environment\n*   `CI_PIPELINE_ID` - Value uniquely identifies a GitLab pipeline workflow. This value does not change as jobs in the pipeline are retried.\n*   `CI_JOB_NAME` - Value uniquely identifies a single job name within a pipeline. Ex. `run-e2e`\n*   `CI_JOB_ID` - Value uniquely identifies an execution instance of a job. This value will change each time a job is executed/re-executed.\n\nJenkins\n\nReferences: [Jenkins documentation](https://www.jenkins.io/doc/) | [Jenkins environment variables](https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables)\n\nJenkins is heavily customizable through the usage of plugins, which limits the amount of assumptions we can make about available environment variables and overall behavior.\n\nWe have implemented Jenkins support within this module using the broadest set of available default values. For the purposes of this documentation, though, we will discuss terms related to [Jenkins Pipeline support](https://www.jenkins.io/doc/book/pipeline/getting-started/).\n\n**Essential environment variables**\n\n*   `JENKINS_HOME` - Presence identifies the environment as a Jenkins environment\n*   `BUILD_URL` - Value uniquely identifies a Jenkins job execution, including name and id characteristics.\n\nAzure\n\nReferences: [Azure Pipelines key concepts](https://learn.microsoft.com/en-us/azure/devops/pipelines/get-started/key-pipelines-concepts?view=azure-devops) | [Azure Pipelines predefined variables](https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml)\n\n> Note: Cypress v13.13.1 is the earliest Cypress release that records the environment variables necessary for this module to identify runs in an Azure environment. Previous Cypress versions are not supported in Azure pipelines.\n\n**Essential environment variables**\n\n*   `TF_BUILD` and `AZURE_HTTP_USER_AGENT` - Combined presence identifies the environment as an Azure pipeline environment.\n*   `SYSTEM_PLANID` - Value uniquely identifies a pipeline run. Value does not change as jobs within the pipeline are retried from failure.\n*   `SYSTEM_JOBID` - Value uniquely identifies a job execution. Value changes each time a job is retried from failure, in conjunction with the `SYSTEM_JOBATTEMPT` being incremented.\n*   `SYSTEM_JOBATTEMPT` - Value identifies the pipelines shared attempt index. Value is incremented when jobs are retried from failure.\n\nCircleCI\n\nReferences: [About CircleCI](https://circleci.com/docs/about-circleci/) | [CircleCI built-in environment variables](https://circleci.com/docs/variables/#built-in-environment-variables)\n\n> Note: Cypress v13.13.1 is the earliest Cypress release that records the environment variables necessary for this module to identify runs in an CircleCI environment. Previous Cypress versions are not supported in CircleCI pipelines.\n\n**Essential environment variables**\n\n*   `CIRCLECI` - Presence identifies the environment as a CircleCI environment\n*   `CIRCLE_PIPELINE_ID` - Value uniquely identifies a CircleCI pipeline, created on push or manually triggered through the UI. This value does not change as workflows within the pipeline are re-executed.\n*   `CIRCLE_WORKFLOW_ID` - Value uniquely identifies an instance of a workflow's execution within a pipeline. This value will be updated upon each workflow execution; in other words, retrying a workflow from failure from the Circle UI will create a new workflow with a new `CIRCLE_WORKFLOW_ID` value available to the jobs executed within it.\n*   `CIRCLE_WORKFLOW_JOB_ID` - Value uniquely identifies an execution instance of a named job within a workflow instance.\n\nAWS CodeBuild\n\nReferences: [AWS CodeBuild documentation](https://docs.aws.amazon.com/codebuild/) | [AWS CodeBuild environment variables](https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html)\n\n**Essential environment variables**\n\n*   `CODEBUILD_BUILD_ID` - Presence identifies the environment as an AWS CodeBuild environment. Value uniquely identifies a build.\n\nDrone\n\nReferences: [Drone pipeline overview](https://docs.drone.io/pipeline/overview/) | [Drone environment reference](https://docs.drone.io/pipeline/environment/reference/)\n\n**Essential environment variables**\n\n*   `DRONE` - Presence identifies the environment as a Drone environment.\n*   `DRONE_BUILD_NUMBER` - Value uniquely identifies a Drone build.\n\nBitbucket\n\nReferences: [Bitbucket Cloud documentation](https://support.atlassian.com/bitbucket-cloud/docs/) | [Bitbucket variables and secrets](https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/)\n\n**Essential environment variables**\n\n*   `BITBUCKET_BUILD_NUMBER` - Presence identifies the environment as a Bitbucket environment. Value uniquely identifies a build.\n*   `BITBUCKET_STEP_RUN_NUMBER` - Value indicates a build step execution index and increments when a step is retried. Initial value of 1.\n\nBuildkite\n\nReferences: [Buildkite documentation](https://buildkite.com/docs) | [Buildkite environment variables](https://buildkite.com/docs/pipelines/environment-variables)\n\n**Essential environment variables**\n\n*   `BUILDKITE` - Presence identifies the environment as a Buildkite environment.\n*   `BUILDKITE_BUILD_ID` - Value uniquely identifies a build. This value does not change across different jobs within the same build.\n*   `BUILDKITE_JOB_ID` - Value uniquely identifies a job execution. Each job in a build has a unique job ID.\n*   `BUILDKITE_RETRY_COUNT` - Value indicates the retry attempt for a job. Default value of 0.\n",
      "section": "ui-coverage",
      "anchors": [
        "environment-variables-by-ci-provider"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 1007
    },
    {
      "id": "ui-coverage/results-api#local-development-example",
      "doc_id": "ui-coverage/results-api",
      "heading": "Local development example",
      "heading_level": 3,
      "content_markdown": "### Local development example\n\nTo iterate on your verification script and see everything working without putting code into your CI environment, simulate the CI context for a specific Cypress run locally. This can save a lot of time when getting started.\n\nIf you executed a run in GitHub Actions and it was recorded to Cypress Cloud, you would set these 4 environment variables to replicate the context of that run locally and execute your local handler script. This is a great way to iterate on your script and verify everything is working as expected, without having to integrate anything in CI. It's also useful for debugging.\n\n```\nCYPRESS_PROJECT_ID=AAACYPRESS_RECORD_KEY=BBBGITHUB_ACTIONS=trueGITHUB_RUN_ID=111GITHUB_RUN_ATTEMPT=1node verifyResults.js\n```\n\nThe Results API will then look for the Cypress Cloud run that matches this run ID. If there is more than one Cypress Cloud run found for that GitHub Actions Run, you can pass run tags to narrow down to one run's report.\n",
      "section": "ui-coverage",
      "anchors": [
        "local-development-example"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 204
    },
    {
      "id": "ui-coverage/results-api#see-also",
      "doc_id": "ui-coverage/results-api",
      "heading": "See also",
      "heading_level": 2,
      "content_markdown": "## See also\n\n*   [Block pull requests and set policies](/llm/markdown/ui-coverage/guides/block-pull-requests.md): set a coverage policy and fail a pull request when it isn't met.\n*   [Monitor changes](/llm/markdown/ui-coverage/guides/monitor-changes.md): track coverage trends and catch regressions over time.\n*   [Results API FAQ](/llm/markdown/ui-coverage/faq.md#Results-API-and-CI): quick answers to common Results API and CI questions.\n*   [Profiles](/llm/markdown/ui-coverage/configuration/profiles.md): apply different configuration to different runs using run tags.\n",
      "section": "ui-coverage",
      "anchors": [
        "see-also"
      ],
      "path": "/llm/json/chunked/ui-coverage/results-api.json",
      "token_estimate": 77
    }
  ]
}