version: 2.1

# usually we don't build Mac app - it takes a long time
# but sometimes we want to really confirm we are doing the right thing
# so just add your branch to the list here to build and test on Mac
macBuildFilters: &macBuildFilters
  filters:
    branches:
      only:
        - develop
        - remove-old-binary-file

defaults: &defaults
  parallelism: 1
  working_directory: ~/cypress
  parameters:
    executor:
      type: executor
      default: cy-doc
  executor: <<parameters.executor>>
  environment:
    ## set specific timezone
    TZ: "/usr/share/zoneinfo/America/New_York"

    ## store artifacts here
    CIRCLE_ARTIFACTS: /tmp/artifacts

    ## set so that e2e tests are consistent
    COLUMNS: 100
    LINES: 24

# filters and requires for testing binary with Firefox
testBinaryFirefox: &testBinaryFirefox
  filters:
    branches:
      only:
        - develop
  requires:
    - build-npm-package
    - build-binary

executors:
  # the Docker image with Cypress dependencies and Chrome browser
  cy-doc:
    docker:
      - image: cypress/browsers:node12.14.1-chrome83-ff77
    environment:
      PLATFORM: linux

  # Docker image with non-root "node" user
  non-root-docker-user:
    docker:
      - image: cypress/browsers:node12.14.1-chrome83-ff77
        user: node
    environment:
      PLATFORM: linux

  # executor to run on Mac OS
  # https://circleci.com/docs/2.0/executor-types/#using-macos
  # https://circleci.com/docs/2.0/testing-ios/#supported-xcode-versions
  mac:
    macos:
      # Executor should have Node >= required version
      xcode: "11.3.1"
    environment:
      PLATFORM: mac

