Skip to content

GitHub Action for running Cypress end-to-end tests

License

Notifications You must be signed in to change notification settings

vtymofeev-tc/github-action

 
 

Repository files navigation

cypress-io/github-action renovate-app badge Action status

GitHub Action for running Cypress end-to-end tests. Includes NPM installation, custom caching and lots of configuration options.

Important

We are getting reports that Cypress has suddenly started crashing when running on ubuntu-latest OS. Seems, GH Actions have switched from 16.04 to 18.04 overnight, and are having a xvfb issue. Please work around this problem by using runs-on: ubuntu-16.04 image or upgrading to Cypress v3.8.3 where we explicitly set XVFB arguments.

Examples

Basic

name: End-to-end tests
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1
      # Install NPM dependencies, cache them correctly
      # and run all Cypress tests
      - name: Cypress run
        uses: cypress-io/github-action@v1

Browser

Specify the browser name or path with browser parameter

name: E2E on Chrome
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    # let's make sure our tests pass on Chrome browser
    name: E2E on Chrome
    steps:
      - uses: actions/checkout@v1
      - uses: cypress-io/github-action@v1
        with:
          browser: chrome

Headless

Run the browser in headless mode

name: Chrome headless
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    steps:
      - uses: actions/checkout@v1
      - uses: cypress-io/github-action@v1
        with:
          browser: chrome
          headless: true

Docker image

You can run tests in a GH Action in your Docker container.

name: E2E in custom container
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    # Cypress Docker image with Chrome v78
    # and Firefox v70 pre-installed
    container: cypress/browsers:node12.13.0-chrome78-ff70
    steps:
      - uses: actions/checkout@v1
      - uses: cypress-io/github-action@v1
        with:
          browser: firefox

Env

Specify the env argument with env parameter

name: Cypress tests
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1

      - name: Cypress run with env
        uses: cypress-io/github-action@v1
        with:
          env: host=api.dev.local,port=4222

Specs

Specify the spec files to run with spec parameter

name: Cypress tests
on: [push]
jobs:
  cypress-run:
    name: Cypress run
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1

      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          spec: cypress/integration/spec1.js

For more information, visit the Cypress command-line docs.

Record test results on Cypress Dashboard

name: Cypress tests
on: [push]
jobs:
  cypress-run:
    name: Cypress run
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1

      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          record: true
        env:
          # pass the Dashboard record key as an environment variable
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

Tag recordings

You can pass a single or multiple tags when recording a run. For example

name: tags
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-latest
    # let's make sure our "app" works on several versions of Node
    strategy:
      matrix:
        node: [10, 12]
    name: E2E on Node v${{ matrix.node }}
    steps:
      - name: Setup Node
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node }}
      - run: node -v

      - name: Checkout
        uses: actions/checkout@v1

      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          record: true
          tag: node-${{ matrix.node }}
        env:
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

The recording will have tags as labels on the run.

Tags

You can pass multiple tags using commas like tag: node-10,nightly,staging.

Artifacts

If you don't record the test run on Cypress Dashboard, you can still store generated videos and screenshots as CI artifacts. See cypress-gh-action-example and the workflow example below

name: Artifacts
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    name: Artifacts
    steps:
      - uses: actions/checkout@v1
      - uses: cypress-io/github-action@v1
      # after the test run completes
      # store videos and any screenshots
      # NOTE: screenshots will be generated only if E2E test failed
      # thus we store screenshots only on failures
      # Alternative: create and commit an empty cypress/screenshots folder
      # to always have something to upload
      - uses: actions/upload-artifact@v1
        if: failure()
        with:
          name: cypress-screenshots
          path: cypress/screenshots
      # Test run video was always captured, so this action uses "always()" condition
      - uses: actions/upload-artifact@v1
        if: always()
        with:
          name: cypress-videos
          path: cypress/videos

Config

Specify configuration values with config parameter

name: Cypress tests
on: [push]
jobs:
  cypress-run:
    name: Cypress run
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1

      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          config: pageLoadTimeout=100000,watchForFileChanges=false

Config File

Specify the path to your config file with config-file parameter