commands:
  install-required-node:
    # https://discuss.circleci.com/t/switch-nodejs-version-on-machine-executor-solved/26675/2
    description: Install Node version matching .node-version
    steps:
      - run:
          name: Install NVM
          # TODO: determine why we get the missing .nvmrc file error
          command: |
            export NODE_VERSION=$(cat .node-version)
            echo "Installing Node $NODE_VERSION"
            cp .node-version .nvmrc
            curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.3/install.sh | bash
      - run:
          # https://github.com/nvm-sh/nvm#nvmrc
          name: Install Node
          command: |
            . ./scripts/load-nvm.sh
            echo "before nvm install"
            nvm install
            echo "before nvm use"
            nvm use
            echo "before nvm alias default"
            nvm alias default
            node --version

  install-latest-chrome:
    description: Install latest Google Chrome (stable)
    parameters:
      browser:
        default: "electron"
        description: browser shortname to target
        type: string
    steps:
      - run:
          name: Install latest Google Chrome (stable)
          command: |
            if [ <<parameters.browser>> == "chrome" ]; then
              echo "**** Running Chrome tests.  Installing latest stable version of Google Chrome. ****"
              apt-get update
              apt-get install google-chrome-stable -y
              echo "**** Location of Google Chrome Installation: "`which google-chrome`" ****"
              echo "**** Google Chrome Version: "`google-chrome --version`" ****"
            else
              echo "**** Not updating Chrome. Running tests in '<<parameters.browser>>' ****"
            fi

  run-driver-integration-tests:
    parameters:
      browser:
        description: browser shortname to target
        type: string
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          environment:
            CYPRESS_KONFIG_ENV: production
          command: |
            echo Current working directory is $PWD
            echo Total containers $CIRCLE_NODE_TOTAL

            if [[ -v PACKAGES_RECORD_KEY ]]; then
              # internal PR
              CYPRESS_RECORD_KEY=$PACKAGES_RECORD_KEY \
              yarn cypress:run --record --parallel --group 5x-driver-<<parameters.browser>> --browser <<parameters.browser>>
            else
              # external PR
              TESTFILES=$(circleci tests glob "cypress/integration/**/*_spec.*" | circleci tests split --total=$CIRCLE_NODE_TOTAL)
              echo "Test files for this machine are $TESTFILES"

              if [[ -z "$TESTFILES" ]]; then
                echo "Empty list of test files"
              fi
              yarn cypress:run --browser <<parameters.browser>> --spec $TESTFILES
            fi
          working_directory: packages/driver
      - verify-mocha-results
      - store_test_results:
          path: /tmp/cypress
      - store_artifacts:
          path: /tmp/artifacts
      - store-npm-logs

  run-runner-integration-tests:
    parameters:
      browser:
        description: browser shortname to target
        type: string
      percy:
        description: enable percy
        type: boolean
        default: false
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          command: |
            cmd=$([[ <<parameters.percy>> == 'true' ]] && echo 'yarn percy exec --') || true

            CYPRESS_KONFIG_ENV=production \
            CYPRESS_RECORD_KEY=$PACKAGES_RECORD_KEY \
            PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_ID \
            PERCY_PARALLEL_TOTAL=-1 \
            $cmd yarn workspace @packages/runner cypress:run --record --parallel --group runner-integration-<<parameters.browser>> --browser <<parameters.browser>>
      - store_test_results:
          path: /tmp/cypress
      - store_artifacts:
          path: /tmp/artifacts
      - store-npm-logs

  run-e2e-tests:
    parameters:
      browser:
        description: browser shortname to target
        type: string
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          command: yarn workspace @packages/server test ./test/e2e/$(( $CIRCLE_NODE_INDEX ))_*spec* --browser <<parameters.browser>>
      - verify-mocha-results
      - store_test_results:
          path: /tmp/cypress
      - store_artifacts:
          path: /tmp/artifacts
      - store-npm-logs

  store-npm-logs:
    description: Saves any NPM debug logs as artifacts in case there is a problem
    steps:
      - store_artifacts:
          path: ~/.npm/_logs

  post-install-comment:
    description: Post GitHub comment with a blurb on how to install pre-release version
    steps:
      - run: ls -la
      - run: ls -la binary-url.json npm-package-url.json
      - run: cat binary-url.json
      - run: cat npm-package-url.json
      - run:
          name: Post pre-release install comment
          command: |
            node scripts/add-install-comment.js \
              --npm npm-package-url.json \
              --binary binary-url.json

  verify-mocha-results:
    description: Double-check that Mocha tests ran as expected.
    parameters:
      expectedResultCount:
        description: The number of result files to expect, ie, the number of Mocha test suites that ran.
        type: integer
        ## by default, assert that at least 1 test ran
        default: 0
    steps:
      - run: yarn verify:mocha:results <<parameters.expectedResultCount>>

  clone-repo-and-checkout-release-branch:
    description: |
      Clones an external repo and then checks out the branch that matches NEXT_DEV_VERSION otherwise uses 'master' branch.
    parameters:
      repo:
        description: "Name of the github repo to clone like: cypress-example-kitchensink"
        type: string
    steps:
      - attach_workspace:
          at: ~/
      - run:
          name: "Cloning test project: <<parameters.repo>>"
          command: |
            git clone --depth 1 --no-single-branch https://github.com/cypress-io/<<parameters.repo>>.git /tmp/<<parameters.repo>>
            cd /tmp/<<parameters.repo>> && (git checkout $NEXT_DEV_VERSION || true)

  test-binary-against-repo:
    description: |
      Takes the built binary and NPM package, clones given example repo
      and runs the new version of Cypress against it.
    parameters:
      repo:
        description: "Name of the github repo to clone like: cypress-example-kitchensink"
        type: string
      browser:
        description: Name of the browser to use, like "electron", "chrome", "firefox"
        type: enum
        enum: ["", "electron", "chrome", "firefox"]
        default: ""
      command:
        description: Test command to run to start Cypress tests
        type: string
        default: "npm run e2e"
      # if the repo to clone and test is a monorepo, you can
      # run tests inside a specific subfolder
      folder:
        description: Subfolder to test in
        type: string
        default: ""
      # you can test new features in the test runner against recipes or other repos
      # by opening a pull request in those repos and running this test job
      # against a pull request number in the example repo
      pull_request_id:
        description: Pull request number to check out before installing and testing
        type: integer
        default: 0
      wait-on:
        description: Whether to use wait-on to wait on a server to be booted
        type: string
        default: ""
      server-start-command:
        description: Server start command for repo
        type: string
        default: "npm start --if-present"
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      # make sure the binary and NPM package files are present
      - run: ls -l
      - run: ls -l cypress.zip cypress.tgz
      - clone-repo-and-checkout-release-branch:
          repo: <<parameters.repo>>
      - when:
          condition: <<parameters.pull_request_id>>
          steps:
            - run:
                name: Check out PR <<parameters.pull_request_id>>
                working_directory: /tmp/<<parameters.repo>>
                command: |
                  git fetch origin pull/<<parameters.pull_request_id>>/head:pr-<<parameters.pull_request_id>>
                  git checkout pr-<<parameters.pull_request_id>>
                  git log -n 2
      - run:
          command: npm install
          working_directory: /tmp/<<parameters.repo>>
      - run:
          name: Install Cypress
          working_directory: /tmp/<<parameters.repo>>
          # force installing the freshly built binary
          command: CYPRESS_INSTALL_BINARY=~/cypress/cypress.zip npm i ~/cypress/cypress.tgz
      - run:
          name: Types check 🧩 (maybe)
          working_directory: /tmp/<<parameters.repo>>
          command: npm run types --if-present
      - run:
          name: Build 🏗 (maybe)
          working_directory: /tmp/<<parameters.repo>>
          command: npm run build --if-present
      - run:
          working_directory: /tmp/<<parameters.repo>>
          command: <<parameters.server-start-command>>
          background: true
      - run:
          condition: <<parameters.wait-on>>
          name: "Waiting on server to boot: <<parameters.wait-on>>"
          command: "npx wait-on <<parameters.wait-on>> --timeout 120000"
      - when:
          condition: <<parameters.folder>>
          steps:
            - when:
                condition: <<parameters.browser>>
                steps:
                  - run:
                      name: Run tests using browser "<<parameters.browser>>"
                      working_directory: /tmp/<<parameters.repo>>/<<parameters.folder>>
                      command: |
                        <<parameters.command>> -- --browser <<parameters.browser>>
            - unless:
                condition: <<parameters.browser>>
                steps:
                  - run:
                      name: Run tests using command
                      working_directory: /tmp/<<parameters.repo>>/<<parameters.folder>>
                      command: <<parameters.command>>

            - store_artifacts:
                name: screenshots
                path: /tmp/<<parameters.repo>>/<<parameters.folder>>/cypress/screenshots
            - store_artifacts:
                name: videos
                path: /tmp/<<parameters.repo>>/<<parameters.folder>>/cypress/videos
      - unless:
          condition: <<parameters.folder>>
          steps:
            - when:
                condition: <<parameters.browser>>
                steps:
                  - run:
                      name: Run tests using browser "<<parameters.browser>>"
                      working_directory: /tmp/<<parameters.repo>>
                      command: <<parameters.command>> -- --browser <<parameters.browser>>
            - unless:
                condition: <<parameters.browser>>
                steps:
                  - run:
                      name: Run tests using command
                      working_directory: /tmp/<<parameters.repo>>
                      command: <<parameters.command>>
            - store_artifacts:
                name: screenshots
                path: /tmp/<<parameters.repo>>/cypress/screenshots
            - store_artifacts:
                name: videos
                path: /tmp/<<parameters.repo>>/cypress/videos
      - store-npm-logs

  wait-on-circle-jobs:
    description: Polls certain Circle CI jobs until they finish
    parameters:
      job-names:
        description: comma separated list of circle ci job names to wait for
        type: string
    steps:
      - run:
          name: "Waiting on Circle CI jobs: <<parameters.job-names>>"
          command: node ./scripts/wait-on-circle-jobs.js --job-names="<<parameters.job-names>>"

  check-halt:
    description: Halt CI if the package that this job corresponds to is unchanged
    steps:
      - run:
          name: Check if job should run
          command: yarn check-halt || circleci-agent step halt