name: Cypress tests
on: [push]
jobs:
  cypress-run:
    name: Cypress run
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1

      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          config-file: tests/cypress-config.json

Parallel

You can spin multiple containers running in parallel using strategy: matrix argument. Just add more dummy items to the containers: [1, 2, ...] array to spin more free or paid containers. Then use record and parallel parameters to load balance tests

name: Parallel Cypress Tests

on: [push]

jobs:
  test:
    name: Cypress run
    runs-on: ubuntu-16.04
    strategy:
      matrix:
        # run 3 copies of the current job in parallel
        containers: [1, 2, 3]
    steps:
      - name: Checkout
        uses: actions/checkout@v1

      # because of "record" and "parallel" parameters
      # these containers will load balance all found tests among themselves
      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          record: true
          parallel: true
          group: 'Actions example'
        env:
          # pass the Dashboard record key as an environment variable
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

Parallel run

Warning ⚠️: Cypress Dashboard API connects parallel jobs into a single logical run using GitHub commit SHA plus workflow name, since there is no better unique ID during GitHub Action execution. Thus if you attempt to re-run GitHub checks, the Dashboard thinks the run has already ended. In order to truly rerun parallel jobs, push an empty commit with git commit --allow-empty -m "re-run checks" && git push. As another work around you can generate and cache a custom build id, read Adding a unique build number to GitHub Actions

Build app

You can run a build step before starting tests

name: Build
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1
      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          build: npm run build

Start server

If your tests run against a local server, use start parameter, the server will run in the background and will shut down after tests complete

name: With server
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1
      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          start: npm start

Note: sometimes on Windows you need to run a different start command. You can use start-windows parameter for this

name: With server
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1
      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          # Linux and MacOS
          start: npm start
          # Takes precedences on Windows
          start-windows: npm run start:windows:server

Wait-on

If you are starting a local server and it takes a while to start, you can add a parameter wait-on and pass url to wait for the server to respond.

name: After server responds
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1
      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          start: npm start
          # quote the url to be safe against YML parsing surprises
          wait-on: 'http://localhost:8080'

By default, wait-on will retry for 60 seconds. You can pass a custom timeout in seconds using wait-on-timeout.

- uses: cypress-io/github-action@v1
  with:
    start: npm start
    wait-on: 'http://localhost:8080/status'
    # wait for 2 minutes for the server to respond
    wait-on-timeout: 120

Command prefix

You can prefix the test command using the command-prefix option. This is useful for example when running Percy, which requires the test command to be wrapped with percy exec --.

name: Visual
on: [push]
jobs:
  e2e:
    runs-on: ubuntu-16.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1
      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          start: npm start
          # quote the url to be safe against YML parsing surprises
          wait-on: 'http://localhost:8080'
          # the entire command will automatically be prefixed with "npm"
          # and we need the second "npm" to execute "cypress run ..." command line
          command-prefix: 'percy exec -- npx'

See live example angular-pizza-creator.

Custom build id

You can overwrite ci-build-id used to link separate machines running tests into a single parallel run.

name: Parallel
on: [push]
jobs:
  test:
    runs-on: ubuntu-16.04
    strategy:
      matrix:
        # run 3 copies of the current job in parallel
        containers: [1, 2, 3]
    steps:
      - uses: actions/checkout@v1
      - uses: cypress-io/github-action@v1
        with:
          record: true
          parallel: true
          group: 'Actions example'
          ci-build-id: '${{ github.sha }}-${{ github.workflow }}-${{ github.event_name }}'
        env:
          # pass the Dashboard record key as an environment variable
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

Tip: see GitHub Actions environment variables and expression syntax.

Working directory

In a monorepo, the end-to-end test might be placed in a different sub-folder from the application itself, like this

repo/
  app/
  e2e/
    cypress
    cypress.json
  package.json

You can specify the e2e working directory when running Cypress tests using working-directory parameter

on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    steps:
      - uses: actions/checkout@v1
      - uses: cypress-io/github-action@v1
        with:
          start: npm start
          working-directory: e2e

See cypress-gh-action-monorepo for a running example

Subfolders