jobs:
  ## code checkout and yarn installs
  build:
    <<: *defaults
    steps:
      - checkout
      - install-required-node
      - run:
          name: Print working folder
          command: echo $PWD
      - run:
          name: print global yarn cache path
          command: echo $(yarn global bin)
      - run:
          name: print Node version
          command: |
            . ./scripts/load-nvm.sh
            echo "nvm use default"
            nvm use default
            node -v
      - run:
          name: print yarn version
          command: yarn -v
      - run:
          name: check Node version
          command: |
            . ./scripts/load-nvm.sh
            yarn check-node-version

      ## make sure the TERM is set to 'xterm' in node (Linux only)
      ## else colors (and tests) will fail
      ## See the following information
      ##   * http://andykdocs.de/development/Docker/Fixing+the+Docker+TERM+variable+issue
      ##   * https://unix.stackexchange.com/questions/43945/whats-the-difference-between-various-term-variables
      - run:
          name: Check terminal
          command: |
            . ./scripts/load-nvm.sh
            yarn check-terminal

      - run:
          name: Stop .only
          command: |
            . ./scripts/load-nvm.sh
            yarn stop-only-all

      - restore_cache:
          name: Restore yarn cache
          key: v{{ .Environment.CACHE_VERSION }}-{{ arch }}-deps-root-{{ checksum "yarn.lock" }}

      # show what is already cached globally
      - run: ls $(yarn global bin)
      - run: ls $(yarn global bin)/../lib/node_modules

      # try several times, because flaky NPM installs ...
      - run:
          name: install and build
          command: |
            . ./scripts/load-nvm.sh
            yarn --frozen-lockfile || yarn --frozen-lockfile
            yarn build-prod
      - run:
          name: Top level packages
          command: yarn list --depth=0 || true

      - store-npm-logs

      - save_cache:
          name: Save yarn cache
          key: v{{ .Environment.CACHE_VERSION }}-{{ arch }}-deps-root-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache

      ## save entire folder as artifact for other jobs to run without reinstalling
      - persist_to_workspace:
          root: ~/
          paths:
            - cypress
            - .ssh

  lint:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - install-required-node
      ## this will catch ".only"s in js/coffee as well
      - run:
          name: Linting 🧹
          command: |
            . ./scripts/load-nvm.sh
            git clean -df
            yarn lint
      - run:
          name: cypress info (dev)
          command: node cli/bin/cypress info --dev
      - store-npm-logs

  list-changed-packages:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - run:
          name: List changed packages
          command: node scripts/changed-packages.js

  # a special job that keeps polling Circle and when all
  # individual jobs are finished, it closes the Percy build
  percy-finalize:
    <<: *defaults
    executor: cy-doc
    parameters:
      required_env_var:
        type: env_var_name
    steps:
      - attach_workspace:
          at: ~/
      - run:
          # if this is an external pull request, the environment variables
          # are NOT set for security reasons, thus no need to poll -
          # and no need to finalize Percy, since there will be no visual tests
          name: Check if <<parameters.required_env_var>> is set
          command: |
            if [[ -v <<parameters.required_env_var>> ]]; then
              echo "Internal PR, good to go"
            else
              echo "This is an external PR, cannot access other services"
              circleci-agent step halt
            fi
      - wait-on-circle-jobs:
          job-names: >
            desktop-gui-integration-tests-2x,
            desktop-gui-component-tests,
            cli-visual-tests,
            runner-integration-tests-chrome,
      - run: npx percy finalize --all

  cli-visual-tests:
    <<: *defaults
    parallelism: 1
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run: mkdir -p cli/visual-snapshots
      - run:
          command: node cli/bin/cypress info --dev | yarn --silent term-to-html | node scripts/sanitize --type cli-info > cli/visual-snapshots/cypress-info.html
          environment:
            FORCE_COLOR: 2
      - run:
          command: node cli/bin/cypress help | yarn --silent term-to-html > cli/visual-snapshots/cypress-help.html
          environment:
            FORCE_COLOR: 2
      - store_artifacts:
          path: cli/visual-snapshots
      - run:
          name: Upload CLI snapshots for diffing
          command: |
            PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_ID \
            PERCY_PARALLEL_TOTAL=-1 \
            yarn percy snapshot ./cli/visual-snapshots

  unit-tests:
    <<: *defaults
    parallelism: 1
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      # make sure mocha runs
      - run: yarn test-mocha
      # test binary build code
      - run: yarn test-scripts
      # make sure our snapshots are compared correctly
      - run: yarn test-mocha-snapshot
      # make sure packages with TypeScript can be transpiled to JS
      - run: yarn lerna run build-prod --stream
      # run unit tests from each individual package
      - run: yarn test
      - verify-mocha-results:
          expectedResultCount: 9
      - store_test_results:
          path: /tmp/cypress
      # CLI tests generate HTML files with sample CLI command output
      - store_artifacts:
          path: cli/test/html
      - store-npm-logs

  lint-types:
    <<: *defaults
    parallelism: 1
    steps:
      - attach_workspace:
          at: ~/
      - run:
          command: ls -la types
          working_directory: cli
      - run:
          command: ls -la chai
          working_directory: cli/types
      - run:
          name: "Lint types 🧹"
          command: yarn workspace cypress dtslint
      - run:
          name: "TypeScript check 🧩"
          command: yarn type-check --ignore-progress
      - store-npm-logs

  build-system-unit-tests:
    <<: *defaults
    parallelism: 1
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - install-required-node
      - run:
          name: Mocha tests
          command: |
            . ./scripts/load-nvm.sh
            yarn test-mocha
      # test binary build code
      - run:
          name: Test scripts
          command: |
            . ./scripts/load-nvm.sh
            yarn test-scripts

  server-unit-tests:
    <<: *defaults
    parallelism: 1
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run: yarn test-unit --scope @packages/server
      - verify-mocha-results:
          expectedResultCount: 1
      - store_test_results:
          path: /tmp/cypress
      - store-npm-logs

  server-integration-tests:
    <<: *defaults
    parallelism: 1
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run: yarn test-integration --scope @packages/server
      - verify-mocha-results:
          expectedResultCount: 1
      - store_test_results:
          path: /tmp/cypress
      - store-npm-logs

  server-performance-tests:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          command: yarn workspace @packages/server test-performance
      - verify-mocha-results:
          expectedResultCount: 1
      - store_test_results:
          path: /tmp/cypress
      - store_artifacts:
          path: /tmp/artifacts
      - store-npm-logs

  server-e2e-tests-chrome:
    <<: *defaults
    parallelism: 8
    steps:
      - run-e2e-tests:
          browser: chrome

  server-e2e-tests-electron:
    <<: *defaults
    parallelism: 8
    steps:
      - run-e2e-tests:
          browser: electron

  server-e2e-tests-firefox:
    <<: *defaults
    parallelism: 8
    steps:
      - run-e2e-tests:
          browser: firefox

  server-e2e-tests-non-root:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - run:
          command: yarn workspace @packages/server test ./test/e2e/non_root*spec* --browser electron
      - verify-mocha-results
      - store_test_results:
          path: /tmp/cypress
      - store_artifacts:
          path: /tmp/artifacts
      - store-npm-logs

  runner-integration-tests-chrome:
    <<: *defaults
    parallelism: 2
    steps:
      - run-runner-integration-tests:
          browser: chrome
          percy: true

  runner-integration-tests-firefox:
    <<: *defaults
    parallelism: 2
    steps:
      - run-runner-integration-tests:
          browser: firefox

  driver-integration-tests-chrome:
    <<: *defaults
    parallelism: 5
    steps:
      - run-driver-integration-tests:
          browser: chrome

  driver-integration-tests-firefox:
    <<: *defaults
    parallelism: 5
    steps:
      - run-driver-integration-tests:
          browser: firefox

  desktop-gui-integration-tests-2x:
    <<: *defaults
    parallelism: 2
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          command: yarn build-prod
          working_directory: packages/desktop-gui
      - run:
          command: |
            CYPRESS_KONFIG_ENV=production \
            CYPRESS_RECORD_KEY=$PACKAGES_RECORD_KEY \
            PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_ID \
            PERCY_PARALLEL_TOTAL=-1 \
            yarn percy exec -- \
            yarn cypress:run --record --parallel --group 2x-desktop-gui
          working_directory: packages/desktop-gui
      - verify-mocha-results
      - store_test_results:
          path: /tmp/cypress
      - store_artifacts:
          path: /tmp/artifacts
      - store-npm-logs

  desktop-gui-visual-tests:
    <<: *defaults
    parallelism: 1
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          command: yarn build-prod
          working_directory: packages/desktop-gui
      - run:
          name: Desktop GUI server
          command: yarn start
          working_directory: packages/desktop-gui
          background: true
      - run:
          # will use PERCY_TOKEN environment variable if available
          # to tie Percy builds together, use environment variables
          # https://docs.percy.io/docs/parallel-test-suites
          # we can use workflow id and list number of jobs with Percy screenshots
          # if we allow Percy snapshots in more jobs, use the same
          # PERCY_* variables in all of them
          # NOTE: we only execute specs with "cy.percySnapshot" commands in them
          command: |
            CYPRESS_KONFIG_ENV=production \
            PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_ID \
            PERCY_PARALLEL_TOTAL=1 \
            yarn percy exec -- \
            yarn cypress:run \
              --spec cypress/integration/settings_spec.js,cypress/integration/specs_list_spec.js,cypress/integration/runs_list_spec.js,cypress/integration/login_spec.js
          working_directory: packages/desktop-gui
      - verify-mocha-results
      # we don't really need any artifacts - we are only interested in visual screenshots
      - store-npm-logs

  desktop-gui-component-tests:
    <<: *defaults
    parallelism: 1
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          # builds JS and CSS, and we need the app CSS
          # to correctly apply component styles
          command: |
            yarn build-prod
            ls -la dist
          working_directory: packages/desktop-gui
      # for now, because we have baseUrl in cypress.json
      # we must start it, even if we don't use it for component tests
      # https://github.com/cypress-io/cypress/issues/7800
      - run:
          name: Unnecessary Desktop GUI server
          command: yarn start
          working_directory: packages/desktop-gui
          background: true
      - run:
          # will use PERCY_TOKEN environment variable if available
          command: |
            CYPRESS_KONFIG_ENV=production \
            PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_ID \
            PERCY_PARALLEL_TOTAL=-1 \
            yarn percy exec -- \
            yarn cypress:run --spec 'src/**/*_spec.jsx'
          working_directory: packages/desktop-gui
      - verify-mocha-results
      # we don't really need any artifacts - we are only interested in visual screenshots
      - store-npm-logs

  reporter-integration-tests:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          command: yarn build-for-tests
          working_directory: packages/reporter
      - run:
          command: |
            CYPRESS_KONFIG_ENV=production \
            CYPRESS_RECORD_KEY=$PACKAGES_RECORD_KEY \
            yarn cypress:run --record --parallel --group reporter
          working_directory: packages/reporter
      - verify-mocha-results
      - store_test_results:
          path: /tmp/cypress
      - store_artifacts:
          path: /tmp/artifacts
      - store-npm-logs

  ui-components-integration-tests:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          command: yarn build-for-tests
          working_directory: packages/ui-components
      - run:
          command: |
            CYPRESS_KONFIG_ENV=production \
            CYPRESS_RECORD_KEY=$PACKAGES_RECORD_KEY \
            yarn cypress:run --record --parallel --group ui-components
          working_directory: packages/ui-components
      - verify-mocha-results
      - store_test_results:
          path: /tmp/cypress
      - store_artifacts:
          path: /tmp/artifacts
      - store-npm-logs

  run-launcher:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          command: node index.js
          working_directory: packages/launcher

  npm-webpack-preprocessor:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          name: Build
          command: yarn workspace @cypress/webpack-preprocessor build
      - run:
          name: Run tests
          command: yarn workspace @cypress/webpack-preprocessor test
      - run:
          name: Test babelrc
          command: yarn test
          working_directory: npm/webpack-preprocessor/examples/use-babelrc
      - run:
          name: Build ts-loader
          command: yarn install
          working_directory: npm/webpack-preprocessor/examples/use-ts-loader
      - run:
          name: Types ts-loader
          command: yarn types
          working_directory: npm/webpack-preprocessor/examples/use-ts-loader
      - run:
          name: Test ts-loader
          command: yarn test
          working_directory: npm/webpack-preprocessor/examples/use-ts-loader
      - run:
          name: Start React app
          command: yarn start
          background: true
          working_directory: npm/webpack-preprocessor/examples/react-app
      - run:
          name: Test React app
          command: yarn test
          working_directory: npm/webpack-preprocessor/examples/react-app
      - store-npm-logs

  npm-vue:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          name: Build
          command: yarn workspace @cypress/vue build
      - run:
          name: Run tests
          command: yarn workspace @cypress/vue test
      - store-npm-logs

  npm-react:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          name: Build
          command: yarn workspace @cypress/react build
      - run:
          name: Run unit test
          command: yarn workspace @cypress/react test:unit
      - run:
          name: Run tests
          command: yarn workspace @cypress/react test
      - store-npm-logs
      - persist_to_workspace:
          root: ~/
          paths: cypress/npm/react

  npm-react-e2e-example:
    <<: *defaults
    description: Run react component testing end-to-end examples
    parameters:
      executor:
        description: Executor name to use
        type: executor
        default: cy-doc
      path:
        description: relative to npm/react path of example
        type: string
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - restore_cache:
          name: Restore Cache
          keys:
            - yarn-packages-{{ checksum "npm/react/<<parameters.path>>/yarn.lock" }}
      - run:
          name: Install Dependencies
          command: yarn install --frozen-lockfile
          working_directory: npm/react/<<parameters.path>>
      - save_cache:
          name: Save Cache
          key: yarn-packages-{{ checksum "npm/react/<<parameters.path>>/yarn.lock" }}
          paths:
            - ~/.cache
      - run:
          name: Run e2e example tests
          command: yarn test
          working_directory: npm/react/<<parameters.path>>

  npm-eslint-plugin-dev:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run:
          name: Run tests
          command: yarn workspace @cypress/eslint-plugin-dev test

  npm-release:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - run:
          name: Release packages
          command: yarn npm-release

  build-binary:
    <<: *defaults
    shell: /bin/bash --login
    steps:
      - run:
          name: Check environment variables before code sign (if on Mac)
          # NOTE
          # our Mac code sign works via electron-builder
          # by default, electron-builder will NOT sign app built in a pull request
          # even our internal one (!)
          # Usually this is not a problem, since we only build and test binary
          # built on "develop" and "master" branches
          # but if you need to really build and sign a Mac binary in a PR
          # set variable CSC_FOR_PULL_REQUEST=true
          command: |
            set -e
            if [[ "$OSTYPE" == "darwin"* ]]; then
              if [ -z "$CSC_LINK" ]; then
                echo "Need to provide environment variable CSC_LINK"
                  echo "with base64 encoded certificate .p12 file"
                exit 1
              fi
              if [ -z "$CSC_KEY_PASSWORD" ]; then
                echo "Need to provide environment variable CSC_KEY_PASSWORD"
                  echo "with password for unlocking certificate .p12 file"
                exit 1
              fi
            else
              echo "Not Mac platform, skipping code sign setup"
            fi

      - attach_workspace:
          at: ~/
      - check-halt
      - run: $(yarn bin)/print-arch
      - install-required-node
      - run:
          environment:
            DEBUG: electron-builder,electron-osx-sign*
          # notarization on Mac can take a while
          no_output_timeout: "30m"
          # if this is a forked pull request, the NEXT_DEV_VERSION environment variable
          # won't be set and we will use default version, since we are not going to
          # upload the dev binary build anywhere
          command: |
            . ./scripts/load-nvm.sh
            node --version
            yarn binary-build --platform $PLATFORM --version ${NEXT_DEV_VERSION:-0.0.0-development}
      - run:
          name: Zip the binary
          command: |
            . ./scripts/load-nvm.sh
            yarn binary-zip --platform $PLATFORM
      # Cypress binary file should be zipped to cypress.zip
      - run: ls -l *.zip
      - store-npm-logs
      - persist_to_workspace:
          root: ~/
          paths:
            - cypress/cypress.zip

  upload-binary:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run: ls -l
      - run:
          name: upload unique binary
          command: |
            node scripts/binary.js upload-unique-binary \
              --file cypress.zip \
              --version $NEXT_DEV_VERSION
      - run: cat binary-url.json
      - store-npm-logs
      - persist_to_workspace:
          root: ~/
          paths:
            - cypress/binary-url.json

  test-kitchensink:
    <<: *defaults
    steps:
      - check-halt
      - clone-repo-and-checkout-release-branch:
          repo: cypress-example-kitchensink
      - install-required-node
      - run:
          name: Install prod dependencies
          command: yarn --production
          working_directory: /tmp/cypress-example-kitchensink
      - run:
          name: Example server
          command: yarn start
          working_directory: /tmp/cypress-example-kitchensink
          background: true
      - run:
          name: Run Kitchensink example project
          command: |
            . ./scripts/load-nvm.sh
            yarn cypress:run --project /tmp/cypress-example-kitchensink
      - store_artifacts:
          path: /tmp/cypress-example-kitchensink/cypress/screenshots
      - store_artifacts:
          path: /tmp/cypress-example-kitchensink/cypress/videos
      - store-npm-logs

  "test-kitchensink-against-staging":
    <<: *defaults
    steps:
      - check-halt
      - clone-repo-and-checkout-release-branch:
          repo: cypress-example-kitchensink
      - run:
          name: Install prod dependencies
          command: yarn --production
          working_directory: /tmp/cypress-example-kitchensink
      - run:
          name: Example server
          command: yarn start
          working_directory: /tmp/cypress-example-kitchensink
          background: true
      - run:
          name: Run Kitchensink example project
          command: |
            CYPRESS_PROJECT_ID=$TEST_KITCHENSINK_PROJECT_ID \
            CYPRESS_RECORD_KEY=$TEST_KITCHENSINK_RECORD_KEY \
            CYPRESS_INTERNAL_ENV=staging \
            CYPRESS_video=false \
            yarn cypress:run --project /tmp/cypress-example-kitchensink --record
      - store-npm-logs

  "test-against-staging":
    <<: *defaults
    steps:
      - check-halt
      - clone-repo-and-checkout-release-branch:
          repo: cypress-test-tiny
      - run:
          name: Run test project
          command: |
            CYPRESS_PROJECT_ID=$TEST_TINY_PROJECT_ID \
            CYPRESS_RECORD_KEY=$TEST_TINY_RECORD_KEY \
            CYPRESS_INTERNAL_ENV=staging \
            yarn cypress:run --project /tmp/cypress-test-tiny --record
      - store-npm-logs

  build-npm-package:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - install-required-node
      - run:
          name: Check next dev version
          command: |
            . ./scripts/load-nvm.sh
            yarn check-next-dev-version
      - run:
          name: bump NPM version
          command: yarn version --no-git-tag-version --new-version ${NEXT_DEV_VERSION:-0.0.0-development}
      - run:
          name: build NPM package
          command: |
            . ./scripts/load-nvm.sh
            yarn build --scope cypress
      - run:
          command: ls -la types
          working_directory: cli/build
      - run:
          name: list NPM package contents
          command: yarn workspace cypress size
      - run:
          name: pack NPM package
          working_directory: cli/build
          command: yarn pack
      - run:
          name: list created NPM package
          working_directory: cli/build
          command: ls -l
      # created file should have filename cypress-<version>.tgz
      - run: mkdir /tmp/urls
      - run: cp cli/build/cypress-v${NEXT_DEV_VERSION:-0.0.0-development}.tgz cypress.tgz
      - run: cp cli/build/cypress-v${NEXT_DEV_VERSION:-0.0.0-development}.tgz /tmp/urls/cypress.tgz
      - run: ls -l /tmp/urls
      - store-npm-logs
      - run: pwd
      - run: ls -l
      - persist_to_workspace:
          root: ~/
          paths:
            - cypress/cypress.tgz

  upload-npm-package:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run: ls -l
      # NPM package file should have filename cypress-<version>.tgz
      - run:
          name: upload NPM package
          command: |
            node scripts/binary.js upload-npm-package \
              --file cypress.tgz \
              --version $NEXT_DEV_VERSION
      - store-npm-logs
      - run: ls -l
      - run: cat npm-package-url.json
      - persist_to_workspace:
          root: ~/
          paths:
            - cypress/npm-package-url.json

  "test-binary-and-npm-against-other-projects":
    <<: *defaults
    steps:
      # needs uploaded NPM and test binary
      - attach_workspace:
          at: ~/
      - check-halt
      - run: ls -la
      # make sure JSON files with uploaded urls are present
      - run: ls -la binary-url.json npm-package-url.json
      - run: cat binary-url.json
      - run: cat npm-package-url.json
      - run: mkdir /tmp/testing
      - run:
          name: create dummy package
          working_directory: /tmp/testing
          command: npm init -y
      - run:
          # install NPM from unique urls
          name: Install Cypress
          command: |
            node scripts/test-unique-npm-and-binary.js \
              --npm npm-package-url.json \
              --binary binary-url.json \
              --cwd /tmp/testing
      - run:
          name: Verify Cypress binary
          working_directory: /tmp/testing
          command: $(yarn bin)/cypress verify
      - run:
          name: Running other test projects with new NPM package and binary
          command: |
            node scripts/test-other-projects.js \
              --npm npm-package-url.json \
              --binary binary-url.json \
              --provider circle
      - store-npm-logs

  post-pre-release-install-comment:
    <<: *defaults
    steps:
      # needs uploaded NPM and test binary
      - attach_workspace:
          at: ~/
      - check-halt
      - run: ls -la
      - post-install-comment

  "test-npm-module-and-verify-binary":
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      # make sure we have cypress.zip received
      - run: ls -l
      - run: ls -l cypress.zip cypress.tgz
      - run: mkdir test-binary
      - run:
          name: Create new NPM package
          working_directory: test-binary
          command: npm init -y
      - run:
          # install NPM from built NPM package folder
          name: Install Cypress
          working_directory: test-binary
          # force installing the freshly built binary
          command: CYPRESS_INSTALL_BINARY=/root/cypress/cypress.zip npm i /root/cypress/cypress.tgz
      - run:
          name: Verify Cypress binary
          working_directory: test-binary
          command: $(yarn bin)/cypress verify
      - run:
          name: Cypress help
          working_directory: test-binary
          command: $(yarn bin)/cypress help
      - run:
          name: Cypress info
          working_directory: test-binary
          command: $(yarn bin)/cypress info
      - store-npm-logs

  test-npm-module-on-minimum-node-version:
    <<: *defaults
    docker:
      - image: cypress/base:10.0.0
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      # make sure we have cypress.zip received
      - run: ls -l
      - run: ls -l cypress.zip cypress.tgz
      - run: mkdir test-binary
      - run: node --version
      - run: npm --version
      - run:
          name: Create new NPM package
          working_directory: test-binary
          command: npm init -y
      - run:
          name: Install Cypress
          working_directory: test-binary
          command: CYPRESS_INSTALL_BINARY=/root/cypress/cypress.zip npm install /root/cypress/cypress.tgz
      - run:
          name: Verify Cypress binary
          working_directory: test-binary
          command: $(npm bin)/cypress verify
      - run:
          name: Print Cypress version
          working_directory: test-binary
          command: $(npm bin)/cypress version
      - run:
          name: Cypress info
          working_directory: test-binary
          command: $(npm bin)/cypress info

  test-types-cypress-and-jest:
    parameters:
      executor:
        description: Executor name to use
        type: executor
        default: cy-doc
      wd:
        description: Working directory, should be OUTSIDE cypress monorepo folder
        type: string
        default: /root/test-cypress-and-jest
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      # make sure we have cypress.zip received
      - run: ls -l
      - run: ls -l cypress.zip cypress.tgz
      - run: mkdir <<parameters.wd>>
      - run: node --version
      - run: npm --version
      - run:
          name: Create new NPM package ⚗️
          working_directory: <<parameters.wd>>
          command: npm init -y
      - run:
          name: Install dependencies 📦
          working_directory: <<parameters.wd>>
          environment:
            CYPRESS_INSTALL_BINARY: /root/cypress/cypress.zip
          # let's install Cypress, Jest and any other package that might conflict
          # https://github.com/cypress-io/cypress/issues/6690
          command: |
            npm install /root/cypress/cypress.tgz \
              typescript jest @types/jest enzyme @types/enzyme
      - run:
          name: Test types clash ⚔️
          working_directory: <<parameters.wd>>
          command: |
            echo "console.log('hello world')" > hello.ts
            npx tsc hello.ts --noEmit

  # testing scaffolding examples and running them
  # against example.cypress.io
  test-cypress-scaffold:
    parameters:
      executor:
        description: Executor name to use
        type: executor
        default: cy-doc
      wd:
        description: Working directory, should be OUTSIDE cypress monorepo folder
        type: string
        default: /root/test-scaffold
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      # make sure we have cypress.zip received
      - run: ls -l
      - run: ls -l cypress.zip cypress.tgz
      - run: mkdir <<parameters.wd>>
      - run: node --version
      - run: npm --version
      - run:
          name: Create new NPM package ⚗️
          working_directory: <<parameters.wd>>
          command: npm init -y
      - run:
          name: Install dependencies 📦
          working_directory: <<parameters.wd>>
          environment:
            CYPRESS_INSTALL_BINARY: /root/cypress/cypress.zip
          # let's install Cypress, Jest and any other package that might conflict
          # https://github.com/cypress-io/cypress/issues/6690
          command: |
            npm install /root/cypress/cypress.tgz \
              typescript jest @types/jest enzyme @types/enzyme
      - run:
          name: Scaffold and test examples 🏗
          working_directory: <<parameters.wd>>
          environment:
            CYPRESS_INTERNAL_FORCE_SCAFFOLD: "1"
          command: |
            echo '{}' > cypress.json
            npx cypress run

  test-full-typescript-project:
    parameters:
      executor:
        description: Executor name to use
        type: executor
        default: cy-doc
      wd:
        description: Working directory, should be OUTSIDE cypress monorepo folder
        type: string
        default: /root/test-full-typescript
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      # make sure we have cypress.zip received
      - run: ls -l
      - run: ls -l cypress.zip cypress.tgz
      - run: mkdir <<parameters.wd>>
      - run: node --version
      - run: npm --version
      - run:
          name: Create new NPM package ⚗️
          working_directory: <<parameters.wd>>
          command: npm init -y
      - run:
          name: Install dependencies 📦
          working_directory: <<parameters.wd>>
          environment:
            CYPRESS_INSTALL_BINARY: /root/cypress/cypress.zip
          command: |
            npm install /root/cypress/cypress.tgz typescript
      - run:
          name: Scaffold full TypeScript project 🏗
          working_directory: <<parameters.wd>>
          command: npx @bahmutov/cly@1 init --typescript
      - run:
          name: Run project tests 🗳
          working_directory: <<parameters.wd>>
          command: npx cypress run

  # install NPM + binary zip and run against staging API
  "test-binary-against-staging":
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      - run: ls -l
      # make sure we have the binary and NPM package
      - run: ls -l cypress.zip cypress.tgz
      - clone-repo-and-checkout-release-branch:
          repo: cypress-test-tiny
      - run:
          name: Install Cypress
          working_directory: /tmp/cypress-test-tiny
          # force installing the freshly built binary
          command: CYPRESS_INSTALL_BINARY=~/cypress/cypress.zip npm i ~/cypress/cypress.tgz
      - run:
          name: Run test project
          working_directory: /tmp/cypress-test-tiny
          command: |
            CYPRESS_PROJECT_ID=$TEST_TINY_PROJECT_ID \
            CYPRESS_RECORD_KEY=$TEST_TINY_RECORD_KEY \
            CYPRESS_INTERNAL_ENV=staging \
            $(yarn bin)/cypress run --record
      - store-npm-logs

  "test-binary-against-recipes-firefox":
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-example-recipes
          command: npm run test:ci:firefox

  # This is a special job. It allows you to test the current
  # built test runner against a pull request in the repo
  # cypress-example-recipes.
  # Imagine you are working on a feature and want to show / test a recipe
  # You would need to run the built test runner before release
  # against a PR that cannot be merged until the new version
  # of the test runner is released.
  # Use:
  #   specify pull request number
  #   and the recipe folder
  test-binary-against-recipe-pull-request:
    <<: *defaults
    steps:
      # test a specific pull request by number from cypress-example-recipes
      - test-binary-against-repo:
          repo: cypress-example-recipes
          command: npm run test:ci
          pull_request_id: 515
          folder: examples/fundamentals__typescript
      - test-binary-against-repo:
          repo: cypress-example-recipes
          command: npm test
          pull_request_id: 513
          folder: examples/fundamentals__module-api-wrap

  "test-binary-against-kitchensink":
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-example-kitchensink
          browser: "electron"

  test-binary-against-awesome-typescript-loader:
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-test-awesome-typescript-loader
          browser: "electron"

  "test-binary-against-kitchensink-firefox":
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-example-kitchensink
          browser: firefox

  "test-binary-against-kitchensink-chrome":
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-example-kitchensink
          browser: chrome

  "test-binary-against-todomvc-firefox":
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-example-todomvc
          browser: firefox

  "test-binary-against-documentation-firefox":
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-documentation
          browser: firefox
          command: "npm run cypress:run"
          wait-on: http://localhost:2222

  "test-binary-against-realworld-firefox":
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-example-realworld
          browser: firefox
          command: "npm run cypress:run"

  "test-binary-against-api-testing-firefox":
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-example-api-testing
          browser: firefox
          command: "npm run cy:run"

  "test-binary-against-piechopper-firefox":
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-example-piechopper
          browser: firefox
          command: "npm run cypress:run"

  "test-binary-against-cypress-realworld-app":
    <<: *defaults
    steps:
      - test-binary-against-repo:
          repo: cypress-realworld-app
          browser: chrome
          server-start-command: "npm run start:ci"
          command: "npm run cypress:run"
          wait-on: http://localhost:3000

  test-binary-as-specific-user:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/
      - check-halt
      # the user should be "node"
      - run: whoami
      - run: pwd
      # prints the current user's effective user id
      # for root it is 0
      # for other users it is a positive integer
      - run: node -e 'console.log(process.geteuid())'
      # make sure the binary and NPM package files are present
      - run: ls -l
      - run: ls -l cypress.zip cypress.tgz
      - run: mkdir test-binary
      - run:
          name: Create new NPM package
          working_directory: test-binary
          command: npm init -y
      - run:
          # install NPM from built NPM package folder
          name: Install Cypress
          working_directory: test-binary
          # force installing the freshly built binary
          command: CYPRESS_INSTALL_BINARY=~/cypress/cypress.zip npm i ~/cypress/cypress.tgz
      - run:
          name: Cypress help
          working_directory: test-binary
          command: $(yarn bin)/cypress help
      - run:
          name: Cypress info
          working_directory: test-binary
          command: $(yarn bin)/cypress info
      - run:
          name: Add Cypress demo
          working_directory: test-binary
          command: npx @bahmutov/cly init
      - run:
          name: Verify Cypress binary
          working_directory: test-binary
          command: DEBUG=cypress:cli $(yarn bin)/cypress verify
      - run:
          name: Run Cypress binary
          working_directory: test-binary
          command: DEBUG=cypress:cli $(yarn bin)/cypress run
      - store-npm-logs

linux-workflow: &linux-workflow
  jobs:
    - build
    - lint:
        name: Linux lint
        requires:
          - build
    - list-changed-packages:
        requires:
          - build
    - percy-finalize:
        context: test-runner:poll-circle-workflow
        required_env_var: PERCY_TOKEN # skips job if not defined (external PR)
        requires:
          - build
    - lint-types:
        requires:
          - build
    # unit, integration and e2e tests
    - cli-visual-tests:
        requires:
          - build
    - build-system-unit-tests:
        requires:
          - build
    - unit-tests:
        requires:
          - build
    - server-unit-tests:
        requires:
          - build
    - server-integration-tests:
        requires:
          - build
    - server-performance-tests:
        requires:
          - build
    - server-e2e-tests-chrome:
        requires:
          - build
    - server-e2e-tests-electron:
        requires:
          - build
    - server-e2e-tests-firefox:
        requires:
          - build
    - server-e2e-tests-non-root:
        executor: non-root-docker-user
        requires:
          - build
    - driver-integration-tests-chrome:
        requires:
          - build
    - driver-integration-tests-firefox:
        requires:
          - build
    - runner-integration-tests-chrome:
        requires:
          - build
    - runner-integration-tests-firefox:
        requires:
          - build

    ## TODO: add these back in when flaky tests are fixed
    # - driver-integration-tests-electron:
    #     requires:
    #       - build
    - desktop-gui-integration-tests-2x:
        requires:
          - build
    - desktop-gui-component-tests:
        requires:
          - build
    - reporter-integration-tests:
        requires:
          - build
    - ui-components-integration-tests:
        requires:
          - build
    - run-launcher:
        requires:
          - build

    - npm-webpack-preprocessor:
        requires:
          - build
    - npm-vue:
        requires:
          - build
    - npm-react:
        requires:
          - build
    # Run tests for end-to-end react component tests examples
    - npm-react-e2e-example:
        name: npm-react-axe
        path: examples/a11y
        requires:
          - npm-react
    - npm-react-e2e-example:
        name: npm-react-next
        path: examples/nextjs
        requires:
          - npm-react
    - npm-react-e2e-example:
        name: npm-react-cra
        path: examples/react-scripts
        requires:
          - npm-react
    - npm-react-e2e-example:
        name: npm-react-cra-folder
        path: examples/react-scripts-folder
        requires:
          - npm-react
    - npm-react-e2e-example:
        name: npm-react-rollup
        path: examples/rollup
        requires:
          - npm-react
    - npm-react-e2e-example:
        name: npm-react-sass-ts
        path: examples/sass-and-ts
        requires:
          - npm-react
    - npm-react-e2e-example:
        name: npm-react-snapshots
        path: examples/snapshots
        requires:
          - npm-react
    - npm-react-e2e-example:
        name: npm-react-tailwind
        path: examples/tailwind
        requires:
          - npm-react
    # Requires Applitools key in the env
    # - npm-react-e2e-example:
    #     name: React + Applitools component testing
    #     path: examples/visual-testing-with-applitools
    #     requires:
    #       - npm-react
    - npm-react-e2e-example:
        name: npm-react-percy
        path: examples/visual-testing-with-percy
        requires:
          - npm-react
    # Requires Happo api key in the env vars
    # - npm-react-e2e-example:
    #     name: React + Happo component testing
    #     path: examples/visual-testing-with-happo
    #     requires:
    #       - npm-react
    - npm-react-e2e-example:
        name: npm-react-webpack-file
        path: examples/webpack-file
        requires:
          - npm-react
    - npm-react-e2e-example:
        name: npm-react-webpack-options
        path: examples/webpack-options
        requires:
          - npm-react

    - npm-eslint-plugin-dev:
        requires:
          - build

    - npm-release:
        requires:
          - build

    # various testing scenarios, like building full binary
    # and testing it on a real project
    - test-against-staging:
        context: test-runner:record-tests
        filters:
          branches:
            only:
              - develop
        requires:
          - build
    - test-kitchensink:
        requires:
          - build
        filters:
          branches:
            ignore:
              ## TODO: remove this upon merging the PR
              - rename-blacklisthosts
              - pull/7622
    - test-kitchensink-against-staging:
        context: test-runner:record-tests
        filters:
          branches:
            only:
              - develop
        requires:
          - build
    - build-npm-package:
        requires:
          - build
    - upload-npm-package:
        context: test-runner:upload
        filters:
          branches:
            only:
              - develop
              - v5.0-release
        requires:
          - build-npm-package
    - build-binary:
        requires:
          - build
    - upload-binary:
        context: test-runner:upload
        filters:
          branches:
            only:
              - develop
              - v5.0-release
        requires:
          - build-binary
    - test-npm-module-on-minimum-node-version:
        requires:
          - build-binary
          - build-npm-package
    - test-types-cypress-and-jest:
        requires:
          - build-binary
          - build-npm-package
    - test-cypress-scaffold:
        requires:
          - build-binary
          - build-npm-package
    - test-full-typescript-project:
        requires:
          - build-binary
          - build-npm-package
    - test-binary-against-kitchensink:
        requires:
          - build-binary
          - build-npm-package
        filters:
          branches:
            ignore:
              ## TODO: remove this upon merging the PR
              - rename-blacklisthosts
              - pull/7622
    # when working on a feature or a fix,
    # you are probably working in a branch
    # and you want to run a specific PR in the cypress-example-recipes
    # against this branch. This workflow job includes
    # the job but only when it runs on specific branch
    # DO NOT DELETE THIS JOB BEFORE MERGING TO DEVELOP
    # on "develop" this branch will be ignored anyway
    # and someone else might use this job definition for another
    # feature branch and would just update the branch filter
    - test-binary-against-recipe-pull-request:
        name: Test cypress run parsing
        filters:
          branches:
            only:
              - cli-to-module-api-7760
        requires:
          - build-binary
          - build-npm-package
    - test-binary-against-awesome-typescript-loader:
        requires:
          - build-binary
          - build-npm-package
    - post-pre-release-install-comment:
        context: test-runner:commit-status-checks
        filters:
          branches:
            only:
              - develop
              - v5.0-release
        requires:
          - upload-npm-package
          - upload-binary
    - test-binary-and-npm-against-other-projects:
        context: test-runner:trigger-test-jobs
        filters:
          branches:
            only:
              - develop
        requires:
          - upload-npm-package
          - upload-binary
    - test-npm-module-and-verify-binary:
        filters:
          branches:
            only:
              - develop
        requires:
          - build-npm-package
          - build-binary
    - test-binary-against-staging:
        context: test-runner:record-tests
        filters:
          branches:
            only:
              - develop
        requires:
          - build-npm-package
          - build-binary

    - test-binary-against-recipes-firefox:
        <<: *testBinaryFirefox
    - test-binary-against-kitchensink-firefox:
        <<: *testBinaryFirefox
    - test-binary-against-kitchensink-chrome:
        <<: *testBinaryFirefox
    - test-binary-against-todomvc-firefox:
        <<: *testBinaryFirefox
    - test-binary-against-documentation-firefox:
        <<: *testBinaryFirefox
    - test-binary-against-api-testing-firefox:
        <<: *testBinaryFirefox
    - test-binary-against-realworld-firefox:
        <<: *testBinaryFirefox
    - test-binary-against-piechopper-firefox:
        <<: *testBinaryFirefox
    - test-binary-against-cypress-realworld-app:
        filters:
          branches:
            only:
              - develop
              - kevin-v5.0-release-rwa
              - v5.0-release
        requires:
          - build-npm-package
          - build-binary

    - test-binary-as-specific-user:
        name: "test binary as a non-root user"
        executor: non-root-docker-user
        requires:
          - build-npm-package
          - build-binary
    - test-binary-as-specific-user:
        name: "test binary as a root user"
        requires:
          - build-npm-package
          - build-binary