Sometimes Cypress and end-to-end tests have their own package.json file in a subfolder, like

root/
  e2e/
    (code for installing and running Cypress tests)
    package.json
    package-lock.json
    cypress.json
    cypress

  (code for running the "app" with "npm start")
  package.json
  yarn.lock

In that case you can combine this action with bahmutov/npm-install action to install dependencies separately.

name: E2E
on: push
jobs:
  test:
    runs-on: ubuntu-16.04
    steps:
      - uses: actions/checkout@master
      - name: Install root dependencies
        uses: bahmutov/npm-install@v1

      - name: Start server in the background
        run: npm start &

      # Cypress has its own package.json in folder "e2e"
      - name: Install Cypress and run tests
        uses: cypress-io/github-action@v1
        with:
          working-directory: e2e

See cypress-gh-action-subfolders for example.

Custom cache key

Sometimes the default cache key does not work. For example, if you cannot share the Node modules across Node versions due to native extensions. In that case pass your own cache-key parameter.

name: End-to-end tests
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-16.04
    # let's make sure our "app" works on several versions of Node
    strategy:
      matrix:
        node: [10, 12]
    name: E2E on Node v${{ matrix.node }}
    steps:
      - name: Setup Node
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node }}
      - name: Checkout
        uses: actions/checkout@v1
      # run Cypress tests and record them under the same run
      # associated with commit SHA and just give a different group name
      - name: Cypress run
        uses: cypress-io/github-action@v1
        with:
          record: true
          group: Tests on Node v${{ matrix.node }}
          cache-key: node-v${{ matrix.node }}-on-${{ runner.os }}-hash-${{ hashFiles('yarn.lock') }}
        env:
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

Split install and tests

Sometimes you may want to run additional commands between installation and tests. To enable this use the install and runTests parameters.

name: E2E
on: push
jobs:
  test:
    runs-on: ubuntu-16.04
    steps:
      - uses: actions/checkout@master
      - name: Install dependencies
        uses: cypress-io/github-action@v1
        with:
          # just perform install
          runTests: false
      - run: yarn lint
      - name: Run e2e tests
        uses: cypress-io/github-action@v1
        with:
          # we have already installed all dependencies above
          install: false
          # Cypress tests and config file are in "e2e" folder
          working-directory: e2e

See cypress-gh-action-monorepo for working example.

Custom install

Finally, you might not need this GH Action at all. For example, if you want to split the NPM dependencies installation from the Cypress binary installation, then it makes no sense to use this action. Instead you can install and cache Cypress yourself. See cypress-gh-action-split-install for working example.

More examples

Name Description
cypress-gh-action-example uses Yarn, and runs in parallel on several versions of Node, also different browsers
cypress-gh-action-monorepo splits install and running tests commands, runs Cypress from sub-folder
cypress-gh-action-subfolders separate folder for Cypress dependencies
cypress-gh-action-split-install only install NPM dependencies, then install and cache Cypress binary yourself
gh-action-and-gh-integration records to the dashboard and has Cypress GH Integration app installed

Notes

Installation

This action installs local dependencies using lock files. If yarn.lock file is found, the install uses yarn --frozen-lockfile command. Otherwise it expects to find package-lock.json and install using npm ci command.

Debugging

You can see verbose messages from GitHub Actions by setting the following secrets (from Debugging Actions Guide)

ACTIONS_RUNNER_DEBUG: true
ACTIONS_STEP_DEBUG: true

Development

Read DEVELOPMENT.md

More information

Extras

If your repository does not have package.json or yarn.json (maybe it contains a static site and does not need any dependencies), you can run Cypress tests using cypress/included:... Cypress Docker images. In that case you don't even need this GH Action, instead use the Docker container and write cypress run command like this example from cypress-gh-action-included

name: included
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-latest
    # Docker image with Cypress pre-installed
    # https://github.com/cypress-io/cypress-docker-images/tree/master/included
    container: cypress/included:3.8.3
    steps:
      - uses: actions/checkout@v1
      - run: cypress run

License

MIT License

About

GitHub Action for running Cypress end-to-end tests

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%