mac-workflow: &mac-workflow
  jobs:
    - build:
        name: Mac build
        executor: mac
        <<: *macBuildFilters

    - lint:
        name: Mac lint
        executor: mac
        <<: *macBuildFilters
        requires:
          - Mac build

    - build-system-unit-tests:
        name: Mac build system unit tests
        executor: mac
        requires:
          - Mac build
        <<: *macBuildFilters

    # maybe run all unit tests?

    - build-npm-package:
        name: Mac NPM package
        executor: mac
        requires:
          - Mac build
        <<: *macBuildFilters

    - upload-npm-package:
        name: Mac NPM package upload
        context: test-runner:upload
        executor: mac
        <<: *macBuildFilters
        requires:
          - Mac NPM package

    - build-binary:
        name: Mac binary
        context: test-runner:sign-mac-binary
        executor: mac
        <<: *macBuildFilters
        requires:
          - Mac build

    - upload-binary:
        name: Mac binary upload
        executor: mac
        context: test-runner:upload
        <<: *macBuildFilters
        requires:
          - Mac binary

    - test-kitchensink:
        name: Test Mac Kitchensink
        executor: mac
        <<: *macBuildFilters
        requires:
          - Mac build

    - test-binary-against-kitchensink:
        name: Test Mac binary against kitchensink
        executor: mac
        <<: *macBuildFilters
        requires:
          - Mac NPM package
          - Mac binary

    - test-binary-against-staging:
        context: test-runner:record-tests
        name: Test Mac binary against staging
        executor: mac
        filters:
          branches:
            only:
              - develop
        requires:
          - Mac NPM package
          - Mac binary

    - post-pre-release-install-comment:
        context: test-runner:commit-status-checks
        name: Post Mac pre-release install comment
        executor: mac
        filters:
          branches:
            only:
              - develop
        requires:
          - Mac NPM package upload
          - Mac binary upload

    - test-binary-and-npm-against-other-projects:
        context: test-runner:trigger-test-jobs
        name: Test Mac binary against other projects
        executor: mac
        filters:
          branches:
            only:
              - develop
        requires:
          - Mac NPM package upload
          - Mac binary upload

workflows:
  linux:
    <<: *linux-workflow
  mac:
    <<: *mac-workflow
