diff --git a/.circleci/cache-version.txt b/.circleci/cache-version.txt index 4a355f62e1a3..fc3ae1411bde 100644 --- a/.circleci/cache-version.txt +++ b/.circleci/cache-version.txt @@ -1,3 +1,3 @@ # Bump this version to force CI to re-create the cache from scratch. -10-31-22 +12-01-22 diff --git a/.circleci/config.yml b/.circleci/config.yml index 5696514e87ee..c8cb79d7fd45 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,2907 +1,75 @@ version: 2.1 +setup: true -defaults: &defaults - parallelism: 1 - working_directory: ~/cypress - parameters: &defaultsParameters - executor: - type: executor - default: cy-doc - only-cache-for-root-user: - type: boolean - default: false - executor: <> - environment: &defaultsEnvironment - ## set specific timezone - TZ: "/usr/share/zoneinfo/America/New_York" +orbs: + continuation: circleci/continuation@0.3.1 - ## store artifacts here - CIRCLE_ARTIFACTS: /tmp/artifacts - - ## set so that e2e tests are consistent - COLUMNS: 100 - LINES: 24 - -mainBuildFilters: &mainBuildFilters - filters: - branches: - only: - - develop - - retry-flake - -# 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 -macWorkflowFilters: &darwin-workflow-filters - when: - or: - - equal: [ develop, << pipeline.git.branch >> ] - - equal: [ 'retry-flake', << pipeline.git.branch >> ] - - matches: - pattern: "-release$" - value: << pipeline.git.branch >> - -linuxArm64WorkflowFilters: &linux-arm64-workflow-filters - when: - or: - - equal: [ develop, << pipeline.git.branch >> ] - - equal: [ 'retry-flake', << pipeline.git.branch >> ] - - matches: - pattern: "-release$" - value: << pipeline.git.branch >> - -# uncomment & add to the branch conditions below to disable the main linux -# flow if we don't want to test it for a certain branch -linuxWorkflowExcludeFilters: &linux-x64-workflow-exclude-filters - unless: - or: - - false - -# windows is slow and expensive in CI, so it normally only runs on main branches -# add your branch to this list to run the full Windows build on your PR -windowsWorkflowFilters: &windows-workflow-filters - when: - or: - - equal: [ develop, << pipeline.git.branch >> ] - - equal: [ retry-flake, << pipeline.git.branch >> ] - - matches: - pattern: "-release$" - value: << pipeline.git.branch >> - -executors: - # the Docker image with Cypress dependencies and Chrome browser - cy-doc: - docker: - - image: cypress/browsers:node16.16.0-chrome106-ff99-edge - # by default, we use "medium" to balance performance + CI costs. bump or reduce on a per-job basis if needed. - resource_class: medium - environment: - PLATFORM: linux - CI_DOCKER: "true" - - # Docker image with non-root "node" user - non-root-docker-user: +jobs: + verify-ci-should-run: docker: - - image: cypress/browsers:node16.16.0-chrome106-ff99-edge - 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: "14.0.0" - resource_class: macos.x86.medium.gen2 - environment: - PLATFORM: darwin - - # executor to run on Windows - based off of the windows-orb default executor since it is - # not customizable enough to align with our existing setup. - # https://github.com/CircleCI-Public/windows-orb/blob/master/src/executors/default.yml - # https://circleci.com/docs/2.0/hello-world-windows/#software-pre-installed-in-the-windows-image - windows: &windows-executor - machine: - image: windows-server-2019-vs2019:stable - shell: bash.exe -eo pipefail - resource_class: windows.large - environment: - PLATFORM: windows - - darwin-arm64: &darwin-arm64-executor - machine: true - environment: - PLATFORM: darwin - - linux-arm64: &linux-arm64-executor - machine: - image: ubuntu-2004:2022.04.1 - resource_class: arm.medium - environment: - PLATFORM: linux - # TODO: Disabling snapshots for now on Linux Arm 64 architectures. Will revisit with https://github.com/cypress-io/cypress/issues/23557 - DISABLE_SNAPSHOT_REQUIRE: 1 - -commands: - verify_should_persist_artifacts: + - image: cimg/node:current steps: - run: - name: Check current branch to persist artifacts + name: Verify CI should run command: | - if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "retry-flake" ]]; then - echo "Not uploading artifacts or posting install comment for this branch." - circleci-agent step halt + # run CI when manually triggers via CircleCi Dashboard + if [ <> == 'api' ]; then + echo "Always run CI when manually triggered from the UI." + exit 0 fi - restore_workspace_binaries: - steps: - - attach_workspace: - at: ~/ - # make sure we have cypress.zip received - - run: ls -l - - run: ls -l cypress.zip cypress.tgz - - run: node --version - - run: npm --version - - restore_cached_workspace: - steps: - - attach_workspace: - at: ~/ - - install-required-node - - unpack-dependencies - - restore_cached_binary: - steps: - - attach_workspace: - at: ~/ - - prepare-modules-cache: - parameters: - dont-move: - type: boolean - default: false - steps: - - run: node scripts/circle-cache.js --action prepare - - unless: - condition: << parameters.dont-move >> - steps: - - run: - name: Move to /tmp dir for consistent caching across root/non-root users - command: | - mkdir -p /tmp/node_modules_cache - mv ~/cypress/node_modules /tmp/node_modules_cache/root_node_modules - mv ~/cypress/cli/node_modules /tmp/node_modules_cache/cli_node_modules - mv ~/cypress/system-tests/node_modules /tmp/node_modules_cache/system-tests_node_modules - mv ~/cypress/globbed_node_modules /tmp/node_modules_cache/globbed_node_modules - - install-webkit-deps: - steps: - - run: - name: Install WebKit dependencies - command: | - npx playwright install webkit - npx playwright install-deps webkit - - build-and-persist: - description: Save entire folder as artifact for other jobs to run without reinstalling - steps: - - run: - name: Build all codegen - command: | - source ./scripts/ensure-node.sh - yarn gulp buildProd - - run: - name: Build packages - command: | - source ./scripts/ensure-node.sh - yarn build - - run: - name: Generate v8 snapshot - command: | - source ./scripts/ensure-node.sh - yarn build-v8-snapshot-prod - - prepare-modules-cache # So we don't throw these in the workspace cache - - persist_to_workspace: - root: ~/ - paths: - - cypress - - .ssh - - node_modules # contains the npm i -g modules - - install_cache_helpers_dependencies: - steps: - - run: - # Dependencies needed by circle-cache.js, before we "yarn" or unpack cached node_modules - name: Cache Helper Dependencies - working_directory: ~/ - command: npm i glob@7.1.6 fs-extra@10.0.0 minimist@1.2.5 fast-json-stable-stringify@2.1.0 - - unpack-dependencies: - description: 'Unpacks dependencies associated with the current workflow' - steps: - - install_cache_helpers_dependencies - - run: - name: Generate Circle Cache Key - command: node scripts/circle-cache.js --action cacheKey > circle_cache_key - - run: - name: Generate platform key - command: node ./scripts/get-platform-key.js > platform_key - - restore_cache: - name: Restore cache state, to check for known modules cache existence - key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-node-modules-cache-{{ checksum "circle_cache_key" }} - - run: - name: Move node_modules back from /tmp - command: | - if [[ -d "/tmp/node_modules_cache" ]]; then - mv /tmp/node_modules_cache/root_node_modules ~/cypress/node_modules - mv /tmp/node_modules_cache/cli_node_modules ~/cypress/cli/node_modules - mv /tmp/node_modules_cache/system-tests_node_modules ~/cypress/system-tests/node_modules - mv /tmp/node_modules_cache/globbed_node_modules ~/cypress/globbed_node_modules - rm -rf /tmp/node_modules_cache - fi - - run: - name: Restore all node_modules to proper workspace folders - command: node scripts/circle-cache.js --action unpack - - restore_cached_system_tests_deps: - description: 'Restore the cached node_modules for projects in "system-tests/projects/**"' - steps: - - run: - name: Generate Circle Cache key for system tests - command: ./system-tests/scripts/cache-key.sh > system_tests_cache_key - - run: - name: Generate platform key - command: node ./scripts/get-platform-key.js > platform_key - - restore_cache: - name: Restore system tests node_modules cache - keys: - - v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }} - - update_cached_system_tests_deps: - description: 'Update the cached node_modules for projects in "system-tests/projects/**"' - steps: - - run: - name: Generate Circle Cache key for system tests - command: ./system-tests/scripts/cache-key.sh > system_tests_cache_key - - run: - name: Generate platform key - command: node ./scripts/get-platform-key.js > platform_key - - restore_cache: - name: Restore cache state, to check for known modules cache existence - keys: - - v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-state-of-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }} - - run: - name: Send root honeycomb event for this CI build - command: cd system-tests/scripts && node ./send-root-honeycomb-event.js - - run: - name: Bail if specific cache exists - command: | - if [[ -f "/tmp/system_tests_node_modules_installed" ]]; then - echo "No updates to system tests node modules, exiting" - circleci-agent step halt - fi - - restore_cache: - name: Restore system tests node_modules cache - keys: - - v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }} - - v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-system-tests-projects-node-modules-cache- - - run: - name: Update system-tests node_modules cache - command: yarn workspace @tooling/system-tests projects:yarn:install - - save_cache: - name: Save system tests node_modules cache - key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }} - paths: - - /tmp/cy-system-tests-node-modules - - run: touch /tmp/system_tests_node_modules_installed - - save_cache: - name: Save system tests node_modules cache state key - key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-state-of-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }} - paths: - - /tmp/system_tests_node_modules_installed - - caching-dependency-installer: - description: 'Installs & caches the dependencies based on yarn lock & package json dependencies' - parameters: - only-cache-for-root-user: - type: boolean - default: false - steps: - - install_cache_helpers_dependencies - - run: - name: Generate Circle Cache Key - command: node scripts/circle-cache.js --action cacheKey > circle_cache_key - - run: - name: Generate platform key - command: node ./scripts/get-platform-key.js > platform_key - - restore_cache: - name: Restore cache state, to check for known modules cache existence - key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-state-of-node-modules-cache-{{ checksum "circle_cache_key" }} - - run: - name: Bail if cache exists - command: | - if [[ -f "node_modules_installed" ]]; then - echo "Node modules already cached for dependencies, exiting" - circleci-agent step halt + if [[ "$CIRCLE_BRANCH" == "develop" || "$CIRCLE_BRANCH" == "release/"* ]]; then + echo "Always run CI for develop and for release candidate branches." + exit 0 fi - - run: date +%Y-%U > cache_date - - restore_cache: - name: Restore weekly yarn cache - keys: - - v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-deps-root-weekly-{{ checksum "cache_date" }} - - run: - name: Install Node Modules - command: | - source ./scripts/ensure-node.sh - # avoid installing Percy's Chromium every time we use @percy/cli - # https://docs.percy.io/docs/caching-asset-discovery-browser-in-ci - PERCY_POSTINSTALL_BROWSER=true \ - yarn --prefer-offline --frozen-lockfile --cache-folder ~/.yarn - no_output_timeout: 20m - - prepare-modules-cache: - dont-move: <> # we don't move, so we don't hit any issues unpacking symlinks - - when: - condition: <> # we don't move to /tmp since we don't need to worry about different users - steps: - - save_cache: - name: Saving node modules for root, cli, and all globbed workspace packages - key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-node-modules-cache-{{ checksum "circle_cache_key" }} - paths: - - node_modules - - cli/node_modules - - system-tests/node_modules - - globbed_node_modules - - unless: - condition: <> - steps: - - save_cache: - name: Saving node modules for root, cli, and all globbed workspace packages - key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-node-modules-cache-{{ checksum "circle_cache_key" }} - paths: - - /tmp/node_modules_cache - - run: touch node_modules_installed - - save_cache: - name: Saving node-modules cache state key - key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-state-of-node-modules-cache-{{ checksum "circle_cache_key" }} - paths: - - node_modules_installed - - save_cache: - name: Save weekly yarn cache - key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-deps-root-weekly-{{ checksum "cache_date" }} - paths: - - ~/.yarn - - ~/.cy-npm-cache - - verify-build-setup: - description: Common commands run when setting up for build or yarn install - parameters: - executor: - type: executor - default: cy-doc - steps: - - run: pwd - - run: - name: print global yarn cache path - command: echo $(yarn global bin) - - run: - name: print yarn version - command: yarn versions - - unless: - condition: - # stop-only does not correctly match on windows: https://github.com/bahmutov/stop-only/issues/78 - equal: [ *windows-executor, << parameters.executor >> ] - steps: - - run: - name: Stop .only - # this will catch ".only"s in js/coffee as well - command: | - source ./scripts/ensure-node.sh - yarn stop-only-all - - run: - name: Check terminal variables - ## 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 - command: | - source ./scripts/ensure-node.sh - yarn check-terminal - - 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: - # installing NVM will use git+ssh, so update known_hosts - - update_known_hosts - - run: - name: Install Node - command: | - node_version=$(cat .node-version) - source ./scripts/ensure-node.sh - echo "Installing Yarn" - npm install yarn -g # ensure yarn is installed with the correct node engine - yarn check-node-version - - run: - name: Check Node - command: | - source ./scripts/ensure-node.sh - yarn check-node-version - install-chrome: - description: Install Google Chrome - parameters: - channel: - description: browser channel to install - type: string - version: - description: browser version to install - type: string - steps: - - run: - name: Install Google Chrome (<>) - command: | - echo "Installing Chrome (<>) v<>" - wget -O /usr/src/google-chrome-<>_<>_amd64.deb "http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-<>/google-chrome-<>_<>-1_amd64.deb" && \ - dpkg -i /usr/src/google-chrome-<>_<>_amd64.deb ; \ - apt-get install -f -y && \ - rm -f /usr/src/google-chrome-<>_<>_amd64.deb - which google-chrome-<> || (printf "\n\033[0;31mChrome was not successfully downloaded - bailing\033[0m\n\n" && exit 1) - echo "Location of Google Chrome Installation: `which google-chrome-<>`" - echo "Google Chrome Version: `google-chrome-<> --version`" + LAST_COMMIT_MESSAGE=$(curl --silent "https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commits/${CIRCLE_BRANCH}" | jq '.commit.message') - run-driver-integration-tests: - parameters: - browser: - description: browser shortname to target - type: string - install-chrome-channel: - description: chrome channel to install - type: string - default: '' - experimentalSessionAndOrigin: - description: experimental flag to apply - type: boolean - default: false - steps: - - restore_cached_workspace - - when: - condition: <> - steps: - - install-chrome: - channel: <> - version: $(node ./scripts/get-browser-version.js chrome:<>) - - when: - condition: - equal: [ webkit, << parameters.browser >> ] - steps: - - install-webkit-deps - - run: - name: Run driver tests in Cypress - environment: - CYPRESS_CONFIG_ENV: production - command: | - echo Current working directory is $PWD - echo Total containers $CIRCLE_NODE_TOTAL - - if [[ -v MAIN_RECORD_KEY ]]; then - # internal PR - if <>; then - CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ - yarn cypress:run-experimentalSessionAndOrigin --record --parallel --group 5x-driver-<>-experimentalSessionAndOrigin --browser <> - else - CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ - yarn cypress:run --record --parallel --group 5x-driver-<> --browser <> - fi - else - # external PR - TESTFILES=$(circleci tests glob "cypress/e2e/**/*.cy.*" | 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 - if <>; then - yarn cypress:run-experimentalSessionAndOrigin --browser <> --spec $TESTFILES - else - yarn cypress:run --browser <> --spec $TESTFILES - fi + if [[ "$LAST_COMMIT_MESSAGE" =~ "run ci" ]]; then + echo "Always run CI when the commit message includes 'run ci'." + exit 0 fi - working_directory: packages/driver - - verify-mocha-results - - store_test_results: - path: /tmp/cypress - - store_artifacts: - path: /tmp/artifacts - - store-npm-logs - windows-install-chrome: - parameters: - browser: - description: browser shortname to target - type: string - steps: - - run: - # TODO: How can we have preinstalled browsers on CircleCI? - name: 'Install Chrome on Windows' - command: | - # install with `--ignore-checksums` to avoid checksum error - # https://www.gep13.co.uk/blog/chocolatey-error-hashes-do-not-match - [[ $PLATFORM == 'windows' && '<>' == 'chrome' ]] && choco install googlechrome --ignore-checksums || [[ $PLATFORM != 'windows' ]] - - run-new-ui-tests: - parameters: - package: - description: package to target - type: enum - enum: ['frontend-shared', 'launchpad', 'app', 'reporter'] - browser: - description: browser shortname to target - type: string - percy: - description: enable percy - type: boolean - default: false - type: - description: ct or e2e - type: enum - enum: ['ct', 'e2e'] - debug: - description: debug option - type: string - default: '' - steps: - - restore_cached_workspace - - windows-install-chrome: - browser: <> - - run: - command: | - echo Current working directory is $PWD - echo Total containers $CIRCLE_NODE_TOTAL - - if [[ -v MAIN_RECORD_KEY ]]; then - # internal PR - cmd=$([[ <> == 'true' ]] && echo 'yarn percy exec --parallel -- --') || true - DEBUG=<> \ - CYPRESS_CONFIG_ENV=production \ - CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ - PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ - PERCY_ENABLE=${PERCY_TOKEN:-0} \ - PERCY_PARALLEL_TOTAL=-1 \ - $cmd yarn workspace @packages/<> cypress:run:<> --browser <> --record --parallel --group <>-<> - else - # external PR + cancel_build () { + echo "Canceling the CI build..." + curl --request POST \ + --url https://circleci.com/api/v2/workflow/$CIRCLE_WORKFLOW_ID/cancel \ + --header "Circle-Token: ${CIRCLE_TOKEN}" + sleep 30 # Give cancellation a chance to run. This script then won't continue running. + exit 1 # If cancellation didn't run for some reason, fail the build. + } - # To make `circleci tests` work correctly, we need to step into the package folder. - cd packages/<> + TRIGGER_INSTRUCTIONS="to trigger CI , include 'run ci' in the commit message or click the 'Trigger Pipeline' button in the CircleCI UI." - GLOB="cypress/e2e/**/*cy.*" + if [ ! -z "${CIRCLE_PULL_REQUEST##*/}" ]; then + DRAFT=$(curl --silent "https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/pulls/${CIRCLE_PULL_REQUEST##*/}" | jq '.draft') - if [[ <> == 'ct' ]]; then - # component tests are located side by side with the source codes. - GLOB="src/**/*cy.*" + if [[ "${DRAFT}" == true ]]; then + echo "Skipping CI; PR is in draft - $TRIGGER_INSTRUCTIONS" + cancel_build fi - TESTFILES=$(circleci tests glob "$GLOB" | circleci tests split --total=$CIRCLE_NODE_TOTAL) - echo "Test files for this machine are $TESTFILES" - - # To run the `yarn` command, we need to walk out of the package folder. - cd ../.. - - DEBUG=<> \ - CYPRESS_CONFIG_ENV=production \ - PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ - PERCY_ENABLE=${PERCY_TOKEN:-0} \ - PERCY_PARALLEL_TOTAL=-1 \ - yarn workspace @packages/<> cypress:run:<> --browser <> --spec $TESTFILES + echo "Always run CI for PR that is ready for review." + exit 0 fi - - run: - command: | - if [[ <> == 'app' && <> == 'true' && -d "packages/app/cypress/screenshots/runner/screenshot/screenshot.cy.tsx/percy" ]]; then - PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ - PERCY_ENABLE=${PERCY_TOKEN:-0} \ - PERCY_PARALLEL_TOTAL=-1 \ - yarn percy upload packages/app/cypress/screenshots/runner/screenshot/screenshot.cy.tsx/percy - else - echo "skipping percy screenshots uploading" - fi - - store_test_results: - path: /tmp/cypress - - store_artifacts: - path: ./packages/<>/cypress/videos - - store-npm-logs - - run-system-tests: - parameters: - browser: - description: browser shortname to target - type: string - steps: - - restore_cached_workspace - - restore_cached_system_tests_deps - - when: - condition: - equal: [ webkit, << parameters.browser >> ] - steps: - - install-webkit-deps - - run: - name: Run system tests - command: | - ALL_SPECS=`circleci tests glob "/root/cypress/system-tests/test/*spec*"` - SPECS= - for file in $ALL_SPECS; do - # filter out non_root tests, they have their own stage - if [[ "$file" == *"non_root"* ]]; then - echo "Skipping $file" - continue - fi - SPECS="$SPECS $file" - done - SPECS=`echo $SPECS | xargs -n 1 | circleci tests split --split-by=timings` - echo SPECS=$SPECS - yarn workspace @tooling/system-tests test:ci $SPECS --browser <> - - verify-mocha-results - - store_test_results: - path: /tmp/cypress - - store_artifacts: - path: /tmp/artifacts - - store-npm-logs - - run-binary-system-tests: - steps: - - restore_cached_workspace - - restore_cached_system_tests_deps - - run: - name: Run system tests - command: | - ALL_SPECS=`circleci tests glob "$HOME/cypress/system-tests/test-binary/*spec*"` - SPECS=`echo $ALL_SPECS | xargs -n 1 | circleci tests split --split-by=timings` - echo SPECS=$SPECS - yarn workspace @tooling/system-tests test:ci $SPECS - - 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: - 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: - name: 'Verify Mocha Results' - command: | - source ./scripts/ensure-node.sh - yarn verify:mocha:results <> - - clone-repo-and-checkout-branch: - description: | - Clones an external repo and then checks out the branch that matches the next version otherwise uses 'master' branch. - parameters: - repo: - description: "Name of the github repo to clone like: cypress-example-kitchensink" - type: string - pull_request_id: - description: Pull request number to check out before installing and testing - type: integer - default: 0 - steps: - - restore_cached_binary - - run: - name: "Cloning test project and checking out release branch: <>" - working_directory: /tmp/<> - command: | - git clone --depth 1 --no-single-branch https://github.com/cypress-io/<>.git . - - cd ~/cypress/.. - # install some deps for get-next-version - npm i semver@7.3.2 conventional-recommended-bump@6.1.0 conventional-changelog-angular@5.0.12 - NEXT_VERSION=$(node ./cypress/scripts/get-next-version.js) - cd - - - git checkout $NEXT_VERSION || true - - when: - condition: <> - steps: - - run: - name: Check out PR <> - working_directory: /tmp/<> - command: | - git fetch origin pull/<>/head:pr-<> - git checkout pr-<> - - test-binary-against-rwa: - description: | - Takes the built binary and NPM package, clones the RWA repo - and runs the new version of Cypress against it. - parameters: - repo: - description: "Name of the github repo to clone like" - type: string - default: "cypress-realworld-app" - 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: "yarn cypress:run" - # 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: "CI=true yarn start" - steps: - - clone-repo-and-checkout-branch: - repo: <> - - when: - condition: <> - steps: - - run: - name: Check out PR <> - working_directory: /tmp/<> - command: | - git fetch origin pull/<>/head:pr-<> - git checkout pr-<> - git log -n 2 - - run: - command: yarn - working_directory: /tmp/<> - - run: - name: Install Cypress - working_directory: /tmp/<> - # force installing the freshly built binary - command: | - CYPRESS_INSTALL_BINARY=~/cypress/cypress.zip npm i --legacy-peer-deps ~/cypress/cypress.tgz && [[ -f yarn.lock ]] && yarn - - run: - name: Print Cypress version - working_directory: /tmp/<> - command: npx cypress version - - run: - name: Types check 🧩 (maybe) - working_directory: /tmp/<> - command: yarn types - - run: - working_directory: /tmp/<> - command: <> - background: true - - run: - condition: <> - name: "Waiting on server to boot: <>" - command: "npx wait-on <>" - - when: - condition: <> - steps: - - when: - condition: <> - steps: - - run: - name: Run tests using browser "<>" - working_directory: /tmp/<>/<> - command: | - <> -- --browser <> - - unless: - condition: <> - steps: - - run: - name: Run tests using command - working_directory: /tmp/<>/<> - command: <> - - unless: - condition: <> - steps: - - when: - condition: <> - steps: - - run: - name: Run tests using browser "<>" - working_directory: /tmp/<> - command: <> -- --browser <> - - unless: - condition: <> - steps: - - run: - name: Run tests using command - working_directory: /tmp/<> - command: <> - - store-npm-logs - - 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" - build-project: - description: Should the project build script be executed - type: boolean - default: true - # 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: - - clone-repo-and-checkout-branch: - repo: <> - pull_request_id: <> - - run: - # Ensure we're installing the node-version for the cloned repo - command: | - if [[ -f .node-version ]]; then - branch="<< pipeline.git.branch >>" - - externalBranchPattern='^pull\/[0-9]+' - if [[ $branch =~ $externalBranchPattern ]]; then - # We are unable to curl from the external PR branch location - # so we fall back to develop - branch="develop" - fi - - curl -L https://raw.githubusercontent.com/cypress-io/cypress/$branch/scripts/ensure-node.sh --output ci-ensure-node.sh - else - # if no .node-version file exists, we no-op the node script and use the global yarn - echo '' > ci-ensure-node.sh - fi - working_directory: /tmp/<> - - run: - # Install deps + Cypress binary with yarn if yarn.lock present - command: | - source ./ci-ensure-node.sh - if [[ -f yarn.lock ]]; then - yarn --frozen-lockfile - CYPRESS_INSTALL_BINARY=~/cypress/cypress.zip yarn add -D ~/cypress/cypress.tgz - else - npm install - CYPRESS_INSTALL_BINARY=~/cypress/cypress.zip npm install --legacy-peer-deps ~/cypress/cypress.tgz - fi - working_directory: /tmp/<> - - run: - name: Scaffold new config file - working_directory: /tmp/<> - environment: - CYPRESS_INTERNAL_FORCE_SCAFFOLD: "1" - command: | - if [[ -f cypress.json ]]; then - rm -rf cypress.json - echo 'module.exports = { e2e: {} }' > cypress.config.js - fi - - run: - name: Rename support file - working_directory: /tmp/<> - command: | - if [[ -f cypress/support/index.js ]]; then - mv cypress/support/index.js cypress/support/e2e.js - fi - - run: - name: Print Cypress version - working_directory: /tmp/<> - command: | - source ./ci-ensure-node.sh - npx cypress version - - run: - name: Types check 🧩 (maybe) - working_directory: /tmp/<> - command: | - source ./ci-ensure-node.sh - [[ -f yarn.lock ]] && yarn types || npm run types --if-present - - when: - condition: <> - steps: - - run: - name: Build 🏗 (maybe) - working_directory: /tmp/<> - command: | - source ./ci-ensure-node.sh - [[ -f yarn.lock ]] && yarn build || npm run build --if-present - - run: - working_directory: /tmp/<> - command: | - source ./ci-ensure-node.sh - <> - background: true - - run: - condition: <> - name: "Waiting on server to boot: <>" - command: | - npx wait-on <> --timeout 120000 - - windows-install-chrome: - browser: <> - - when: - condition: <> - steps: - - when: - condition: <> - steps: - - run: - name: Run tests using browser "<>" - working_directory: /tmp/<>/<> - command: | - <> -- --browser <> - - unless: - condition: <> - steps: - - run: - name: Run tests using command - working_directory: /tmp/<>/<> - command: <> - - unless: - condition: <> - steps: - - when: - condition: <> - steps: - - run: - name: Run tests using browser "<>" - working_directory: /tmp/<> - command: | - source ./ci-ensure-node.sh - <> -- --browser <> - - unless: - condition: <> - steps: - - run: - name: Run tests using command - working_directory: /tmp/<> - command: | - source ./ci-ensure-node.sh - <> - - 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: <>" - command: node ./scripts/wait-on-circle-jobs.js --job-names="<>" - - build-binary: - steps: - - run: - name: Check environment variables before code sign (if on Mac/Windows) - # NOTE - # our 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 the "develop" branch - # but if you need to really build and sign a binary in a PR - # set variable CSC_FOR_PULL_REQUEST=true - command: | - set -e - NEEDS_CODE_SIGNING=`node -p 'process.platform === "win32" || process.platform === "darwin"'` - if [[ "$NEEDS_CODE_SIGNING" == "true" ]]; then - echo "Checking for required environment variables..." - 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 - echo "Succeeded." - else - echo "Not code signing for this platform" - fi - - run: - name: Build the Cypress binary - environment: - DEBUG: electron-builder,electron-osx-sign* - # notarization on Mac can take a while - no_output_timeout: "45m" - command: | - source ./scripts/ensure-node.sh - node --version - if [[ `node ./scripts/get-platform-key.js` == 'linux-arm64' ]]; then - # these are missing on Circle and there is no way to pre-install them on Arm - sudo apt-get update - sudo apt-get install -y libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb - DISABLE_SNAPSHOT_REQUIRE=1 yarn binary-build --version $(node ./scripts/get-next-version.js) - else - yarn binary-build --version $(node ./scripts/get-next-version.js) - fi - - run: - name: Zip the binary - command: | - if [[ $PLATFORM == 'linux' ]]; then - # on Arm, CI runs as non-root, on x64 CI runs as root but there is no sudo binary - if [[ `whoami` == 'root' ]]; then - apt-get update && apt-get install -y zip - else - sudo apt-get update && sudo apt-get install -y zip - fi - fi - source ./scripts/ensure-node.sh - yarn binary-zip - - store-npm-logs - - persist_to_workspace: - root: ~/ - paths: - - cypress/cypress.zip - - build-cypress-npm-package: - parameters: - executor: - type: executor - default: cy-doc - steps: - - run: - name: Bump NPM version - command: | - source ./scripts/ensure-node.sh - yarn get-next-version --npm - - run: - name: Build NPM package - command: | - source ./scripts/ensure-node.sh - yarn build --scope cypress - - run: - name: Copy Re-exported NPM Packages - command: node ./scripts/post-build.js - working_directory: cli - - run: - command: ls -la types - working_directory: cli/build - - run: - command: ls -la vue vue2 mount-utils react - working_directory: cli/build - - unless: - condition: - equal: [ *windows-executor, << parameters.executor >> ] - steps: - - run: - name: list NPM package contents - command: | - source ./scripts/ensure-node.sh - yarn workspace cypress size - - run: - name: pack NPM package - working_directory: cli/build - command: yarn pack --filename ../../cypress.tgz - - run: - name: list created NPM package - command: ls -l - - store-npm-logs - - persist_to_workspace: - root: ~/ - paths: - - cypress/cypress.tgz - - upload-build-artifacts: - steps: - - run: ls -l - - run: - name: Upload unique binary to S3 - command: | - node scripts/binary.js upload-build-artifact \ - --type binary \ - --file cypress.zip \ - --version $(node -p "require('./package.json').version") - - run: - name: Upload NPM package to S3 - command: | - node scripts/binary.js upload-build-artifact \ - --type npm-package \ - --file cypress.tgz \ - --version $(node -p "require('./package.json').version") - - store-npm-logs - - run: ls -l - - run: cat binary-url.json - - run: cat npm-package-url.json - - persist_to_workspace: - root: ~/ - paths: - - cypress/binary-url.json - - cypress/npm-package-url.json - - update_known_hosts: - description: Ensures that we have the latest Git public keys to prevent git+ssh from failing. - steps: - - run: - name: Update known_hosts with github.com keys - command: | - mkdir -p ~/.ssh - ssh-keyscan github.com >> ~/.ssh/known_hosts - -jobs: - ## Checks if we already have a valid cache for the node_modules_install and if it has, - ## skips ahead to the build step, otherwise installs and caches the node_modules - node_modules_install: - <<: *defaults - parameters: - <<: *defaultsParameters - resource_class: - type: string - default: medium - resource_class: << parameters.resource_class >> - steps: - - checkout - - install-required-node - - verify-build-setup: - executor: << parameters.executor >> - - persist_to_workspace: - root: ~/ - paths: - - cypress - - .nvm # mac / linux - - ProgramData/nvm # windows - - caching-dependency-installer: - only-cache-for-root-user: <> - - store-npm-logs - - ## restores node_modules from previous step & builds if first step skipped - build: - <<: *defaults - parameters: - <<: *defaultsParameters - resource_class: - type: string - default: large - resource_class: << parameters.resource_class >> - steps: - - restore_cached_workspace - - run: - name: Top level packages - command: yarn list --depth=0 || true - - run: - name: Check env canaries on Linux - command: | - # only Docker has the required env data for this - if [[ $CI_DOCKER == 'true' ]]; then - node ./scripts/circle-env.js --check-canaries - fi - - build-and-persist - - store-npm-logs - - lint: - <<: *defaults - steps: - - restore_cached_workspace - - run: - name: Linting 🧹 - command: | - yarn clean - git clean -df - yarn lint - - run: - name: cypress info (dev) - command: node cli/bin/cypress info --dev - - store-npm-logs - - check-ts: - <<: *defaults - steps: - - restore_cached_workspace - - install-required-node - - run: - name: Check TS Types - command: NODE_OPTIONS=--max_old_space_size=4096 yarn gulp checkTs - - - # a special job that keeps polling Circle and when all - # individual jobs are finished, it closes the Percy build - percy-finalize: - <<: *defaults - resource_class: small - parameters: - <<: *defaultsParameters - required_env_var: - type: env_var_name - steps: - - restore_cached_workspace - - 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 <> is set - command: | - if [[ -v <> ]]; 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: > - cli-visual-tests, - reporter-integration-tests, - run-app-component-tests-chrome, - run-app-integration-tests-chrome, - run-frontend-shared-component-tests-chrome, - run-launchpad-component-tests-chrome, - run-launchpad-integration-tests-chrome, - run-reporter-component-tests-chrome, - run-webpack-dev-server-integration-tests, - run-vite-dev-server-integration-tests - - run: - # Sometimes, even though all the circle jobs have finished, Percy times out during `build:finalize` - # If all other jobs finish but `build:finalize` fails, we retry it once - name: Finalize percy build - allows single retry - command: | - PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ - yarn percy build:finalize || yarn percy build:finalize - - cli-visual-tests: - <<: *defaults - resource_class: small - steps: - - restore_cached_workspace - - 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_WORKSPACE_ID \ - PERCY_ENABLE=${PERCY_TOKEN:-0} \ - PERCY_PARALLEL_TOTAL=-1 \ - yarn percy snapshot ./cli/visual-snapshots - - v8-integration-tests: - <<: *defaults - parameters: - <<: *defaultsParameters - resource_class: - type: string - default: medium - resource_class: << parameters.resource_class >> - parallelism: 1 - steps: - - restore_cached_workspace - - restore_cached_system_tests_deps - # TODO: Remove this once we switch off self-hosted M1 runners - - when: - condition: - equal: [ *darwin-arm64-executor, << parameters.executor >> ] - steps: - - run: rm -f /tmp/cypress/junit/* - - unless: - condition: - or: - - equal: [ *linux-arm64-executor, << parameters.executor >> ] # TODO: Figure out how to support linux-arm64 when we get to linux arm64 build: https://github.com/cypress-io/cypress/issues/23557 - steps: - - run: - name: Run v8 integration tests - command: | - source ./scripts/ensure-node.sh - yarn test-integration --scope "'@tooling/{packherd,v8-snapshot,electron-mksnapshot}'" - - verify-mocha-results: - expectedResultCount: 3 - - when: - condition: - or: - - equal: [ *linux-arm64-executor, << parameters.executor >> ] - steps: - - run: - name: Run v8 integration tests - command: | - source ./scripts/ensure-node.sh - yarn test-integration --scope "'@tooling/packherd'" - - verify-mocha-results: - expectedResultCount: 1 - - store_test_results: - path: /tmp/cypress - - store-npm-logs - - unit-tests: - <<: *defaults - parameters: - <<: *defaultsParameters - resource_class: - type: string - default: medium - resource_class: << parameters.resource_class >> - parallelism: 1 - steps: - - restore_cached_workspace - - when: - condition: - # several snapshots fails for windows due to paths. - # until these are fixed, run the tests that are working. - equal: [ *windows-executor, << parameters.executor >> ] - steps: - - run: yarn test-scripts scripts/**/*spec.js - - unless: - condition: - equal: [ *windows-executor, << parameters.executor >> ] - steps: - - run: yarn test-scripts - # make sure packages with TypeScript can be transpiled to JS - - run: yarn lerna run build-prod --stream --concurrency 4 - # run unit tests from each individual package - - run: yarn test - # run type checking for each individual package - - run: yarn lerna run types - - verify-mocha-results: - expectedResultCount: 18 - - store_test_results: - path: /tmp/cypress - # CLI tests generate HTML files with sample CLI command output - - store_artifacts: - path: cli/test/html - - store_artifacts: - path: packages/errors/__snapshot-images__ - - store-npm-logs - - unit-tests-release: - <<: *defaults - resource_class: small - parallelism: 1 - steps: - - restore_cached_workspace - - update_known_hosts - - run: yarn test-npm-package-release-script - - lint-types: - <<: *defaults - parallelism: 1 - steps: - - restore_cached_workspace - - 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 - # todo(lachlan): do we need this? yarn check-ts does something very similar - # - run: - # name: "TypeScript check 🧩" - # command: yarn type-check --ignore-progress - - store-npm-logs - - server-unit-tests: - <<: *defaults - parallelism: 1 - steps: - - restore_cached_workspace - - 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: - - restore_cached_workspace - - 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: - - restore_cached_workspace - - 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 - - system-tests-node-modules-install: - <<: *defaults - steps: - - restore_cached_workspace - - update_cached_system_tests_deps - - binary-system-tests: - parallelism: 2 - working_directory: ~/cypress - environment: - <<: *defaultsEnvironment - PLATFORM: linux - machine: - # using `machine` gives us a Linux VM that can run Docker - image: ubuntu-2004:202111-02 - docker_layer_caching: true - resource_class: medium - steps: - - run-binary-system-tests - - system-tests-chrome: - <<: *defaults - parallelism: 8 - steps: - - run-system-tests: - browser: chrome - - system-tests-electron: - <<: *defaults - parallelism: 8 - steps: - - run-system-tests: - browser: electron - - system-tests-firefox: - <<: *defaults - parallelism: 8 - steps: - - run-system-tests: - browser: firefox - - system-tests-webkit: - <<: *defaults - parallelism: 8 - steps: - - run-system-tests: - browser: webkit - - system-tests-non-root: - <<: *defaults - steps: - - restore_cached_workspace - - run: - command: yarn workspace @tooling/system-tests test:ci "test/non_root*spec*" --browser electron - - verify-mocha-results - - store_test_results: - path: /tmp/cypress - - store_artifacts: - path: /tmp/artifacts - - store-npm-logs - - run-frontend-shared-component-tests-chrome: - <<: *defaults - parameters: - <<: *defaultsParameters - percy: - type: boolean - default: false - parallelism: 3 - steps: - - run-new-ui-tests: - browser: chrome - percy: << parameters.percy >> - package: frontend-shared - type: ct - - run-launchpad-component-tests-chrome: - <<: *defaults - parameters: - <<: *defaultsParameters - percy: - type: boolean - default: false - parallelism: 7 - steps: - - run-new-ui-tests: - browser: chrome - percy: << parameters.percy >> - package: launchpad - type: ct - # debug: cypress:*,engine:socket - - run-launchpad-integration-tests-chrome: - <<: *defaults - parameters: - <<: *defaultsParameters - resource_class: - type: string - default: medium - percy: - type: boolean - default: false - resource_class: << parameters.resource_class >> - parallelism: 3 - steps: - - run-new-ui-tests: - browser: chrome - percy: << parameters.percy >> - package: launchpad - type: e2e - - run-app-component-tests-chrome: - <<: *defaults - parameters: - <<: *defaultsParameters - percy: - type: boolean - default: false - parallelism: 7 - steps: - - run-new-ui-tests: - browser: chrome - percy: << parameters.percy >> - package: app - type: ct - - run-app-integration-tests-chrome: - <<: *defaults - parameters: - <<: *defaultsParameters - resource_class: - type: string - default: medium - percy: - type: boolean - default: false - resource_class: << parameters.resource_class >> - parallelism: 8 - steps: - - run-new-ui-tests: - browser: chrome - percy: << parameters.percy >> - package: app - type: e2e - - driver-integration-tests-chrome: - <<: *defaults - parallelism: 5 - steps: - - run-driver-integration-tests: - browser: chrome - install-chrome-channel: stable - - driver-integration-tests-chrome-beta: - <<: *defaults - parallelism: 5 - steps: - - run-driver-integration-tests: - browser: chrome:beta - install-chrome-channel: beta - - driver-integration-tests-firefox: - <<: *defaults - parallelism: 5 - steps: - - run-driver-integration-tests: - browser: firefox - - driver-integration-tests-electron: - <<: *defaults - parallelism: 5 - steps: - - run-driver-integration-tests: - browser: electron - - driver-integration-tests-webkit: - <<: *defaults - parallelism: 5 - steps: - - run-driver-integration-tests: - browser: webkit - - driver-integration-tests-chrome-experimentalSessionAndOrigin: - <<: *defaults - resource_class: medium - parallelism: 5 - steps: - - run-driver-integration-tests: - browser: chrome - install-chrome-channel: stable - experimentalSessionAndOrigin: true - - driver-integration-tests-chrome-beta-experimentalSessionAndOrigin: - <<: *defaults - resource_class: medium - parallelism: 5 - steps: - - run-driver-integration-tests: - browser: chrome:beta - install-chrome-channel: beta - experimentalSessionAndOrigin: true - - driver-integration-tests-firefox-experimentalSessionAndOrigin: - <<: *defaults - resource_class: medium - parallelism: 5 - steps: - - run-driver-integration-tests: - browser: firefox - experimentalSessionAndOrigin: true - - driver-integration-tests-electron-experimentalSessionAndOrigin: - <<: *defaults - resource_class: medium - parallelism: 5 - steps: - - run-driver-integration-tests: - browser: electron - experimentalSessionAndOrigin: true - - driver-integration-tests-webkit-experimentalSessionAndOrigin: - <<: *defaults - resource_class: medium - parallelism: 5 - steps: - - run-driver-integration-tests: - browser: webkit - experimentalSessionAndOrigin: true - - run-reporter-component-tests-chrome: - <<: *defaults - parameters: - <<: *defaultsParameters - percy: - type: boolean - default: false - parallelism: 2 - steps: - - run-new-ui-tests: - browser: chrome - percy: << parameters.percy >> - package: reporter - type: ct - - reporter-integration-tests: - <<: *defaults - parallelism: 3 - steps: - - restore_cached_workspace - - run: - command: yarn build-for-tests - working_directory: packages/reporter - - run: - command: | - CYPRESS_CONFIG_ENV=production \ - CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ - PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ - PERCY_ENABLE=${PERCY_TOKEN:-0} \ - PERCY_PARALLEL_TOTAL=-1 \ - yarn percy exec --parallel -- -- \ - 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 - - run-webpack-dev-server-integration-tests: - <<: *defaults - parallelism: 2 - steps: - - restore_cached_workspace - - restore_cached_system_tests_deps - - run: - command: | - CYPRESS_CONFIG_ENV=production \ - CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ - PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ - PERCY_ENABLE=${PERCY_TOKEN:-0} \ - PERCY_PARALLEL_TOTAL=-1 \ - yarn percy exec --parallel -- -- \ - yarn cypress:run --record --parallel --group webpack-dev-server - working_directory: npm/webpack-dev-server - - store_test_results: - path: /tmp/cypress - - store_artifacts: - path: /tmp/artifacts - - store-npm-logs - - run-vite-dev-server-integration-tests: - <<: *defaults - # parallelism: 3 TODO: Add parallelism once we have more specs - steps: - - restore_cached_workspace - - restore_cached_system_tests_deps - - run: - command: | - CYPRESS_CONFIG_ENV=production \ - CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ - PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ - PERCY_ENABLE=${PERCY_TOKEN:-0} \ - PERCY_PARALLEL_TOTAL=-1 \ - yarn percy exec --parallel -- -- \ - yarn cypress:run --record --parallel --group vite-dev-server - working_directory: npm/vite-dev-server - - store_test_results: - path: /tmp/cypress - - store_artifacts: - path: /tmp/artifacts - - store-npm-logs - - npm-webpack-preprocessor: - <<: *defaults - steps: - - restore_cached_workspace - - run: - name: Build - command: yarn workspace @cypress/webpack-preprocessor build - - 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 - - run: - name: Run tests - command: yarn workspace @cypress/webpack-preprocessor test - - store-npm-logs - npm-webpack-dev-server: - <<: *defaults - steps: - - restore_cached_workspace - - restore_cached_system_tests_deps - - run: - name: Run tests - command: yarn workspace @cypress/webpack-dev-server test - - run: - name: Run tests - command: yarn workspace @cypress/webpack-dev-server test + echo "Skipping CI; branch in progress - $TRIGGER_INSTRUCTIONS" + cancel_build - npm-vite-dev-server: - <<: *defaults - steps: - - restore_cached_workspace - - run: - name: Run tests - command: yarn test - working_directory: npm/vite-dev-server - - store_test_results: - path: npm/vite-dev-server/test_results - - store-npm-logs - - npm-webpack-batteries-included-preprocessor: - <<: *defaults - resource_class: small - steps: - - restore_cached_workspace - - run: - name: Run tests - command: yarn workspace @cypress/webpack-batteries-included-preprocessor test - - npm-vue: - <<: *defaults - steps: - - restore_cached_workspace - - run: - name: Build - command: yarn workspace @cypress/vue build - - run: - name: Type Check - command: yarn typecheck - working_directory: npm/vue - - store_test_results: - path: npm/vue/test_results - - store_artifacts: - path: npm/vue/test_results - - store-npm-logs - - npm-angular: - <<: *defaults - steps: - - restore_cached_workspace - - run: - name: Build - command: yarn workspace @cypress/angular build - - store-npm-logs - - npm-react: - <<: *defaults - steps: - - restore_cached_workspace - - run: - name: Build - command: yarn workspace @cypress/react build - - run: - name: Run tests - command: yarn test - working_directory: npm/react - - store_test_results: - path: npm/react/test_results - - store_artifacts: - path: npm/react/test_results - - store-npm-logs - - npm-mount-utils: - <<: *defaults - steps: - - restore_cached_workspace - - run: - name: Build - command: yarn workspace @cypress/mount-utils build - - store-npm-logs - - npm-xpath: - <<: *defaults - resource_class: small - steps: - - restore_cached_workspace - - run: - name: Run tests - command: yarn workspace @cypress/xpath cy:run - - store_test_results: - path: npm/xpath/test_results - - store_artifacts: - path: npm/xpath/test_results - - store-npm-logs - - npm-grep: - <<: *defaults - resource_class: small - steps: - - restore_cached_workspace - - run: - name: Run tests - command: yarn workspace @cypress/grep cy:run - - store_test_results: - path: npm/grep/test_results - - store_artifacts: - path: npm/grep/test_results - - store-npm-logs - - npm-create-cypress-tests: - <<: *defaults - resource_class: small - steps: - - restore_cached_workspace - - run: yarn workspace create-cypress-tests build - - npm-eslint-plugin-dev: - <<: *defaults - steps: - - restore_cached_workspace - - run: - name: Run tests - command: yarn workspace @cypress/eslint-plugin-dev test - - npm-cypress-schematic: - <<: *defaults - steps: - - restore_cached_workspace - - run: - name: Build + Install - command: | - yarn workspace @cypress/schematic build - working_directory: npm/cypress-schematic - run: - name: Run unit tests + name: Download .circleci/workflows.yaml command: | - yarn test - working_directory: npm/cypress-schematic - - store-npm-logs - - npm-release: - <<: *defaults - resource_class: medium+ - steps: - - restore_cached_workspace - - run: - name: Release packages after all jobs pass - command: yarn npm-release - - create-build-artifacts: - <<: *defaults - parameters: - <<: *defaultsParameters - resource_class: - type: string - default: large - resource_class: << parameters.resource_class >> - steps: - - restore_cached_workspace - - build-binary - - build-cypress-npm-package: - executor: << parameters.executor >> - - verify_should_persist_artifacts - - upload-build-artifacts - - post-install-comment - - test-kitchensink: - <<: *defaults - parameters: - <<: *defaultsParameters - resource_class: - type: string - default: medium+ - steps: - - restore_cached_workspace - - clone-repo-and-checkout-branch: - repo: cypress-example-kitchensink - - install-required-node - - run: - name: Remove cypress.json - description: Remove cypress.json in case it exists - working_directory: /tmp/cypress-example-kitchensink - environment: - CYPRESS_INTERNAL_FORCE_SCAFFOLD: "1" - command: rm -rf cypress.json - - 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: Rename support file - working_directory: /tmp/cypress-example-kitchensink - command: | - if [[ -f cypress/support/index.js ]]; then - mv cypress/support/index.js cypress/support/e2e.js + if [[ "$CIRCLE_BRANCH" == "pull/"* ]]; then + curl -o workflows.yml https://raw.githubusercontent.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/develop/.circleci/workflows.yml + else + curl -o workflows.yml https://raw.githubusercontent.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BRANCH}/.circleci/workflows.yml fi - - run: - name: Run Kitchensink example project - command: | - yarn cypress:run --project /tmp/cypress-example-kitchensink - - store-npm-logs - - test-kitchensink-against-staging: - <<: *defaults - steps: - - restore_cached_workspace - - clone-repo-and-checkout-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: | - 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: - - restore_cached_workspace - - clone-repo-and-checkout-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 - - test-npm-module-and-verify-binary: - <<: *defaults - steps: - - restore_cached_workspace - # 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: Cypress version - working_directory: test-binary - command: $(yarn bin cypress) version - - 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 - resource_class: small - docker: - - image: cypress/base:12.0.0-libgbm - steps: - - restore_workspace_binaries - - run: mkdir test-binary - - 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 - resource_class: small - steps: - - restore_workspace_binaries - - run: mkdir <> - - run: - name: Create new NPM package ⚗️ - working_directory: <> - command: npm init -y - - run: - name: Install dependencies 📦 - working_directory: <> - 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 - - # Todo: Add `jest` back into the list once https://github.com/yargs/yargs-parser/issues/452 - # is resolved. - command: | - npm install /root/cypress/cypress.tgz \ - typescript @types/jest enzyme @types/enzyme - - run: - name: Test types clash ⚔️ - working_directory: <> - command: | - echo "console.log('hello world')" > hello.ts - npx tsc hello.ts --noEmit - - 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 - resource_class: small - steps: - - restore_workspace_binaries - - run: mkdir <> - - run: - name: Create new NPM package ⚗️ - working_directory: <> - command: npm init -y - - run: - name: Install dependencies 📦 - working_directory: <> - environment: - CYPRESS_INSTALL_BINARY: /root/cypress/cypress.zip - command: | - npm install /root/cypress/cypress.tgz typescript - - run: - name: Scaffold full TypeScript project 🏗 - working_directory: <> - command: npx @bahmutov/cly@1.9.0 init --typescript - - run: - name: Run project tests 🗳 - working_directory: <> - command: npx cypress run - - # install NPM + binary zip and run against staging API - test-binary-against-staging: - <<: *defaults - steps: - - restore_workspace_binaries - - clone-repo-and-checkout-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 --legacy-peer-deps ~/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 - - test-binary-against-recipes-chrome: - <<: *defaults - steps: - - test-binary-against-repo: - repo: cypress-example-recipes - command: npm run test:ci:chrome - - test-binary-against-recipes: - <<: *defaults - steps: - - test-binary-against-repo: - repo: cypress-example-recipes - command: npm run test:ci - - # 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-kitchensink: - <<: *defaults - steps: - - test-binary-against-repo: - repo: cypress-example-kitchensink - 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-conduit-chrome: - <<: *defaults - steps: - - test-binary-against-repo: - repo: cypress-example-conduit-app - browser: chrome - command: "npm run cypress:run" - wait-on: http://localhost:3000 - - 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 - resource_class: medium+ - steps: - - test-binary-against-rwa: - repo: cypress-realworld-app - browser: chrome - wait-on: http://localhost:3000 - - test-binary-as-specific-user: - <<: *defaults - steps: - - restore_workspace_binaries - # 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@1.9.0 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-x64-workflow: &linux-x64-workflow - jobs: - - node_modules_install - - build: - context: test-runner:env-canary - requires: - - node_modules_install - - check-ts: - requires: - - build - - lint: - name: linux-lint - requires: - - build - - percy-finalize: - context: [test-runner:poll-circle-workflow, test-runner:percy] - 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: - context: test-runner:percy - requires: - - build - - unit-tests: - requires: - - build - - unit-tests-release: - context: test-runner:npm-release - requires: - - build - - server-unit-tests: - requires: - - build - - server-integration-tests: - requires: - - build - - server-performance-tests: - requires: - - build - - system-tests-node-modules-install: - context: test-runner:performance-tracking - requires: - - build - - system-tests-chrome: - context: test-runner:performance-tracking - requires: - - system-tests-node-modules-install - - system-tests-electron: - context: test-runner:performance-tracking - requires: - - system-tests-node-modules-install - - system-tests-firefox: - context: test-runner:performance-tracking - requires: - - system-tests-node-modules-install - - system-tests-webkit: - context: test-runner:performance-tracking - requires: - - system-tests-node-modules-install - - system-tests-non-root: - context: test-runner:performance-tracking - executor: non-root-docker-user - requires: - - system-tests-node-modules-install - - driver-integration-tests-chrome: - context: test-runner:cypress-record-key - requires: - - build - - driver-integration-tests-chrome-beta: - context: test-runner:cypress-record-key - requires: - - build - - driver-integration-tests-firefox: - context: test-runner:cypress-record-key - requires: - - build - - driver-integration-tests-electron: - context: test-runner:cypress-record-key - requires: - - build - - driver-integration-tests-webkit: - context: test-runner:cypress-record-key - requires: - - build - - driver-integration-tests-chrome-experimentalSessionAndOrigin: - context: test-runner:cypress-record-key - requires: - - build - - driver-integration-tests-chrome-beta-experimentalSessionAndOrigin: - context: test-runner:cypress-record-key - requires: - - build - - driver-integration-tests-firefox-experimentalSessionAndOrigin: - context: test-runner:cypress-record-key - requires: - - build - - driver-integration-tests-electron-experimentalSessionAndOrigin: - context: test-runner:cypress-record-key - requires: - - build - - driver-integration-tests-webkit-experimentalSessionAndOrigin: - context: test-runner:cypress-record-key - requires: - - build - - run-frontend-shared-component-tests-chrome: - context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] - percy: true - requires: - - build - - run-launchpad-integration-tests-chrome: - context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] - percy: true - requires: - - build - - run-launchpad-component-tests-chrome: - context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] - percy: true - requires: - - build - - run-app-integration-tests-chrome: - context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] - percy: true - requires: - - build - - run-webpack-dev-server-integration-tests: - context: [test-runner:cypress-record-key, test-runner:percy] - requires: - - system-tests-node-modules-install - - run-vite-dev-server-integration-tests: - context: [test-runner:cypress-record-key, test-runner:percy] - requires: - - system-tests-node-modules-install - - run-app-component-tests-chrome: - context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] - percy: true - requires: - - build - - run-reporter-component-tests-chrome: - context: [test-runner:cypress-record-key, test-runner:percy] - percy: true - requires: - - build - - reporter-integration-tests: - context: [test-runner:cypress-record-key, test-runner:percy] - requires: - - build - - npm-webpack-dev-server: - requires: - - system-tests-node-modules-install - - npm-vite-dev-server: - requires: - - build - - npm-webpack-preprocessor: - requires: - - build - - npm-webpack-batteries-included-preprocessor: - requires: - - build - - npm-vue: - requires: - - build - - npm-react: - requires: - - build - - npm-angular: - requires: - - build - - npm-mount-utils: - requires: - - build - - npm-create-cypress-tests: - requires: - - build - - npm-eslint-plugin-dev: - requires: - - build - - npm-cypress-schematic: - requires: - - build - - v8-integration-tests: - requires: - - system-tests-node-modules-install - # This release definition must be updated with any new jobs - # Any attempts to automate this are welcome - # If CircleCI provided an "after all" hook, then this wouldn't be necessary - - npm-release: - context: test-runner:npm-release - requires: - - build - - check-ts - - npm-angular - - npm-eslint-plugin-dev - - npm-create-cypress-tests - - npm-react - - npm-mount-utils - - npm-vue - - npm-webpack-batteries-included-preprocessor - - npm-webpack-preprocessor - - npm-vite-dev-server - - npm-webpack-dev-server - - npm-cypress-schematic - - lint-types - - linux-lint - - percy-finalize - - driver-integration-tests-firefox - - driver-integration-tests-chrome - - driver-integration-tests-chrome-beta - - driver-integration-tests-electron - - driver-integration-tests-firefox-experimentalSessionAndOrigin - - driver-integration-tests-chrome-experimentalSessionAndOrigin - - driver-integration-tests-chrome-beta-experimentalSessionAndOrigin - - driver-integration-tests-electron-experimentalSessionAndOrigin - - system-tests-non-root - - system-tests-firefox - - system-tests-electron - - system-tests-chrome - - server-performance-tests - - server-integration-tests - - server-unit-tests - - test-kitchensink - - unit-tests - - unit-tests-release - - cli-visual-tests - - reporter-integration-tests - - run-app-component-tests-chrome - - run-app-integration-tests-chrome - - run-frontend-shared-component-tests-chrome - - run-launchpad-component-tests-chrome - - run-launchpad-integration-tests-chrome - - run-reporter-component-tests-chrome - - run-webpack-dev-server-integration-tests - - run-vite-dev-server-integration-tests - - v8-integration-tests - - # various testing scenarios, like building full binary - # and testing it on a real project - - test-against-staging: - context: test-runner:record-tests - <<: *mainBuildFilters - requires: - - build - - test-kitchensink: - requires: - - build - - test-kitchensink-against-staging: - context: test-runner:record-tests - <<: *mainBuildFilters - requires: - - build - - create-build-artifacts: - context: - - test-runner:upload - - test-runner:commit-status-checks - requires: - - build - - test-npm-module-on-minimum-node-version: - requires: - - create-build-artifacts - - test-types-cypress-and-jest: - requires: - - create-build-artifacts - - test-full-typescript-project: - requires: - - create-build-artifacts - - test-binary-against-kitchensink: - requires: - - create-build-artifacts - - test-npm-module-and-verify-binary: - <<: *mainBuildFilters - requires: - - create-build-artifacts - - test-binary-against-staging: - context: test-runner:record-tests - <<: *mainBuildFilters - requires: - - create-build-artifacts - - test-binary-against-kitchensink-chrome: - <<: *mainBuildFilters - requires: - - create-build-artifacts - - test-binary-against-recipes-firefox: - <<: *mainBuildFilters - requires: - - create-build-artifacts - - test-binary-against-recipes-chrome: - <<: *mainBuildFilters - requires: - - create-build-artifacts - - test-binary-against-recipes: - <<: *mainBuildFilters - requires: - - create-build-artifacts - - test-binary-against-kitchensink-firefox: - <<: *mainBuildFilters - requires: - - create-build-artifacts - - test-binary-against-todomvc-firefox: - <<: *mainBuildFilters - requires: - - create-build-artifacts - - test-binary-against-cypress-realworld-app: - <<: *mainBuildFilters - requires: - - create-build-artifacts - - test-binary-as-specific-user: - name: "test binary as a non-root user" - executor: non-root-docker-user - requires: - - create-build-artifacts - - test-binary-as-specific-user: - name: "test binary as a root user" - requires: - - create-build-artifacts - - binary-system-tests: - requires: - - create-build-artifacts - - system-tests-node-modules-install - -linux-arm64-workflow: &linux-arm64-workflow - jobs: - - node_modules_install: - name: linux-arm64-node-modules-install - executor: linux-arm64 - resource_class: arm.medium - only-cache-for-root-user: true - - - build: - name: linux-arm64-build - executor: linux-arm64 - resource_class: arm.medium - requires: - - linux-arm64-node-modules-install - - - create-build-artifacts: - name: linux-arm64-create-build-artifacts - context: - - test-runner:upload - - test-runner:commit-status-checks - executor: linux-arm64 - resource_class: arm.medium - requires: - - linux-arm64-build - - - v8-integration-tests: - name: linux-arm64-v8-integration-tests - executor: linux-arm64 - resource_class: arm.medium - requires: - - linux-arm64-build - -darwin-x64-workflow: &darwin-x64-workflow - jobs: - - node_modules_install: - name: darwin-x64-node-modules-install - executor: mac - resource_class: macos.x86.medium.gen2 - only-cache-for-root-user: true - - - build: - name: darwin-x64-build - context: test-runner:env-canary - executor: mac - resource_class: macos.x86.medium.gen2 - requires: - - darwin-x64-node-modules-install - - - lint: - name: darwin-x64-lint - executor: mac - requires: - - darwin-x64-build - - - create-build-artifacts: - name: darwin-x64-create-build-artifacts - context: - - test-runner:sign-mac-binary - - test-runner:upload - - test-runner:commit-status-checks - executor: mac - resource_class: macos.x86.medium.gen2 - requires: - - darwin-x64-build - - - test-kitchensink: - name: darwin-x64-test-kitchensink - executor: mac - requires: - - darwin-x64-build - - - v8-integration-tests: - name: darwin-x64-v8-integration-tests - executor: mac - resource_class: macos.x86.medium.gen2 - requires: - - darwin-x64-build - -darwin-arm64-workflow: &darwin-arm64-workflow - jobs: - - node_modules_install: - name: darwin-arm64-node-modules-install - executor: darwin-arm64 - resource_class: cypress-io/latest_m1 - only-cache-for-root-user: true - - - build: - name: darwin-arm64-build - executor: darwin-arm64 - resource_class: cypress-io/latest_m1 - requires: - - darwin-arm64-node-modules-install - - - create-build-artifacts: - name: darwin-arm64-create-build-artifacts - context: - - test-runner:sign-mac-binary - - test-runner:upload - - test-runner:commit-status-checks - executor: darwin-arm64 - resource_class: cypress-io/latest_m1 - requires: - - darwin-arm64-build - - - v8-integration-tests: - name: darwin-arm64-v8-integration-tests - executor: darwin-arm64 - resource_class: cypress-io/latest_m1 - requires: - - darwin-arm64-build - -windows-workflow: &windows-workflow - jobs: - - node_modules_install: - name: windows-node-modules-install - executor: windows - resource_class: windows.large - only-cache-for-root-user: true - - - build: - name: windows-build - context: test-runner:env-canary - executor: windows - resource_class: windows.large - requires: - - windows-node-modules-install - - - run-app-integration-tests-chrome: - name: windows-run-app-integration-tests-chrome - executor: windows - resource_class: windows.large - context: [test-runner:cypress-record-key, test-runner:launchpad-tests] - requires: - - windows-build - - - run-launchpad-integration-tests-chrome: - name: windows-run-launchpad-integration-tests-chrome - executor: windows - resource_class: windows.large - context: [test-runner:cypress-record-key, test-runner:launchpad-tests] - requires: - - windows-build - - - lint: - name: windows-lint - executor: windows - requires: - - windows-build - - - unit-tests: - name: windows-unit-tests - executor: windows - resource_class: windows.large - requires: - - windows-build - - - create-build-artifacts: - name: windows-create-build-artifacts - executor: windows - resource_class: windows.large - context: - - test-runner:sign-windows-binary - - test-runner:upload - - test-runner:commit-status-checks - requires: - - windows-build - - test-binary-against-kitchensink-chrome: - name: windows-test-binary-against-kitchensink-chrome - executor: windows - requires: - - windows-create-build-artifacts - - - v8-integration-tests: - name: windows-v8-integration-tests - executor: windows - resource_class: windows.large - requires: - - windows-build + - continuation/continue: + configuration_path: workflows.yml workflows: - linux-x64: - <<: *linux-x64-workflow - <<: *linux-x64-workflow-exclude-filters - linux-arm64: - <<: *linux-arm64-workflow - <<: *linux-arm64-workflow-filters - darwin-x64: - <<: *darwin-x64-workflow - <<: *darwin-workflow-filters - darwin-arm64: - <<: *darwin-arm64-workflow - <<: *darwin-workflow-filters - windows: - <<: *windows-workflow - <<: *windows-workflow-filters + # the setup-workflow workflow is always triggered. + setup-workflow: + jobs: + - verify-ci-should-run: + context: workflow-setup diff --git a/.circleci/workflows.yml b/.circleci/workflows.yml new file mode 100644 index 000000000000..b5aa3d8b79e0 --- /dev/null +++ b/.circleci/workflows.yml @@ -0,0 +1,2829 @@ +version: 2.1 + +defaults: &defaults + parallelism: 1 + working_directory: ~/cypress + parameters: &defaultsParameters + executor: + type: executor + default: cy-doc + only-cache-for-root-user: + type: boolean + default: false + executor: <> + environment: &defaultsEnvironment + ## 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 + +mainBuildFilters: &mainBuildFilters + filters: + branches: + only: + - develop + - /^release\/\d+\.\d+\.\d+$/ + - 'retry-flake' + +# 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 +macWorkflowFilters: &darwin-workflow-filters + when: + or: + - equal: [ develop, << pipeline.git.branch >> ] + - equal: [ 'retry-flake', << pipeline.git.branch >> ] + - matches: + pattern: /^release\/\d+\.\d+\.\d+$/ + value: << pipeline.git.branch >> +linuxArm64WorkflowFilters: &linux-arm64-workflow-filters + when: + or: + - equal: [ develop, << pipeline.git.branch >> ] + - equal: [ 'retry-flake', << pipeline.git.branch >> ] + - matches: + pattern: /^release\/\d+\.\d+\.\d+$/ + value: << pipeline.git.branch >> + +# uncomment & add to the branch conditions below to disable the main linux +# flow if we don't want to test it for a certain branch +linuxWorkflowExcludeFilters: &linux-x64-workflow-exclude-filters + unless: + or: + - false + +# windows is slow and expensive in CI, so it normally only runs on main branches +# add your branch to this list to run the full Windows build on your PR +windowsWorkflowFilters: &windows-workflow-filters + when: + or: + - equal: [ develop, << pipeline.git.branch >> ] + - equal: [ 'retry-flake', << pipeline.git.branch >> ] + - matches: + pattern: /^release\/\d+\.\d+\.\d+$/ + value: << pipeline.git.branch >> +executors: + # the Docker image with Cypress dependencies and Chrome browser + cy-doc: + docker: + - image: cypress/browsers:node16.16.0-chrome106-ff99-edge + # by default, we use "medium" to balance performance + CI costs. bump or reduce on a per-job basis if needed. + resource_class: medium + environment: + PLATFORM: linux + CI_DOCKER: "true" + + # Docker image with non-root "node" user + non-root-docker-user: + docker: + - image: cypress/browsers:node16.16.0-chrome106-ff99-edge + 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: "14.0.0" + resource_class: macos.x86.medium.gen2 + environment: + PLATFORM: darwin + + # executor to run on Windows - based off of the windows-orb default executor since it is + # not customizable enough to align with our existing setup. + # https://github.com/CircleCI-Public/windows-orb/blob/master/src/executors/default.yml + # https://circleci.com/docs/2.0/hello-world-windows/#software-pre-installed-in-the-windows-image + windows: &windows-executor + machine: + image: windows-server-2019-vs2019:stable + shell: bash.exe -eo pipefail + resource_class: windows.large + environment: + PLATFORM: windows + + darwin-arm64: &darwin-arm64-executor + machine: true + environment: + PLATFORM: darwin + + linux-arm64: &linux-arm64-executor + machine: + image: ubuntu-2004:2022.04.1 + resource_class: arm.medium + environment: + PLATFORM: linux + # TODO: Disabling snapshots for now on Linux Arm 64 architectures. Will revisit with https://github.com/cypress-io/cypress/issues/23557 + DISABLE_SNAPSHOT_REQUIRE: 1 + +commands: + verify_should_persist_artifacts: + steps: + - run: + name: Check current branch to persist artifacts + command: | + if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "retry-flake" ]]; then + echo "Not uploading artifacts or posting install comment for this branch." + circleci-agent step halt + fi + + restore_workspace_binaries: + steps: + - attach_workspace: + at: ~/ + # make sure we have cypress.zip received + - run: ls -l + - run: ls -l cypress.zip cypress.tgz + - run: node --version + - run: npm --version + + restore_cached_workspace: + steps: + - attach_workspace: + at: ~/ + - install-required-node + - unpack-dependencies + + restore_cached_binary: + steps: + - attach_workspace: + at: ~/ + + prepare-modules-cache: + parameters: + dont-move: + type: boolean + default: false + steps: + - run: node scripts/circle-cache.js --action prepare + - unless: + condition: << parameters.dont-move >> + steps: + - run: + name: Move to /tmp dir for consistent caching across root/non-root users + command: | + mkdir -p /tmp/node_modules_cache + mv ~/cypress/node_modules /tmp/node_modules_cache/root_node_modules + mv ~/cypress/cli/node_modules /tmp/node_modules_cache/cli_node_modules + mv ~/cypress/system-tests/node_modules /tmp/node_modules_cache/system-tests_node_modules + mv ~/cypress/globbed_node_modules /tmp/node_modules_cache/globbed_node_modules + + install-webkit-deps: + steps: + - run: + name: Install WebKit dependencies + command: | + npx playwright install webkit + npx playwright install-deps webkit + + build-and-persist: + description: Save entire folder as artifact for other jobs to run without reinstalling + steps: + - run: + name: Build all codegen + command: | + source ./scripts/ensure-node.sh + yarn gulp buildProd + - run: + name: Build packages + command: | + source ./scripts/ensure-node.sh + yarn build + - run: + name: Generate v8 snapshot + command: | + source ./scripts/ensure-node.sh + yarn build-v8-snapshot-prod + - prepare-modules-cache # So we don't throw these in the workspace cache + - persist_to_workspace: + root: ~/ + paths: + - cypress + - .ssh + - node_modules # contains the npm i -g modules + + install_cache_helpers_dependencies: + steps: + - run: + # Dependencies needed by circle-cache.js, before we "yarn" or unpack cached node_modules + name: Cache Helper Dependencies + working_directory: ~/ + command: npm i glob@7.1.6 fs-extra@10.0.0 minimist@1.2.5 fast-json-stable-stringify@2.1.0 + + unpack-dependencies: + description: 'Unpacks dependencies associated with the current workflow' + steps: + - install_cache_helpers_dependencies + - run: + name: Generate Circle Cache Key + command: node scripts/circle-cache.js --action cacheKey > circle_cache_key + - run: + name: Generate platform key + command: node ./scripts/get-platform-key.js > platform_key + - restore_cache: + name: Restore cache state, to check for known modules cache existence + key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-node-modules-cache-{{ checksum "circle_cache_key" }} + - run: + name: Move node_modules back from /tmp + command: | + if [[ -d "/tmp/node_modules_cache" ]]; then + mv /tmp/node_modules_cache/root_node_modules ~/cypress/node_modules + mv /tmp/node_modules_cache/cli_node_modules ~/cypress/cli/node_modules + mv /tmp/node_modules_cache/system-tests_node_modules ~/cypress/system-tests/node_modules + mv /tmp/node_modules_cache/globbed_node_modules ~/cypress/globbed_node_modules + rm -rf /tmp/node_modules_cache + fi + - run: + name: Restore all node_modules to proper workspace folders + command: node scripts/circle-cache.js --action unpack + + restore_cached_system_tests_deps: + description: 'Restore the cached node_modules for projects in "system-tests/projects/**"' + steps: + - run: + name: Generate Circle Cache key for system tests + command: ./system-tests/scripts/cache-key.sh > system_tests_cache_key + - run: + name: Generate platform key + command: node ./scripts/get-platform-key.js > platform_key + - restore_cache: + name: Restore system tests node_modules cache + keys: + - v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }} + + update_cached_system_tests_deps: + description: 'Update the cached node_modules for projects in "system-tests/projects/**"' + steps: + - run: + name: Generate Circle Cache key for system tests + command: ./system-tests/scripts/cache-key.sh > system_tests_cache_key + - run: + name: Generate platform key + command: node ./scripts/get-platform-key.js > platform_key + - restore_cache: + name: Restore cache state, to check for known modules cache existence + keys: + - v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-state-of-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }} + - run: + name: Send root honeycomb event for this CI build + command: cd system-tests/scripts && node ./send-root-honeycomb-event.js + - run: + name: Bail if specific cache exists + command: | + if [[ -f "/tmp/system_tests_node_modules_installed" ]]; then + echo "No updates to system tests node modules, exiting" + circleci-agent step halt + fi + - restore_cache: + name: Restore system tests node_modules cache + keys: + - v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }} + - v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-system-tests-projects-node-modules-cache- + - run: + name: Update system-tests node_modules cache + command: yarn workspace @tooling/system-tests projects:yarn:install + - save_cache: + name: Save system tests node_modules cache + key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }} + paths: + - /tmp/cy-system-tests-node-modules + - run: touch /tmp/system_tests_node_modules_installed + - save_cache: + name: Save system tests node_modules cache state key + key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-state-of-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }} + paths: + - /tmp/system_tests_node_modules_installed + + caching-dependency-installer: + description: 'Installs & caches the dependencies based on yarn lock & package json dependencies' + parameters: + only-cache-for-root-user: + type: boolean + default: false + steps: + - install_cache_helpers_dependencies + - run: + name: Generate Circle Cache Key + command: node scripts/circle-cache.js --action cacheKey > circle_cache_key + - run: + name: Generate platform key + command: node ./scripts/get-platform-key.js > platform_key + - restore_cache: + name: Restore cache state, to check for known modules cache existence + key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-state-of-node-modules-cache-{{ checksum "circle_cache_key" }} + - run: + name: Bail if cache exists + command: | + if [[ -f "node_modules_installed" ]]; then + echo "Node modules already cached for dependencies, exiting" + circleci-agent step halt + fi + - run: date +%Y-%U > cache_date + - restore_cache: + name: Restore weekly yarn cache + keys: + - v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-deps-root-weekly-{{ checksum "cache_date" }} + - run: + name: Install Node Modules + command: | + source ./scripts/ensure-node.sh + # avoid installing Percy's Chromium every time we use @percy/cli + # https://docs.percy.io/docs/caching-asset-discovery-browser-in-ci + PERCY_POSTINSTALL_BROWSER=true \ + yarn --prefer-offline --frozen-lockfile --cache-folder ~/.yarn + no_output_timeout: 20m + - prepare-modules-cache: + dont-move: <> # we don't move, so we don't hit any issues unpacking symlinks + - when: + condition: <> # we don't move to /tmp since we don't need to worry about different users + steps: + - save_cache: + name: Saving node modules for root, cli, and all globbed workspace packages + key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-node-modules-cache-{{ checksum "circle_cache_key" }} + paths: + - node_modules + - cli/node_modules + - system-tests/node_modules + - globbed_node_modules + - unless: + condition: <> + steps: + - save_cache: + name: Saving node modules for root, cli, and all globbed workspace packages + key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-node-modules-cache-{{ checksum "circle_cache_key" }} + paths: + - /tmp/node_modules_cache + - run: touch node_modules_installed + - save_cache: + name: Saving node-modules cache state key + key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-state-of-node-modules-cache-{{ checksum "circle_cache_key" }} + paths: + - node_modules_installed + - save_cache: + name: Save weekly yarn cache + key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-deps-root-weekly-{{ checksum "cache_date" }} + paths: + - ~/.yarn + - ~/.cy-npm-cache + + verify-build-setup: + description: Common commands run when setting up for build or yarn install + parameters: + executor: + type: executor + default: cy-doc + steps: + - run: pwd + - run: + name: print global yarn cache path + command: echo $(yarn global bin) + - run: + name: print yarn version + command: yarn versions + - unless: + condition: + # stop-only does not correctly match on windows: https://github.com/bahmutov/stop-only/issues/78 + equal: [ *windows-executor, << parameters.executor >> ] + steps: + - run: + name: Stop .only + # this will catch ".only"s in js/coffee as well + command: | + source ./scripts/ensure-node.sh + yarn stop-only-all + - run: + name: Check terminal variables + ## 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 + command: | + source ./scripts/ensure-node.sh + yarn check-terminal + + 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: + # installing NVM will use git+ssh, so update known_hosts + - update_known_hosts + - run: + name: Install Node + command: | + node_version=$(cat .node-version) + source ./scripts/ensure-node.sh + echo "Installing Yarn" + npm install yarn -g # ensure yarn is installed with the correct node engine + yarn check-node-version + - run: + name: Check Node + command: | + source ./scripts/ensure-node.sh + yarn check-node-version + + install-chrome: + description: Install Google Chrome + parameters: + channel: + description: browser channel to install + type: string + version: + description: browser version to install + type: string + steps: + - run: + name: Install Google Chrome (<>) + command: | + echo "Installing Chrome (<>) v<>" + wget -O /usr/src/google-chrome-<>_<>_amd64.deb "http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-<>/google-chrome-<>_<>-1_amd64.deb" && \ + dpkg -i /usr/src/google-chrome-<>_<>_amd64.deb ; \ + apt-get install -f -y && \ + rm -f /usr/src/google-chrome-<>_<>_amd64.deb + which google-chrome-<> || (printf "\n\033[0;31mChrome was not successfully downloaded - bailing\033[0m\n\n" && exit 1) + echo "Location of Google Chrome Installation: `which google-chrome-<>`" + echo "Google Chrome Version: `google-chrome-<> --version`" + + run-driver-integration-tests: + parameters: + browser: + description: browser shortname to target + type: string + install-chrome-channel: + description: chrome channel to install + type: string + default: '' + steps: + - restore_cached_workspace + - when: + condition: <> + steps: + - install-chrome: + channel: <> + version: $(node ./scripts/get-browser-version.js chrome:<>) + - when: + condition: + equal: [ webkit, << parameters.browser >> ] + steps: + - install-webkit-deps + - run: + name: Run driver tests in Cypress + environment: + CYPRESS_CONFIG_ENV: production + command: | + echo Current working directory is $PWD + echo Total containers $CIRCLE_NODE_TOTAL + + if [[ -v MAIN_RECORD_KEY ]]; then + # internal PR + CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ + yarn cypress:run --record --parallel --group 5x-driver-<> --browser <> + else + # external PR + TESTFILES=$(circleci tests glob "cypress/e2e/**/*.cy.*" | 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 <> --spec $TESTFILES + fi + working_directory: packages/driver + - verify-mocha-results + - store_test_results: + path: /tmp/cypress + - store_artifacts: + path: /tmp/artifacts + - store-npm-logs + + windows-install-chrome: + parameters: + browser: + description: browser shortname to target + type: string + steps: + - run: + # TODO: How can we have preinstalled browsers on CircleCI? + name: 'Install Chrome on Windows' + command: | + # install with `--ignore-checksums` to avoid checksum error + # https://www.gep13.co.uk/blog/chocolatey-error-hashes-do-not-match + [[ $PLATFORM == 'windows' && '<>' == 'chrome' ]] && choco install googlechrome --ignore-checksums || [[ $PLATFORM != 'windows' ]] + + run-new-ui-tests: + parameters: + package: + description: package to target + type: enum + enum: ['frontend-shared', 'launchpad', 'app', 'reporter'] + browser: + description: browser shortname to target + type: string + percy: + description: enable percy + type: boolean + default: false + type: + description: ct or e2e + type: enum + enum: ['ct', 'e2e'] + debug: + description: debug option + type: string + default: '' + steps: + - restore_cached_workspace + - windows-install-chrome: + browser: <> + - run: + command: | + echo Current working directory is $PWD + echo Total containers $CIRCLE_NODE_TOTAL + + if [[ -v MAIN_RECORD_KEY ]]; then + # internal PR + cmd=$([[ <> == 'true' ]] && echo 'yarn percy exec --parallel -- --') || true + DEBUG=<> \ + CYPRESS_CONFIG_ENV=production \ + CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ + PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ + PERCY_ENABLE=${PERCY_TOKEN:-0} \ + PERCY_PARALLEL_TOTAL=-1 \ + $cmd yarn workspace @packages/<> cypress:run:<> --browser <> --record --parallel --group <>-<> + else + # external PR + + # To make `circleci tests` work correctly, we need to step into the package folder. + cd packages/<> + + GLOB="cypress/e2e/**/*cy.*" + + if [[ <> == 'ct' ]]; then + # component tests are located side by side with the source codes. + GLOB="src/**/*cy.*" + fi + + TESTFILES=$(circleci tests glob "$GLOB" | circleci tests split --total=$CIRCLE_NODE_TOTAL) + echo "Test files for this machine are $TESTFILES" + + # To run the `yarn` command, we need to walk out of the package folder. + cd ../.. + + DEBUG=<> \ + CYPRESS_CONFIG_ENV=production \ + PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ + PERCY_ENABLE=${PERCY_TOKEN:-0} \ + PERCY_PARALLEL_TOTAL=-1 \ + yarn workspace @packages/<> cypress:run:<> --browser <> --spec $TESTFILES + fi + - run: + command: | + if [[ <> == 'app' && <> == 'true' && -d "packages/app/cypress/screenshots/runner/screenshot/screenshot.cy.tsx/percy" ]]; then + PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ + PERCY_ENABLE=${PERCY_TOKEN:-0} \ + PERCY_PARALLEL_TOTAL=-1 \ + yarn percy upload packages/app/cypress/screenshots/runner/screenshot/screenshot.cy.tsx/percy + else + echo "skipping percy screenshots uploading" + fi + - store_test_results: + path: /tmp/cypress + - store_artifacts: + path: ./packages/<>/cypress/videos + - store-npm-logs + + run-system-tests: + parameters: + browser: + description: browser shortname to target + type: string + steps: + - restore_cached_workspace + - restore_cached_system_tests_deps + - when: + condition: + equal: [ webkit, << parameters.browser >> ] + steps: + - install-webkit-deps + - run: + name: Run system tests + environment: + CYPRESS_COMMERCIAL_RECOMMENDATIONS: '0' + command: | + ALL_SPECS=`circleci tests glob "/root/cypress/system-tests/test/*spec*"` + SPECS= + for file in $ALL_SPECS; do + # filter out non_root tests, they have their own stage + if [[ "$file" == *"non_root"* ]]; then + echo "Skipping $file" + continue + fi + SPECS="$SPECS $file" + done + SPECS=`echo $SPECS | xargs -n 1 | circleci tests split --split-by=timings` + echo SPECS=$SPECS + yarn workspace @tooling/system-tests test:ci $SPECS --browser <> + - verify-mocha-results + - store_test_results: + path: /tmp/cypress + - store_artifacts: + path: /tmp/artifacts + - store-npm-logs + + run-binary-system-tests: + steps: + - restore_cached_workspace + - restore_cached_system_tests_deps + - run: + name: Run system tests + environment: + CYPRESS_COMMERCIAL_RECOMMENDATIONS: '0' + command: | + ALL_SPECS=`circleci tests glob "$HOME/cypress/system-tests/test-binary/*spec*"` + SPECS=`echo $ALL_SPECS | xargs -n 1 | circleci tests split --split-by=timings` + echo SPECS=$SPECS + yarn workspace @tooling/system-tests test:ci $SPECS + - 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: + 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: + name: 'Verify Mocha Results' + command: | + source ./scripts/ensure-node.sh + yarn verify:mocha:results <> + + clone-repo-and-checkout-branch: + description: | + Clones an external repo and then checks out the branch that matches the next version otherwise uses 'master' branch. + parameters: + repo: + description: "Name of the github repo to clone like: cypress-example-kitchensink" + type: string + pull_request_id: + description: Pull request number to check out before installing and testing + type: integer + default: 0 + steps: + - restore_cached_binary + - run: + name: "Cloning test project and checking out release branch: <>" + working_directory: /tmp/<> + command: | + git clone --depth 1 --no-single-branch https://github.com/cypress-io/<>.git . + + cd ~/cypress/.. + # install some deps for get-next-version + npm i semver@7.3.2 conventional-recommended-bump@6.1.0 conventional-changelog-angular@5.0.12 + NEXT_VERSION=$(node ./cypress/scripts/get-next-version.js) + cd - + + git checkout $NEXT_VERSION || true + - when: + condition: <> + steps: + - run: + name: Check out PR <> + working_directory: /tmp/<> + command: | + git fetch origin pull/<>/head:pr-<> + git checkout pr-<> + + test-binary-against-rwa: + description: | + Takes the built binary and NPM package, clones the RWA repo + and runs the new version of Cypress against it. + parameters: + repo: + description: "Name of the github repo to clone like" + type: string + default: "cypress-realworld-app" + 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: "yarn cypress:run" + # 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: "CI=true yarn start" + steps: + - clone-repo-and-checkout-branch: + repo: <> + - when: + condition: <> + steps: + - run: + name: Check out PR <> + working_directory: /tmp/<> + command: | + git fetch origin pull/<>/head:pr-<> + git checkout pr-<> + git log -n 2 + - run: + command: yarn + working_directory: /tmp/<> + - run: + name: Install Cypress + working_directory: /tmp/<> + # force installing the freshly built binary + command: | + CYPRESS_INSTALL_BINARY=~/cypress/cypress.zip npm i --legacy-peer-deps ~/cypress/cypress.tgz && [[ -f yarn.lock ]] && yarn + - run: + name: Print Cypress version + working_directory: /tmp/<> + command: npx cypress version + - run: + name: Types check 🧩 (maybe) + working_directory: /tmp/<> + command: yarn types + - run: + working_directory: /tmp/<> + command: <> + background: true + - run: + condition: <> + name: "Waiting on server to boot: <>" + command: "npx wait-on <>" + - when: + condition: <> + steps: + - when: + condition: <> + steps: + - run: + name: Run tests using browser "<>" + working_directory: /tmp/<>/<> + command: | + <> -- --browser <> + - unless: + condition: <> + steps: + - run: + name: Run tests using command + working_directory: /tmp/<>/<> + command: <> + - unless: + condition: <> + steps: + - when: + condition: <> + steps: + - run: + name: Run tests using browser "<>" + working_directory: /tmp/<> + command: <> -- --browser <> + - unless: + condition: <> + steps: + - run: + name: Run tests using command + working_directory: /tmp/<> + command: <> + - store-npm-logs + + 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" + build-project: + description: Should the project build script be executed + type: boolean + default: true + # 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: + - clone-repo-and-checkout-branch: + repo: <> + pull_request_id: <> + - run: + # Ensure we're installing the node-version for the cloned repo + command: | + if [[ -f .node-version ]]; then + branch="<< pipeline.git.branch >>" + + externalBranchPattern='^pull\/[0-9]+' + if [[ $branch =~ $externalBranchPattern ]]; then + # We are unable to curl from the external PR branch location + # so we fall back to develop + branch="develop" + fi + + curl -L https://raw.githubusercontent.com/cypress-io/cypress/$branch/scripts/ensure-node.sh --output ci-ensure-node.sh + else + # if no .node-version file exists, we no-op the node script and use the global yarn + echo '' > ci-ensure-node.sh + fi + working_directory: /tmp/<> + - run: + # Install deps + Cypress binary with yarn if yarn.lock present + command: | + source ./ci-ensure-node.sh + if [[ -f yarn.lock ]]; then + yarn --frozen-lockfile + CYPRESS_INSTALL_BINARY=~/cypress/cypress.zip yarn add -D ~/cypress/cypress.tgz + else + npm install + CYPRESS_INSTALL_BINARY=~/cypress/cypress.zip npm install --legacy-peer-deps ~/cypress/cypress.tgz + fi + working_directory: /tmp/<> + - run: + name: Scaffold new config file + working_directory: /tmp/<> + environment: + CYPRESS_INTERNAL_FORCE_SCAFFOLD: "1" + command: | + if [[ -f cypress.json ]]; then + rm -rf cypress.json + echo 'module.exports = { e2e: {} }' > cypress.config.js + fi + - run: + name: Rename support file + working_directory: /tmp/<> + command: | + if [[ -f cypress/support/index.js ]]; then + mv cypress/support/index.js cypress/support/e2e.js + fi + - run: + name: Print Cypress version + working_directory: /tmp/<> + command: | + source ./ci-ensure-node.sh + npx cypress version + - run: + name: Types check 🧩 (maybe) + working_directory: /tmp/<> + command: | + source ./ci-ensure-node.sh + [[ -f yarn.lock ]] && yarn types || npm run types --if-present + - when: + condition: <> + steps: + - run: + name: Build 🏗 (maybe) + working_directory: /tmp/<> + command: | + source ./ci-ensure-node.sh + [[ -f yarn.lock ]] && yarn build || npm run build --if-present + - run: + working_directory: /tmp/<> + command: | + source ./ci-ensure-node.sh + <> + background: true + - run: + condition: <> + name: "Waiting on server to boot: <>" + command: | + npx wait-on <> --timeout 120000 + - windows-install-chrome: + browser: <> + - when: + condition: <> + steps: + - when: + condition: <> + steps: + - run: + name: Run tests using browser "<>" + working_directory: /tmp/<>/<> + command: | + <> -- --browser <> + - unless: + condition: <> + steps: + - run: + name: Run tests using command + working_directory: /tmp/<>/<> + command: <> + - unless: + condition: <> + steps: + - when: + condition: <> + steps: + - run: + name: Run tests using browser "<>" + working_directory: /tmp/<> + command: | + source ./ci-ensure-node.sh + <> -- --browser <> + - unless: + condition: <> + steps: + - run: + name: Run tests using command + working_directory: /tmp/<> + command: | + source ./ci-ensure-node.sh + <> + - 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: <>" + command: node ./scripts/wait-on-circle-jobs.js --job-names="<>" + + build-binary: + steps: + - run: + name: Check environment variables before code sign (if on Mac/Windows) + # NOTE + # our 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 the "develop" branch + # but if you need to really build and sign a binary in a PR + # set variable CSC_FOR_PULL_REQUEST=true + command: | + set -e + NEEDS_CODE_SIGNING=`node -p 'process.platform === "win32" || process.platform === "darwin"'` + if [[ "$NEEDS_CODE_SIGNING" == "true" ]]; then + echo "Checking for required environment variables..." + 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 + echo "Succeeded." + else + echo "Not code signing for this platform" + fi + - run: + name: Build the Cypress binary + environment: + DEBUG: electron-builder,electron-osx-sign* + # notarization on Mac can take a while + no_output_timeout: "45m" + command: | + source ./scripts/ensure-node.sh + node --version + if [[ `node ./scripts/get-platform-key.js` == 'linux-arm64' ]]; then + # these are missing on Circle and there is no way to pre-install them on Arm + sudo apt-get update + sudo apt-get install -y libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb + DISABLE_SNAPSHOT_REQUIRE=1 yarn binary-build --version $(node ./scripts/get-next-version.js) + else + yarn binary-build --version $(node ./scripts/get-next-version.js) + fi + - run: + name: Zip the binary + command: | + if [[ $PLATFORM == 'linux' ]]; then + # on Arm, CI runs as non-root, on x64 CI runs as root but there is no sudo binary + if [[ `whoami` == 'root' ]]; then + apt-get update && apt-get install -y zip + else + sudo apt-get update && sudo apt-get install -y zip + fi + fi + source ./scripts/ensure-node.sh + yarn binary-zip + - store-npm-logs + - persist_to_workspace: + root: ~/ + paths: + - cypress/cypress.zip + + build-cypress-npm-package: + parameters: + executor: + type: executor + default: cy-doc + steps: + - run: + name: Bump NPM version + command: | + source ./scripts/ensure-node.sh + yarn get-next-version --npm + - run: + name: Build NPM package + command: | + source ./scripts/ensure-node.sh + yarn build --scope cypress + - run: + name: Copy Re-exported NPM Packages + command: node ./scripts/post-build.js + working_directory: cli + - run: + command: ls -la types + working_directory: cli/build + - run: + command: ls -la vue vue2 mount-utils react + working_directory: cli/build + - unless: + condition: + equal: [ *windows-executor, << parameters.executor >> ] + steps: + - run: + name: list NPM package contents + command: | + source ./scripts/ensure-node.sh + yarn workspace cypress size + - run: + name: pack NPM package + working_directory: cli/build + command: yarn pack --filename ../../cypress.tgz + - run: + name: list created NPM package + command: ls -l + - store-npm-logs + - persist_to_workspace: + root: ~/ + paths: + - cypress/cypress.tgz + + upload-build-artifacts: + steps: + - run: ls -l + - run: + name: Upload unique binary to S3 + command: | + node scripts/binary.js upload-build-artifact \ + --type binary \ + --file cypress.zip \ + --version $(node -p "require('./package.json').version") + - run: + name: Upload NPM package to S3 + command: | + node scripts/binary.js upload-build-artifact \ + --type npm-package \ + --file cypress.tgz \ + --version $(node -p "require('./package.json').version") + - store-npm-logs + - run: ls -l + - run: cat binary-url.json + - run: cat npm-package-url.json + - persist_to_workspace: + root: ~/ + paths: + - cypress/binary-url.json + - cypress/npm-package-url.json + + update_known_hosts: + description: Ensures that we have the latest Git public keys to prevent git+ssh from failing. + steps: + - run: + name: Update known_hosts with github.com keys + command: | + mkdir -p ~/.ssh + ssh-keyscan github.com >> ~/.ssh/known_hosts + +jobs: + ## Checks if we already have a valid cache for the node_modules_install and if it has, + ## skips ahead to the build step, otherwise installs and caches the node_modules + node_modules_install: + <<: *defaults + parameters: + <<: *defaultsParameters + resource_class: + type: string + default: medium + resource_class: << parameters.resource_class >> + steps: + - checkout + - install-required-node + - verify-build-setup: + executor: << parameters.executor >> + - persist_to_workspace: + root: ~/ + paths: + - cypress + - .nvm # mac / linux + - ProgramData/nvm # windows + - caching-dependency-installer: + only-cache-for-root-user: <> + - store-npm-logs + + ## restores node_modules from previous step & builds if first step skipped + build: + <<: *defaults + parameters: + <<: *defaultsParameters + resource_class: + type: string + default: large + resource_class: << parameters.resource_class >> + steps: + - restore_cached_workspace + - run: + name: Top level packages + command: yarn list --depth=0 || true + - run: + name: Check env canaries on Linux + command: | + # only Docker has the required env data for this + if [[ $CI_DOCKER == 'true' ]]; then + node ./scripts/circle-env.js --check-canaries + fi + - build-and-persist + - store-npm-logs + + lint: + <<: *defaults + steps: + - restore_cached_workspace + - run: + name: Linting 🧹 + command: | + yarn clean + git clean -df + yarn lint + - run: + name: cypress info (dev) + command: node cli/bin/cypress info --dev + - store-npm-logs + + check-ts: + <<: *defaults + steps: + - restore_cached_workspace + - install-required-node + - run: + name: Check TS Types + command: NODE_OPTIONS=--max_old_space_size=4096 yarn gulp checkTs + + + # a special job that keeps polling Circle and when all + # individual jobs are finished, it closes the Percy build + percy-finalize: + <<: *defaults + resource_class: small + parameters: + <<: *defaultsParameters + required_env_var: + type: env_var_name + steps: + - restore_cached_workspace + - 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 <> is set + command: | + if [[ -v <> ]]; 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: > + cli-visual-tests, + reporter-integration-tests, + run-app-component-tests-chrome, + run-app-integration-tests-chrome, + run-frontend-shared-component-tests-chrome, + run-launchpad-component-tests-chrome, + run-launchpad-integration-tests-chrome, + run-reporter-component-tests-chrome, + run-webpack-dev-server-integration-tests, + run-vite-dev-server-integration-tests + - run: + # Sometimes, even though all the circle jobs have finished, Percy times out during `build:finalize` + # If all other jobs finish but `build:finalize` fails, we retry it once + name: Finalize percy build - allows single retry + command: | + PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ + yarn percy build:finalize || yarn percy build:finalize + + cli-visual-tests: + <<: *defaults + resource_class: small + steps: + - restore_cached_workspace + - 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_WORKSPACE_ID \ + PERCY_ENABLE=${PERCY_TOKEN:-0} \ + PERCY_PARALLEL_TOTAL=-1 \ + yarn percy snapshot ./cli/visual-snapshots + + v8-integration-tests: + <<: *defaults + parameters: + <<: *defaultsParameters + resource_class: + type: string + default: medium + resource_class: << parameters.resource_class >> + parallelism: 1 + steps: + - restore_cached_workspace + - restore_cached_system_tests_deps + # TODO: Remove this once we switch off self-hosted M1 runners + - when: + condition: + equal: [ *darwin-arm64-executor, << parameters.executor >> ] + steps: + - run: rm -f /tmp/cypress/junit/* + - unless: + condition: + or: + - equal: [ *linux-arm64-executor, << parameters.executor >> ] # TODO: Figure out how to support linux-arm64 when we get to linux arm64 build: https://github.com/cypress-io/cypress/issues/23557 + steps: + - run: + name: Run v8 integration tests + command: | + source ./scripts/ensure-node.sh + yarn test-integration --scope "'@tooling/{packherd,v8-snapshot,electron-mksnapshot}'" + - verify-mocha-results: + expectedResultCount: 3 + - when: + condition: + or: + - equal: [ *linux-arm64-executor, << parameters.executor >> ] + steps: + - run: + name: Run v8 integration tests + command: | + source ./scripts/ensure-node.sh + yarn test-integration --scope "'@tooling/packherd'" + - verify-mocha-results: + expectedResultCount: 1 + - store_test_results: + path: /tmp/cypress + - store-npm-logs + + unit-tests: + <<: *defaults + parameters: + <<: *defaultsParameters + resource_class: + type: string + default: medium + resource_class: << parameters.resource_class >> + parallelism: 1 + steps: + - restore_cached_workspace + - when: + condition: + # several snapshots fails for windows due to paths. + # until these are fixed, run the tests that are working. + equal: [ *windows-executor, << parameters.executor >> ] + steps: + - run: yarn test-scripts scripts/**/*spec.js + - unless: + condition: + equal: [ *windows-executor, << parameters.executor >> ] + steps: + - run: yarn test-scripts + # make sure packages with TypeScript can be transpiled to JS + - run: yarn lerna run build-prod --stream --concurrency 4 + # run unit tests from each individual package + - run: yarn test + # run type checking for each individual package + - run: yarn lerna run types + - verify-mocha-results: + expectedResultCount: 18 + - store_test_results: + path: /tmp/cypress + # CLI tests generate HTML files with sample CLI command output + - store_artifacts: + path: cli/test/html + - store_artifacts: + path: packages/errors/__snapshot-images__ + - store-npm-logs + + unit-tests-release: + <<: *defaults + resource_class: small + parallelism: 1 + steps: + - restore_cached_workspace + - update_known_hosts + - run: yarn test-npm-package-release-script + + lint-types: + <<: *defaults + parallelism: 1 + steps: + - restore_cached_workspace + - 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 + # todo(lachlan): do we need this? yarn check-ts does something very similar + # - run: + # name: "TypeScript check 🧩" + # command: yarn type-check --ignore-progress + - store-npm-logs + + server-unit-tests: + <<: *defaults + parallelism: 1 + steps: + - restore_cached_workspace + - 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: + - restore_cached_workspace + - 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: + - restore_cached_workspace + - 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 + + system-tests-node-modules-install: + <<: *defaults + steps: + - restore_cached_workspace + - update_cached_system_tests_deps + + binary-system-tests: + parallelism: 2 + working_directory: ~/cypress + environment: + <<: *defaultsEnvironment + PLATFORM: linux + machine: + # using `machine` gives us a Linux VM that can run Docker + image: ubuntu-2004:202111-02 + docker_layer_caching: true + resource_class: medium + steps: + - run-binary-system-tests + + system-tests-chrome: + <<: *defaults + parallelism: 8 + steps: + - run-system-tests: + browser: chrome + + system-tests-electron: + <<: *defaults + parallelism: 8 + steps: + - run-system-tests: + browser: electron + + system-tests-firefox: + <<: *defaults + parallelism: 8 + steps: + - run-system-tests: + browser: firefox + + system-tests-webkit: + <<: *defaults + parallelism: 8 + steps: + - run-system-tests: + browser: webkit + + system-tests-non-root: + <<: *defaults + steps: + - restore_cached_workspace + - run: + environment: + CYPRESS_COMMERCIAL_RECOMMENDATIONS: '0' + command: yarn workspace @tooling/system-tests test:ci "test/non_root*spec*" --browser electron + - verify-mocha-results + - store_test_results: + path: /tmp/cypress + - store_artifacts: + path: /tmp/artifacts + - store-npm-logs + + run-frontend-shared-component-tests-chrome: + <<: *defaults + parameters: + <<: *defaultsParameters + percy: + type: boolean + default: false + parallelism: 3 + steps: + - run-new-ui-tests: + browser: chrome + percy: << parameters.percy >> + package: frontend-shared + type: ct + + run-launchpad-component-tests-chrome: + <<: *defaults + parameters: + <<: *defaultsParameters + percy: + type: boolean + default: false + parallelism: 7 + steps: + - run-new-ui-tests: + browser: chrome + percy: << parameters.percy >> + package: launchpad + type: ct + # debug: cypress:*,engine:socket + + run-launchpad-integration-tests-chrome: + <<: *defaults + parameters: + <<: *defaultsParameters + resource_class: + type: string + default: medium + percy: + type: boolean + default: false + resource_class: << parameters.resource_class >> + parallelism: 3 + steps: + - run-new-ui-tests: + browser: chrome + percy: << parameters.percy >> + package: launchpad + type: e2e + + run-app-component-tests-chrome: + <<: *defaults + parameters: + <<: *defaultsParameters + percy: + type: boolean + default: false + parallelism: 7 + steps: + - run-new-ui-tests: + browser: chrome + percy: << parameters.percy >> + package: app + type: ct + + run-app-integration-tests-chrome: + <<: *defaults + parameters: + <<: *defaultsParameters + resource_class: + type: string + default: medium + percy: + type: boolean + default: false + resource_class: << parameters.resource_class >> + parallelism: 8 + steps: + - run-new-ui-tests: + browser: chrome + percy: << parameters.percy >> + package: app + type: e2e + + driver-integration-tests-chrome: + <<: *defaults + parallelism: 5 + steps: + - run-driver-integration-tests: + browser: chrome + install-chrome-channel: stable + + driver-integration-tests-chrome-beta: + <<: *defaults + parallelism: 5 + steps: + - run-driver-integration-tests: + browser: chrome:beta + install-chrome-channel: beta + + driver-integration-tests-firefox: + <<: *defaults + parallelism: 5 + steps: + - run-driver-integration-tests: + browser: firefox + + driver-integration-tests-electron: + <<: *defaults + parallelism: 5 + steps: + - run-driver-integration-tests: + browser: electron + + driver-integration-tests-webkit: + <<: *defaults + resource_class: medium+ + parallelism: 5 + steps: + - run-driver-integration-tests: + browser: webkit + + run-reporter-component-tests-chrome: + <<: *defaults + parameters: + <<: *defaultsParameters + percy: + type: boolean + default: false + parallelism: 2 + steps: + - run-new-ui-tests: + browser: chrome + percy: << parameters.percy >> + package: reporter + type: ct + + reporter-integration-tests: + <<: *defaults + parallelism: 3 + steps: + - restore_cached_workspace + - run: + command: yarn build-for-tests + working_directory: packages/reporter + - run: + command: | + CYPRESS_CONFIG_ENV=production \ + CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ + PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ + PERCY_ENABLE=${PERCY_TOKEN:-0} \ + PERCY_PARALLEL_TOTAL=-1 \ + yarn percy exec --parallel -- -- \ + 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 + + run-webpack-dev-server-integration-tests: + <<: *defaults + parallelism: 2 + steps: + - restore_cached_workspace + - restore_cached_system_tests_deps + - run: + command: | + CYPRESS_CONFIG_ENV=production \ + CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ + PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ + PERCY_ENABLE=${PERCY_TOKEN:-0} \ + PERCY_PARALLEL_TOTAL=-1 \ + yarn percy exec --parallel -- -- \ + yarn cypress:run --record --parallel --group webpack-dev-server + working_directory: npm/webpack-dev-server + - store_test_results: + path: /tmp/cypress + - store_artifacts: + path: /tmp/artifacts + - store-npm-logs + + run-vite-dev-server-integration-tests: + <<: *defaults + # parallelism: 3 TODO: Add parallelism once we have more specs + steps: + - restore_cached_workspace + - restore_cached_system_tests_deps + - run: + command: | + CYPRESS_CONFIG_ENV=production \ + CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \ + PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \ + PERCY_ENABLE=${PERCY_TOKEN:-0} \ + PERCY_PARALLEL_TOTAL=-1 \ + yarn percy exec --parallel -- -- \ + yarn cypress:run --record --parallel --group vite-dev-server + working_directory: npm/vite-dev-server + - store_test_results: + path: /tmp/cypress + - store_artifacts: + path: /tmp/artifacts + - store-npm-logs + + npm-webpack-preprocessor: + <<: *defaults + steps: + - restore_cached_workspace + - run: + name: Build + command: yarn workspace @cypress/webpack-preprocessor build + - 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 + - run: + name: Run tests + command: yarn workspace @cypress/webpack-preprocessor test + - store-npm-logs + + npm-webpack-dev-server: + <<: *defaults + steps: + - restore_cached_workspace + - restore_cached_system_tests_deps + - run: + name: Run tests + command: yarn workspace @cypress/webpack-dev-server test + - run: + name: Run tests + command: yarn workspace @cypress/webpack-dev-server test + + npm-vite-dev-server: + <<: *defaults + steps: + - restore_cached_workspace + - run: + name: Run tests + command: yarn test + working_directory: npm/vite-dev-server + - store_test_results: + path: npm/vite-dev-server/test_results + - store-npm-logs + + npm-webpack-batteries-included-preprocessor: + <<: *defaults + resource_class: small + steps: + - restore_cached_workspace + - run: + name: Run tests + command: yarn workspace @cypress/webpack-batteries-included-preprocessor test + + npm-vue: + <<: *defaults + steps: + - restore_cached_workspace + - run: + name: Build + command: yarn workspace @cypress/vue build + - run: + name: Type Check + command: yarn typecheck + working_directory: npm/vue + - store_test_results: + path: npm/vue/test_results + - store_artifacts: + path: npm/vue/test_results + - store-npm-logs + + npm-angular: + <<: *defaults + steps: + - restore_cached_workspace + - run: + name: Build + command: yarn workspace @cypress/angular build + - store-npm-logs + + npm-react: + <<: *defaults + steps: + - restore_cached_workspace + - run: + name: Build + command: yarn workspace @cypress/react build + - run: + name: Run tests + command: yarn test + working_directory: npm/react + - store_test_results: + path: npm/react/test_results + - store_artifacts: + path: npm/react/test_results + - store-npm-logs + + npm-mount-utils: + <<: *defaults + steps: + - restore_cached_workspace + - run: + name: Build + command: yarn workspace @cypress/mount-utils build + - store-npm-logs + + npm-xpath: + <<: *defaults + resource_class: small + steps: + - restore_cached_workspace + - run: + name: Run tests + command: yarn workspace @cypress/xpath cy:run + - store_test_results: + path: npm/xpath/test_results + - store_artifacts: + path: npm/xpath/test_results + - store-npm-logs + + npm-grep: + <<: *defaults + resource_class: small + steps: + - restore_cached_workspace + - run: + name: Run tests + command: yarn workspace @cypress/grep cy:run + - store_test_results: + path: npm/grep/test_results + - store_artifacts: + path: npm/grep/test_results + - store-npm-logs + + npm-create-cypress-tests: + <<: *defaults + resource_class: small + steps: + - restore_cached_workspace + - run: yarn workspace create-cypress-tests build + + npm-eslint-plugin-dev: + <<: *defaults + steps: + - restore_cached_workspace + - run: + name: Run tests + command: yarn workspace @cypress/eslint-plugin-dev test + + npm-cypress-schematic: + <<: *defaults + steps: + - restore_cached_workspace + - run: + name: Build + Install + command: | + yarn workspace @cypress/schematic build + working_directory: npm/cypress-schematic + - run: + name: Run unit tests + command: | + yarn test + working_directory: npm/cypress-schematic + - store-npm-logs + + npm-release: + <<: *defaults + resource_class: medium+ + steps: + - restore_cached_workspace + - run: + name: Release packages after all jobs pass + command: yarn npm-release + + create-build-artifacts: + <<: *defaults + parameters: + <<: *defaultsParameters + resource_class: + type: string + default: xlarge + resource_class: << parameters.resource_class >> + steps: + - restore_cached_workspace + - build-binary + - build-cypress-npm-package: + executor: << parameters.executor >> + - verify_should_persist_artifacts + - upload-build-artifacts + - post-install-comment + + test-kitchensink: + <<: *defaults + parameters: + <<: *defaultsParameters + resource_class: + type: string + default: medium+ + steps: + - restore_cached_workspace + - clone-repo-and-checkout-branch: + repo: cypress-example-kitchensink + - install-required-node + - run: + name: Remove cypress.json + description: Remove cypress.json in case it exists + working_directory: /tmp/cypress-example-kitchensink + environment: + CYPRESS_INTERNAL_FORCE_SCAFFOLD: "1" + command: rm -rf cypress.json + - 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: Rename support file + working_directory: /tmp/cypress-example-kitchensink + command: | + if [[ -f cypress/support/index.js ]]; then + mv cypress/support/index.js cypress/support/e2e.js + fi + - run: + name: Run Kitchensink example project + command: | + yarn cypress:run --project /tmp/cypress-example-kitchensink + - store-npm-logs + + test-kitchensink-against-staging: + <<: *defaults + steps: + - restore_cached_workspace + - clone-repo-and-checkout-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: | + 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: + - restore_cached_workspace + - clone-repo-and-checkout-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 + + test-npm-module-and-verify-binary: + <<: *defaults + steps: + - restore_cached_workspace + # 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: Cypress version + working_directory: test-binary + command: $(yarn bin cypress) version + - 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 + resource_class: small + docker: + - image: cypress/base:12.0.0-libgbm + steps: + - restore_workspace_binaries + - run: mkdir test-binary + - 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 + resource_class: small + steps: + - restore_workspace_binaries + - run: mkdir <> + - run: + name: Create new NPM package ⚗️ + working_directory: <> + command: npm init -y + - run: + name: Install dependencies 📦 + working_directory: <> + 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 + + # Todo: Add `jest` back into the list once https://github.com/yargs/yargs-parser/issues/452 + # is resolved. + command: | + npm install /root/cypress/cypress.tgz \ + typescript @types/jest enzyme @types/enzyme + - run: + name: Test types clash ⚔️ + working_directory: <> + command: | + echo "console.log('hello world')" > hello.ts + npx tsc hello.ts --noEmit + + 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 + resource_class: small + steps: + - restore_workspace_binaries + - run: mkdir <> + - run: + name: Create new NPM package ⚗️ + working_directory: <> + command: npm init -y + - run: + name: Install dependencies 📦 + working_directory: <> + environment: + CYPRESS_INSTALL_BINARY: /root/cypress/cypress.zip + command: | + npm install /root/cypress/cypress.tgz typescript + - run: + name: Scaffold full TypeScript project 🏗 + working_directory: <> + command: npx @bahmutov/cly@1.9.0 init --typescript + - run: + name: Run project tests 🗳 + working_directory: <> + command: npx cypress run + + # install NPM + binary zip and run against staging API + test-binary-against-staging: + <<: *defaults + steps: + - restore_workspace_binaries + - clone-repo-and-checkout-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 --legacy-peer-deps ~/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 + + test-binary-against-recipes-chrome: + <<: *defaults + steps: + - test-binary-against-repo: + repo: cypress-example-recipes + command: npm run test:ci:chrome + + test-binary-against-recipes: + <<: *defaults + steps: + - test-binary-against-repo: + repo: cypress-example-recipes + command: npm run test:ci + + # 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-kitchensink: + <<: *defaults + steps: + - test-binary-against-repo: + repo: cypress-example-kitchensink + 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-conduit-chrome: + <<: *defaults + steps: + - test-binary-against-repo: + repo: cypress-example-conduit-app + browser: chrome + command: "npm run cypress:run" + wait-on: http://localhost:3000 + + 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 + resource_class: medium+ + steps: + - test-binary-against-rwa: + repo: cypress-realworld-app + browser: chrome + wait-on: http://localhost:3000 + + test-binary-as-specific-user: + <<: *defaults + steps: + - restore_workspace_binaries + # 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@1.9.0 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-x64-workflow: &linux-x64-workflow + jobs: + - node_modules_install + - build: + context: test-runner:env-canary + requires: + - node_modules_install + - check-ts: + requires: + - build + - lint: + name: linux-lint + requires: + - build + - percy-finalize: + context: [test-runner:poll-circle-workflow, test-runner:percy] + 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: + context: test-runner:percy + requires: + - build + - unit-tests: + requires: + - build + - unit-tests-release: + context: test-runner:npm-release + requires: + - build + - server-unit-tests: + requires: + - build + - server-integration-tests: + requires: + - build + - server-performance-tests: + requires: + - build + - system-tests-node-modules-install: + context: test-runner:performance-tracking + requires: + - build + - system-tests-chrome: + context: test-runner:performance-tracking + requires: + - system-tests-node-modules-install + - system-tests-electron: + context: test-runner:performance-tracking + requires: + - system-tests-node-modules-install + - system-tests-firefox: + context: test-runner:performance-tracking + requires: + - system-tests-node-modules-install + - system-tests-webkit: + context: test-runner:performance-tracking + requires: + - system-tests-node-modules-install + - system-tests-non-root: + context: test-runner:performance-tracking + executor: non-root-docker-user + requires: + - system-tests-node-modules-install + - driver-integration-tests-chrome: + context: test-runner:cypress-record-key + requires: + - build + - driver-integration-tests-chrome-beta: + context: test-runner:cypress-record-key + requires: + - build + - driver-integration-tests-firefox: + context: test-runner:cypress-record-key + requires: + - build + - driver-integration-tests-electron: + context: test-runner:cypress-record-key + requires: + - build + - driver-integration-tests-webkit: + context: test-runner:cypress-record-key + requires: + - build + - run-frontend-shared-component-tests-chrome: + context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] + percy: true + requires: + - build + - run-launchpad-integration-tests-chrome: + context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] + percy: true + requires: + - build + - run-launchpad-component-tests-chrome: + context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] + percy: true + requires: + - build + - run-app-integration-tests-chrome: + context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] + percy: true + requires: + - build + - run-webpack-dev-server-integration-tests: + context: [test-runner:cypress-record-key, test-runner:percy] + requires: + - system-tests-node-modules-install + - run-vite-dev-server-integration-tests: + context: [test-runner:cypress-record-key, test-runner:percy] + requires: + - system-tests-node-modules-install + - run-app-component-tests-chrome: + context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] + percy: true + requires: + - build + - run-reporter-component-tests-chrome: + context: [test-runner:cypress-record-key, test-runner:percy] + percy: true + requires: + - build + - reporter-integration-tests: + context: [test-runner:cypress-record-key, test-runner:percy] + requires: + - build + - npm-webpack-dev-server: + requires: + - system-tests-node-modules-install + - npm-vite-dev-server: + requires: + - build + - npm-webpack-preprocessor: + requires: + - build + - npm-webpack-batteries-included-preprocessor: + requires: + - build + - npm-vue: + requires: + - build + - npm-react: + requires: + - build + - npm-angular: + requires: + - build + - npm-mount-utils: + requires: + - build + - npm-create-cypress-tests: + requires: + - build + - npm-eslint-plugin-dev: + requires: + - build + - npm-cypress-schematic: + requires: + - build + - v8-integration-tests: + requires: + - system-tests-node-modules-install + # This release definition must be updated with any new jobs + # Any attempts to automate this are welcome + # If CircleCI provided an "after all" hook, then this wouldn't be necessary + - npm-release: + context: test-runner:npm-release + requires: + - build + - check-ts + - npm-angular + - npm-eslint-plugin-dev + - npm-create-cypress-tests + - npm-react + - npm-mount-utils + - npm-vue + - npm-webpack-batteries-included-preprocessor + - npm-webpack-preprocessor + - npm-vite-dev-server + - npm-webpack-dev-server + - npm-cypress-schematic + - lint-types + - linux-lint + - percy-finalize + - driver-integration-tests-firefox + - driver-integration-tests-chrome + - driver-integration-tests-chrome-beta + - driver-integration-tests-electron + - system-tests-non-root + - system-tests-firefox + - system-tests-electron + - system-tests-chrome + - server-performance-tests + - server-integration-tests + - server-unit-tests + - test-kitchensink + - unit-tests + - unit-tests-release + - cli-visual-tests + - reporter-integration-tests + - run-app-component-tests-chrome + - run-app-integration-tests-chrome + - run-frontend-shared-component-tests-chrome + - run-launchpad-component-tests-chrome + - run-launchpad-integration-tests-chrome + - run-reporter-component-tests-chrome + - run-webpack-dev-server-integration-tests + - run-vite-dev-server-integration-tests + - v8-integration-tests + + # various testing scenarios, like building full binary + # and testing it on a real project + - test-against-staging: + context: test-runner:record-tests + <<: *mainBuildFilters + requires: + - build + - test-kitchensink: + requires: + - build + - test-kitchensink-against-staging: + context: test-runner:record-tests + <<: *mainBuildFilters + requires: + - build + - create-build-artifacts: + context: + - test-runner:upload + - test-runner:commit-status-checks + requires: + - build + - test-npm-module-on-minimum-node-version: + requires: + - create-build-artifacts + - test-types-cypress-and-jest: + requires: + - create-build-artifacts + - test-full-typescript-project: + requires: + - create-build-artifacts + - test-binary-against-kitchensink: + requires: + - create-build-artifacts + - test-npm-module-and-verify-binary: + <<: *mainBuildFilters + requires: + - create-build-artifacts + - test-binary-against-staging: + context: test-runner:record-tests + <<: *mainBuildFilters + requires: + - create-build-artifacts + - test-binary-against-kitchensink-chrome: + <<: *mainBuildFilters + requires: + - create-build-artifacts + - test-binary-against-recipes-firefox: + <<: *mainBuildFilters + requires: + - create-build-artifacts + - test-binary-against-recipes-chrome: + <<: *mainBuildFilters + requires: + - create-build-artifacts + - test-binary-against-recipes: + <<: *mainBuildFilters + requires: + - create-build-artifacts + - test-binary-against-kitchensink-firefox: + <<: *mainBuildFilters + requires: + - create-build-artifacts + - test-binary-against-todomvc-firefox: + <<: *mainBuildFilters + requires: + - create-build-artifacts + - test-binary-against-cypress-realworld-app: + <<: *mainBuildFilters + requires: + - create-build-artifacts + - test-binary-as-specific-user: + name: "test binary as a non-root user" + executor: non-root-docker-user + requires: + - create-build-artifacts + - test-binary-as-specific-user: + name: "test binary as a root user" + requires: + - create-build-artifacts + - binary-system-tests: + requires: + - create-build-artifacts + - system-tests-node-modules-install + +linux-arm64-workflow: &linux-arm64-workflow + jobs: + - node_modules_install: + name: linux-arm64-node-modules-install + executor: linux-arm64 + resource_class: arm.medium + only-cache-for-root-user: true + + - build: + name: linux-arm64-build + executor: linux-arm64 + resource_class: arm.medium + requires: + - linux-arm64-node-modules-install + + - create-build-artifacts: + name: linux-arm64-create-build-artifacts + context: + - test-runner:upload + - test-runner:commit-status-checks + executor: linux-arm64 + resource_class: arm.medium + requires: + - linux-arm64-build + + - v8-integration-tests: + name: linux-arm64-v8-integration-tests + executor: linux-arm64 + resource_class: arm.medium + requires: + - linux-arm64-build + +darwin-x64-workflow: &darwin-x64-workflow + jobs: + - node_modules_install: + name: darwin-x64-node-modules-install + executor: mac + resource_class: macos.x86.medium.gen2 + only-cache-for-root-user: true + + - build: + name: darwin-x64-build + context: test-runner:env-canary + executor: mac + resource_class: macos.x86.medium.gen2 + requires: + - darwin-x64-node-modules-install + + - lint: + name: darwin-x64-lint + executor: mac + requires: + - darwin-x64-build + + - create-build-artifacts: + name: darwin-x64-create-build-artifacts + context: + - test-runner:sign-mac-binary + - test-runner:upload + - test-runner:commit-status-checks + executor: mac + resource_class: macos.x86.medium.gen2 + requires: + - darwin-x64-build + + - test-kitchensink: + name: darwin-x64-test-kitchensink + executor: mac + requires: + - darwin-x64-build + + - v8-integration-tests: + name: darwin-x64-v8-integration-tests + executor: mac + resource_class: macos.x86.medium.gen2 + requires: + - darwin-x64-build + +darwin-arm64-workflow: &darwin-arm64-workflow + jobs: + - node_modules_install: + name: darwin-arm64-node-modules-install + executor: darwin-arm64 + resource_class: cypress-io/latest_m1 + only-cache-for-root-user: true + + - build: + name: darwin-arm64-build + executor: darwin-arm64 + resource_class: cypress-io/latest_m1 + requires: + - darwin-arm64-node-modules-install + + - create-build-artifacts: + name: darwin-arm64-create-build-artifacts + context: + - test-runner:sign-mac-binary + - test-runner:upload + - test-runner:commit-status-checks + executor: darwin-arm64 + resource_class: cypress-io/latest_m1 + requires: + - darwin-arm64-build + + - v8-integration-tests: + name: darwin-arm64-v8-integration-tests + executor: darwin-arm64 + resource_class: cypress-io/latest_m1 + requires: + - darwin-arm64-build + +windows-workflow: &windows-workflow + jobs: + - node_modules_install: + name: windows-node-modules-install + executor: windows + resource_class: windows.large + only-cache-for-root-user: true + + - build: + name: windows-build + context: test-runner:env-canary + executor: windows + resource_class: windows.large + requires: + - windows-node-modules-install + + - run-app-integration-tests-chrome: + name: windows-run-app-integration-tests-chrome + executor: windows + resource_class: windows.large + context: [test-runner:cypress-record-key, test-runner:launchpad-tests] + requires: + - windows-build + + - run-launchpad-integration-tests-chrome: + name: windows-run-launchpad-integration-tests-chrome + executor: windows + resource_class: windows.large + context: [test-runner:cypress-record-key, test-runner:launchpad-tests] + requires: + - windows-build + + - lint: + name: windows-lint + executor: windows + requires: + - windows-build + + - unit-tests: + name: windows-unit-tests + executor: windows + resource_class: windows.large + requires: + - windows-build + + - create-build-artifacts: + name: windows-create-build-artifacts + executor: windows + resource_class: windows.large + context: + - test-runner:sign-windows-binary + - test-runner:upload + - test-runner:commit-status-checks + requires: + - windows-build + - test-binary-against-kitchensink-chrome: + name: windows-test-binary-against-kitchensink-chrome + executor: windows + requires: + - windows-create-build-artifacts + + - v8-integration-tests: + name: windows-v8-integration-tests + executor: windows + resource_class: windows.large + requires: + - windows-build + +workflows: + linux-x64: + <<: *linux-x64-workflow + <<: *linux-x64-workflow-exclude-filters + linux-arm64: + <<: *linux-arm64-workflow + <<: *linux-arm64-workflow-filters + darwin-x64: + <<: *darwin-x64-workflow + <<: *darwin-workflow-filters + darwin-arm64: + <<: *darwin-arm64-workflow + <<: *darwin-workflow-filters + windows: + <<: *windows-workflow + <<: *windows-workflow-filters diff --git a/.eslintrc.js b/.eslintrc.js index a5e6e3ba3e40..33bb01de53da 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -34,6 +34,12 @@ module.exports = { 'plugin:@cypress/dev/tests', ], parser: '@typescript-eslint/parser', + ignorePatterns: [ + // cli types are checked by dtslint + 'cli/types/**', + // these fixtures are supposed to fail linting + 'npm/eslint-plugin-dev/test/fixtures/**', + ], overrides: [ { files: [ diff --git a/.gitattributes b/.gitattributes index ebbd9782ff01..86f60e7ec9b9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,4 +2,6 @@ *.json text eol=lf +**/.eslintrc text eol=lf + packages/errors/__snapshot-html__/** linguist-generated=true \ No newline at end of file diff --git a/.github/workflows/trigger_circleci.yml b/.github/workflows/trigger_circleci.yml new file mode 100644 index 000000000000..1386ec551beb --- /dev/null +++ b/.github/workflows/trigger_circleci.yml @@ -0,0 +1,47 @@ +name: "Trigger CircleCi Pipeline" + +on: + pull_request_target: + types: + - opened + - ready_for_review + +jobs: + main: + name: Trigger CircleCi Pipeline when PR is ready for review + runs-on: ubuntu-latest + steps: + - if: ${{ github.event.pull_request.draft == false }} + shell: bash + env: + CIRCLE_TOKEN: ${{ secrets.CIRCLE_TOKEN }} + BASE_ORG_AND_REPO: ${{ github.event.pull_request.head.full_name }} + PULL_ID: ${{ github.event.pull_request.number }} + run: | + if [[ "${CIRCLE_TOKEN}" == "" ]]; then + echo "The CIRCLE_TOKEN is unset. Cannot trigger pipeline..." + exit 1; + fi + + BRANCH="$GITHUB_HEAD_REF" + + if [[ "$BASE_ORG_AND_REPO" != "cypress-io/cypress" ]]; then + echo "Triggering CircleCi pipeline for outside contributor." + BRANCH="pull/$PULL_ID/head" + fi + + echo "Triggering CircleCi pipeline for $BRANCH" + + response=$(curl -X POST https://circleci.com/api/v2/project/github/cypress-io/cypress/pipeline \ + --header "Circle-Token:$CIRCLE_TOKEN" \ + --header "content-type:application/json" \ + --data "{\"branch\":\"$BRANCH\"}" \ + --silent + ) + + echo "$response" + + if [ "$(jq 'has("message")' <<< $response )" == "true" ]; then + echo "Error triggering pipeline..." + exit 1; + fi diff --git a/.github/workflows/update_v8_snapshot_cache.yml b/.github/workflows/update_v8_snapshot_cache.yml new file mode 100644 index 000000000000..e0b0666a007a --- /dev/null +++ b/.github/workflows/update_v8_snapshot_cache.yml @@ -0,0 +1,10 @@ +name: Update V8 Snapshot Cache +on: [workflow_dispatch] +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true +jobs: + update-v8-snapshot-cache: + steps: + - name: Dummy step + run: echo "Dummy step" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8b15d616c664..0745ab104242 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -112,9 +112,9 @@ video | Problems with video recordings | [open](https://github.com/cypress-io/cy ## Writing Documentation - + Cypress documentation lives in a separate repository with its own dependencies and build tools. -See [Documentation Contributing Guideline](https://github.com/cypress-io/cypress-documentation/blob/master/CONTRIBUTING.md). +See [Documentation Contributing Guidelines](https://github.com/cypress-io/cypress-documentation/blob/master/CONTRIBUTING.md). ## Writing code @@ -164,7 +164,7 @@ Here is a list of the core packages in this repository with a short description, | [ts](./packages/ts) | `@packages/ts` | A centralized version of typescript. | | [types](./packages/types) | `@packages/types` | The shared internal Cypress types. | | [v8-snapshot-require](./packages/v8-snapshot-require) | `@packages/v8-snapshot-requie` | Tool to load a snapshot for Electron applications that was created by `@tooling/v8-snapshot`. | - | [web-config](./packages/web-config) | `@packages/ui-components` | The web-related configuration. | + | [web-config](./packages/web-config) | `@packages/web-config` | The web-related configuration. | Private packages involved in development of the app live within the [`tooling`](./tooling) directory and are in the `@tooling/` namespace. They are discrete modules with different responsibilities, but each is necessary for development of the Cypress app and is not necessarily useful outside of the Cypress app. @@ -358,7 +358,7 @@ This is to ensure that links do not go dead in older versions of Cypress when th ### Tests -For most packages there are typically unit and integration tests. +For most packages there are typically unit and integration tests. For UI packages there are E2E and component tests. Please refer to each packages' `README.md` which documents how to run tests. It is not feasible to try to run all of the tests together. We run our entire test fleet across over a dozen containers in CI. @@ -488,22 +488,28 @@ We do not continuously deploy the Cypress binary, so `develop` contains all of t - When opening a PR for a specific issue already open, please name the branch you are working on using the convention `issue-[issue number]`. For example, if your PR fixes Issue #803, name your branch `issue-803`. If the PR is a larger issue, you can add more context like `issue-803-new-scrollable-area`. If there's not an associated open issue, **[create an issue](https://github.com/cypress-io/cypress/issues/new/choose)**. - PRs can be opened before all the work is finished. In fact we encourage this! Please create a [Draft Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests) if your PR is not ready for review. [Mark the PR as **Ready for Review**](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review) when you're ready for a Cypress team member to review the PR. - Prefix the title of the Pull Request using [semantic-release](https://github.com/semantic-release/semantic-release)'s format as defined [here](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#type). For example, if your PR is fixing a bug, you should prefix the PR title with `fix:`. -- Fill out the [Pull Request Template](./.github/PULL_REQUEST_TEMPLATE.md) completely within the body of the PR. If you feel some areas are not relevant add `N/A` as opposed to deleting those sections. PR's will not be reviewed if this template is not filled in. +- Fill out the [Pull Request Template](./.github/PULL_REQUEST_TEMPLATE.md) completely within the body of the PR. If you feel some areas are not relevant add `N/A` as opposed to deleting those sections. PRs will not be reviewed if this template is not filled in. - If the PR is a user facing change and you're a Cypress team member that has logged into [ZenHub](https://www.zenhub.com/) and downloaded the [ZenHub for GitHub extension](https://www.zenhub.com/extension), set the release the PR is intended to ship in from the sidebar of the PR. Follow semantic versioning to select the intended release. This is used to generate the changelog for the release. If you don't tag a PR for release, it won't be mentioned in the changelog. ![Select release for PR](https://user-images.githubusercontent.com/1271364/135139641-657015d6-2dca-42d4-a4fb-16478f61d63f.png) - Please check the "Allow edits from maintainers" checkbox when submitting your PR. This will make it easier for the maintainers to make minor adjustments, to help with tests or any other changes we may need. ![Allow edits from maintainers checkbox](https://user-images.githubusercontent.com/1271181/31393427-b3105d44-ada9-11e7-80f2-0dac51e3919e.png) - All Pull Requests require a minimum of **two** approvals. - After the PR is approved, the original contributor can merge the PR (if the original contributor has access). -- When you merge a PR into `develop`, select [**Squash and merge**](https://docs.github.com/en/github/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-pull-request-commits). This will squash all commits into a single commit. *The only exception to squashing is when converting files to another language and there is a clear commit history needed to maintain from the file conversion.* +- When you merge a PR into `develop`, select [**Squash and merge**](https://docs.github.com/en/github/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-pull-request-commits). This will squash all commits into a single commit. + +*The only exceptions to squashing are:* + +1. When converting files to another language and there is a clear commit history needed to maintain from the file conversion. +2. When merging a `release/*` branch to `develop`. Individual PRs were already squashed when they were merged to the release branch, and we want that history intact on develop. ### Write Some Tests -If you are adding a new feature or fixing a regression, ensure you add tests for it. Broadly speaking, there are three categories of tests you might consider: +If you are adding a new feature or fixing a regression, ensure you add tests for it. Broadly speaking, there are four categories of tests you might consider: -1. Unit test. Those are inside of `test/unit`, if the package has them. These are the fastest and cheapest to execute. -2. E2E/Integration tests. Those are inside `cypress/e2e`, if the package has them. These are between Unit Tests and System Tests when it comes to speed of execution. -3. System Tests. Those go in the [`system-tests`](https://github.com/cypress-io/cypress/tree/develop/system-tests) directory. The README explains how they work. These are the slowest to run, so you generally only want to add a system-test if it's absolutely required (but don't let that discourage you; they are also the most realistic way to test Cypress). +1. Unit tests. Those are inside of `test/unit`, if the package has them. These are the fastest and cheapest to execute. +2. Component Tests. These are co-located with components in the `src` directory of UI-related packages. These test individual UI components in isolation. They can exhaustively test all expected variations of a component and are faster than E2E tests. +3. E2E/Integration tests. Those are inside `cypress/e2e`, if the package has them. These are between Unit Tests and System Tests when it comes to speed of execution. +4. System tests. Those go in the [`system-tests`](https://github.com/cypress-io/cypress/tree/develop/system-tests) directory. The README explains how they work. These are the slowest to run, so you generally only want to add a system-test if it's absolutely required (but don't let that discourage you; they are also the most realistic way to test Cypress). When choosing what's most appropriate, consider: @@ -511,6 +517,8 @@ When choosing what's most appropriate, consider: - ease of debugging - resilience to refactoring +It is also worth considering when a failure will be noticed. A unit or component test is likely to be run while the related code is being modified and provides very fast feedback. E2E tests and System Tests are more likely to only fail in CI since they are slower to run. + ### Dependencies We use [RenovateBot](https://renovatebot.com/) to automatically upgrade our dependencies. The bot uses the settings in [renovate.json](renovate.json) to maintain our [Update Dependencies](https://github.com/cypress-io/cypress/issues/3777) issue and open PRs. You can manually select a package to open a PR from our [Update Dependencies](https://github.com/cypress-io/cypress/issues/3777) issue. diff --git a/cli/lib/util.js b/cli/lib/util.js index 6c42b3f58780..1a5e54899018 100644 --- a/cli/lib/util.js +++ b/cli/lib/util.js @@ -533,6 +533,7 @@ const util = { la(is.unemptyString(varName), 'expected environment variable name, not', varName) const configVarName = `npm_config_${varName}` + const configVarNameLower = configVarName.toLowerCase() const packageConfigVarName = `npm_package_config_${varName}` let result @@ -545,6 +546,10 @@ const util = { debug(`Using ${varName} from npm config`) result = process.env[configVarName] + } else if (process.env.hasOwnProperty(configVarNameLower)) { + debug(`Using ${varName.toLowerCase()} from npm config`) + + result = process.env[configVarNameLower] } else if (process.env.hasOwnProperty(packageConfigVarName)) { debug(`Using ${varName} from package.json config`) diff --git a/cli/package.json b/cli/package.json index a9f70660e5ec..d485b7e34f3c 100644 --- a/cli/package.json +++ b/cli/package.json @@ -116,7 +116,7 @@ "cypress": "bin/cypress" }, "engines": { - "node": ">=12.0.0" + "node": "^14.0.0 || ^16.0.0 || >=18.0.0" }, "types": "types", "exports": { diff --git a/cli/test/lib/util_spec.js b/cli/test/lib/util_spec.js index 7a347e11294a..008f4719e2fa 100644 --- a/cli/test/lib/util_spec.js +++ b/cli/test/lib/util_spec.js @@ -543,6 +543,11 @@ describe('util', () => { expect(util.getEnv('CYPRESS_FOO')).to.eql('') }) + it('npm config set should work', () => { + process.env.npm_config_cypress_foo_foo = 'bazz' + expect(util.getEnv('CYPRESS_FOO_FOO')).to.eql('bazz') + }) + it('throws on non-string name', () => { expect(() => { util.getEnv() diff --git a/cli/types/cypress-npm-api.d.ts b/cli/types/cypress-npm-api.d.ts index 126f50202863..a7051b7f1462 100644 --- a/cli/types/cypress-npm-api.d.ts +++ b/cli/types/cypress-npm-api.d.ts @@ -173,7 +173,7 @@ declare namespace CypressCommandLine { title: string[] state: string body: string - /** + /** * Error string as it's presented in console if the test fails */ displayError: string | null @@ -229,6 +229,7 @@ declare namespace CypressCommandLine { startedAt: dateTimeISO endedAt: dateTimeISO duration: ms + wallClockDuration?: number } /** * Reporter name like "spec" @@ -259,8 +260,10 @@ declare namespace CypressCommandLine { * resolved filename of the spec */ absolute: string + relativeToCommonRoot: string } shouldUploadVideo: boolean + skippedSpec: boolean } /** diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 537d598c7625..515c4142ca52 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -50,6 +50,9 @@ declare namespace Cypress { interface CommandFnWithOriginalFnAndSubject { (this: Mocha.Context, originalFn: CommandOriginalFnWithSubject, prevSubject: S, ...args: Parameters): ReturnType | void } + interface QueryFn { + (this: Command, ...args: Parameters): (subject: any) => any + } interface ObjectLike { [key: string]: any } @@ -128,6 +131,58 @@ declare namespace Cypress { unsupportedVersion?: boolean } + interface Ensure { + /** + * Throws an error if `subject` is not one of the passed in `type`s. + */ + isType(subject: any, type: PrevSubject[], commandName: string, cy: Chainable): void + + /** + * Throws an error if `subject` is not a DOM element. + */ + isElement(subject: any, commandName: string, cy: Chainable): void + + /** + * Throws an error if `subject` is not a `document`. + */ + isDocument(subject: any, commandName: string, cy: Chainable): void + + /** + * Throws an error if `subject` is not a `window`. + */ + isWindow(subject: any, commandName: string, cy: Chainable): void + + /** + * Throws an error if `subject` is not a DOM element attached to the application under test. + */ + isAttached(subject: any, commandName: string, cy: Chainable, onFail?: Log): void + + /** + * Throws an error if `subject` is a disabled DOM element. + */ + isNotDisabled(subject: any, commandName: string, onFail?: Log): void + + /** + * Throws an error if `subject` is a DOM element hidden by any of its parent elements. + */ + isNotHiddenByAncestors(subject: any, commandName: string, onFail?: Log): void + + /** + * Throws an error if `subject` is a read-only form element. + */ + isNotReadonly(subject: any, commandName: string, onFail?: Log): void + + /** + * Throws an error if `subject` is a read-only form element. + */ + isScrollable(subject: any, commandName: string, onFail?: Log): void + + /** + * Throws an error if `subject` is not a DOM element visible in the AUT. + */ + isVisible(subject: any, commandName: string, onFail?: Log): void + } + interface LocalStorage { /** * Called internally to clear `localStorage` in two situations. @@ -142,6 +197,39 @@ declare namespace Cypress { clear: (keys?: string[]) => void } + // TODO: raise minimum required TypeScript version to 3.7 + // and make this recursive + // https://github.com/cypress-io/cypress/issues/24875 + type Storable = + | string + | number + | boolean + | null + | StorableObject + | StorableArray + + interface StorableObject { + [key: string]: Storable + } + + interface StorableArray extends Array { } + + type StorableRecord = Record + + interface OriginStorage { + origin: string + value: StorableRecord + } + + interface Storages { + localStorage: OriginStorage[] + sessionStorage: OriginStorage[] + } + + interface StorageByOrigin { + [key: string]: StorableRecord + } + type IsBrowserMatcher = BrowserName | Partial | Array> interface ViewportPosition extends WindowPosition { @@ -272,6 +360,12 @@ declare namespace Cypress { */ sinon: sinon.SinonStatic + /** + * Utility functions for ensuring various properties about a subject. + * @see https://on.cypress.io/custom-queries + */ + ensure: Ensure + /** * Cypress version string. i.e. "1.1.2" * @see https://on.cypress.io/version @@ -463,30 +557,92 @@ declare namespace Cypress { */ log(options: Partial): Log - /** - * @see https://on.cypress.io/api/commands - */ Commands: { + /** + * Add a custom command + * @see https://on.cypress.io/api/commands + */ add(name: T, fn: CommandFn): void + + /** + * Add a custom parent command + * @see https://on.cypress.io/api/commands#Parent-Commands + */ add(name: T, options: CommandOptions & {prevSubject: false}, fn: CommandFn): void + + /** + * Add a custom child command + * @see https://on.cypress.io/api/commands#Child-Commands + */ add(name: T, options: CommandOptions & {prevSubject: true}, fn: CommandFnWithSubject): void + + /** + * Add a custom child or dual command + * @see https://on.cypress.io/api/commands#Validations + */ add( name: T, options: CommandOptions & { prevSubject: S | ['optional'] }, fn: CommandFnWithSubject, ): void + + /** + * Add a custom command that allows multiple types as the prevSubject + * @see https://on.cypress.io/api/commands#Validations#Allow-Multiple-Types + */ add( name: T, options: CommandOptions & { prevSubject: S[] }, fn: CommandFnWithSubject[S]>, ): void + + /** + * Add one or more custom commands + * @see https://on.cypress.io/api/commands + */ addAll(fns: CommandFns): void + + /** + * Add one or more custom parent commands + * @see https://on.cypress.io/api/commands#Parent-Commands + */ addAll(options: CommandOptions & {prevSubject: false}, fns: CommandFns): void + + /** + * Add one or more custom child commands + * @see https://on.cypress.io/api/commands#Child-Commands + */ addAll(options: CommandOptions & { prevSubject: true }, fns: CommandFnsWithSubject): void + + /** + * Add one or more custom commands that validate their prevSubject + * @see https://on.cypress.io/api/commands#Validations + */ addAll( options: CommandOptions & { prevSubject: S | ['optional'] }, fns: CommandFnsWithSubject, ): void + + /** + * Add one or more custom commands that allow multiple types as their prevSubject + * @see https://on.cypress.io/api/commands#Allow-Multiple-Types + */ addAll( options: CommandOptions & { prevSubject: S[] }, fns: CommandFnsWithSubject[S]>, ): void + + /** + * Overwrite an existing Cypress command with a new implementation + * @see https://on.cypress.io/api/commands#Overwrite-Existing-Commands + */ overwrite(name: T, fn: CommandFnWithOriginalFn): void + + /** + * Overwrite an existing Cypress command with a new implementation + * @see https://on.cypress.io/api/commands#Overwrite-Existing-Commands + */ overwrite(name: T, fn: CommandFnWithOriginalFnAndSubject): void + + /** + * Add a custom query + * @see https://on.cypress.io/api/custom-queries + */ + addQuery(name: T, fn: QueryFn): void } /** @@ -494,16 +650,6 @@ declare namespace Cypress { */ Cookies: { debug(enabled: boolean, options?: Partial): void - /** - * @deprecated Use `cy.session()` instead. - * @see https://on.cypress.io/session - */ - preserveOnce(...names: string[]): void - /** - * @deprecated Use `cy.session()` instead. - * @see https://on.cypress.io/session - */ - defaults(options: Partial): CookieDefaults } /** @@ -602,13 +748,6 @@ declare namespace Cypress { defaults(options: Partial): void } - /** - * @see https://on.cypress.io/api/api-server - */ - Server: { - defaults(options: Partial): void - } - /** * @see https://on.cypress.io/screenshot-api */ @@ -660,7 +799,7 @@ declare namespace Cypress { * Whether or not to persist the session across all specs in the run. * @default {false} */ - cacheAcrossSpecs?: boolean, + cacheAcrossSpecs?: boolean /** * Function to run immediately after the session is created and `setup` function runs or * after a session is restored and the page is cleared. If this returns `false`, throws an @@ -776,7 +915,7 @@ declare namespace Cypress { clear(options?: Partial): Chainable /** - * Clear a specific browser cookie for the current superdomain or for the domain specified. + * Clear a specific browser cookie for the current hostname or for the domain specified. * Cypress automatically clears all cookies before each test to prevent state from being shared across tests. You shouldn't need to use this command unless you're using it to clear a specific cookie inside a single test. * * @see https://on.cypress.io/clearcookie @@ -784,7 +923,7 @@ declare namespace Cypress { clearCookie(name: string, options?: CookieOptions): Chainable /** - * Clear all browser cookies for the current superdomain or for the domain specified. + * Clear all browser cookies for the current hostname or for the domain specified. * Cypress automatically clears all cookies before each test to prevent state from being shared across tests. You shouldn't need to use this command unless you're using it to clear all cookies or specific cookies inside a single test. * * @see https://on.cypress.io/clearcookies @@ -792,7 +931,35 @@ declare namespace Cypress { clearCookies(options?: CookieOptions): Chainable /** - * Clear data in local storage. + * Get local storage for all origins. + * + * @see https://on.cypress.io/getalllocalstorage + */ + getAllLocalStorage(options?: Partial): Chainable + + /** + * Clear local storage for all origins. + * + * @see https://on.cypress.io/clearalllocalstorage + */ + clearAllLocalStorage(options?: Partial): Chainable + + /** + * Get session storage for all origins. + * + * @see https://on.cypress.io/getallsessionstorage + */ + getAllSessionStorage(options?: Partial): Chainable + + /** + * Clear session storage for all origins. + * + * @see https://on.cypress.io/clearallsessionstorage + */ + clearAllSessionStorage(options?: Partial): Chainable + + /** + * Clear data in local storage for the current origin. * Cypress automatically runs this command before each test to prevent state from being * shared across tests. You shouldn't need to use this command unless you're using it * to clear localStorage inside a single test. Yields `localStorage` object. @@ -1086,8 +1253,6 @@ declare namespace Cypress { /** * Save/Restore browser Cookies, LocalStorage, and SessionStorage data resulting from the supplied `setup` function. * - * Only available if the `experimentalSessionAndOrigin` config option is enabled. - * * @see https://on.cypress.io/session */ session(id: string | object, setup: () => void, options?: SessionOptions): Chainable @@ -1249,14 +1414,14 @@ declare namespace Cypress { get(alias: string, options?: Partial): Chainable /** - * Get a browser cookie by its name for the current superdomain or for the domain specified. + * Get a browser cookie by its name for the current hostname or for the domain specified. * * @see https://on.cypress.io/getcookie */ getCookie(name: string, options?: CookieOptions): Chainable /** - * Get all of the browser cookies for the current superdomain or for the domain specified. + * Get all of the browser cookies for the current hostname or for the domain specified. * * @see https://on.cypress.io/getcookies */ @@ -1430,6 +1595,13 @@ declare namespace Cypress { */ not(selector: string, options?: Partial): Chainable + /** + * Invoke a command synchronously, without using the command queue. + * + * @see https://on.cypress.io/custom-queries + */ + now(name: string, ...args: any[]): Promise | ((subject: any) => any) + /** * These events come from Cypress as it issues commands and reacts to their state. These are all useful to listen to for debugging purposes. * @see https://on.cypress.io/catalog-of-events#App-Events @@ -1678,66 +1850,6 @@ declare namespace Cypress { */ root(options?: Partial): Chainable> // can't do better typing unless we ignore the `.within()` case - /** - * @deprecated Use `cy.intercept()` instead. - * - * Use `cy.route()` to manage the behavior of network requests. - * @see https://on.cypress.io/route - * @example - * cy.server() - * cy.route('https://localhost:7777/users', [{id: 1, name: 'Pat'}]) - */ - route(url: string | RegExp, response?: string | object): Chainable - /** - * @deprecated Use `cy.intercept()` instead. - * - * Spy or stub request with specific method and url. - * - * @see https://on.cypress.io/route - * @example - * cy.server() - * // spy on POST /todos requests - * cy.route('POST', '/todos').as('add-todo') - */ - route(method: string, url: string | RegExp, response?: string | object): Chainable - /** - * @deprecated Use `cy.intercept()` instead. - * - * Set a route by returning an object literal from a callback function. - * Functions that return a Promise will automatically be awaited. - * - * @see https://on.cypress.io/route - * @example - * cy.server() - * cy.route(() => { - * // your logic here - * // return an appropriate routing object here - * return { - * method: 'POST', - * url: '/comments', - * response: this.commentsFixture - * } - * }) - */ - route(fn: () => RouteOptions): Chainable - /** - * @deprecated Use `cy.intercept()` instead. - * - * Spy or stub a given route. - * - * @see https://on.cypress.io/route - * @example - * cy.server() - * cy.route({ - * method: 'DELETE', - * url: '/users', - * status: 412, - * delay: 1000 - * // and other options, see documentation - * }) - */ - route(options: Partial): Chainable - /** * Take a screenshot of the application under test and the Cypress Command Log. * @@ -1783,26 +1895,6 @@ declare namespace Cypress { */ select(valueOrTextOrIndex: string | number | Array, options?: Partial): Chainable - /** - * @deprecated Use `cy.intercept()` instead. - * - * Start a server to begin routing responses to `cy.route()` and `cy.request()`. - * - * @example - * // start server - * cy.server() - * // get default server options - * cy.server().should((server) => { - * expect(server.delay).to.eq(0) - * expect(server.method).to.eq('GET') - * expect(server.status).to.eq(200) - * // and many others options - * }) - * - * @see https://on.cypress.io/server - */ - server(options?: Partial): Chainable - /** * Set a browser cookie. * @@ -2404,10 +2496,6 @@ declare namespace Cypress { type Agent = SinonSpyAgent & T - interface CookieDefaults { - preserve: string | string[] | RegExp | ((cookie: Cookie) => boolean) - } - interface Failable { /** * Whether to fail on response codes other than 2xx and 3xx @@ -2637,7 +2725,7 @@ declare namespace Cypress { interface CookieOptions extends Partial { /** * Domain to set cookies on or get cookies from - * @default superdomain of the current app under test + * @default hostname of the current app under test */ domain?: string } @@ -2695,7 +2783,7 @@ declare namespace Cypress { */ env: { [key: string]: any } /** - * A String or Array of glob patterns used to ignore test files that would otherwise be shown in your list of tests. Cypress uses minimatch with the options: {dot: true, matchBase: true}. We suggest using http://globtester.com to test what files would match. + * A String or Array of glob patterns used to ignore test files that would otherwise be shown in your list of tests. Cypress uses minimatch with the options: {dot: true, matchBase: true}. We suggest using a tool to test what files would match. * @default "*.hot-update.js" */ excludeSpecPattern: string | string[] @@ -2817,8 +2905,7 @@ declare namespace Cypress { */ supportFile: string | false /** - * The test isolation ensures a clean browser context between tests. This option is only available when - * `experimentalSessionAndOrigin=true`. + * The test isolation ensures a clean browser context between tests. * * Cypress will always reset/clear aliases, intercepts, clock, and viewport before each test * to ensure a clean test slate; i.e. this configuration only impacts the browser context. @@ -2826,23 +2913,23 @@ declare namespace Cypress { * Note: the [`cy.session()`](https://on.cypress.io/session) command will inherent this value to determine whether * or not the page is cleared when the command executes. This command is only available in end-to-end testing. * - * - on - The page is cleared before each test. Cookies, local storage and session storage in all domains are cleared + * - true - The page is cleared before each test. Cookies, local storage and session storage in all domains are cleared * before each test. The `cy.session()` command will also clear the page and current browser context when creating * or restoring the browser session. - * - off - The current browser state will persist between tests. The page does not clear before the test and cookies, local + * - false - The current browser state will persist between tests. The page does not clear before the test and cookies, local * storage and session storage will be available in the next test. The `cy.session()` command will only clear the * current browser context when creating or restoring the browser session - the current page will not clear. * * Tradeoffs: * Turning test isolation off may improve performance of end-to-end tests, however, previous tests could impact the * browser state of the next test and cause inconsistency when using .only(). Be mindful to write isolated tests when - * test isolation is off. If a test in the suite impacts the state of other tests and it were to fail, you could see + * test isolation is false. If a test in the suite impacts the state of other tests and it were to fail, you could see * misleading errors in later tests which makes debugging clunky. See the [documentation](https://on.cypress.io/test-isolation) * for more information. * - * @default null, when experimentalSessionAndOrigin=false. The default is 'on' when experimentalSessionAndOrigin=true. + * @default true */ - testIsolation: null | 'on' | 'off' + testIsolation: boolean /** * Path to folder where videos will be saved after a headless or CI run * @default "cypress/videos" @@ -2903,11 +2990,6 @@ declare namespace Cypress { * @default false */ experimentalInteractiveRunEvents: boolean - /** - * Enables cross-origin and improved session support, including the `cy.origin` and `cy.session` commands. See https://on.cypress.io/origin and https://on.cypress.io/session. - * @default false - */ - experimentalSessionAndOrigin: boolean /** * Whether Cypress will search for and replace obstructive code in third party .js or .html files. * NOTE: Setting this flag to true removes Subresource Integrity (SRI). @@ -2983,7 +3065,7 @@ declare namespace Cypress { * Override default config options for E2E Testing runner. * @default {} */ - e2e: Omit + e2e: EndToEndConfigOptions /** * An array of objects defining the certificates @@ -2998,6 +3080,19 @@ declare namespace Cypress { indexHtmlFile: string } + interface EndToEndConfigOptions extends Omit { + /** + * Enables the "Run All Specs" UI feature, allowing the execution of multiple specs sequentially. + * @default false + */ + experimentalRunAllSpecs?: boolean + /** + * Enables support for require/import within cy.origin. + * @default false + */ + experimentalOriginDependencies?: boolean + } + /** * Options appended to config object on runtime. */ @@ -3071,19 +3166,17 @@ declare namespace Cypress { socketIoRoute: string spec: Cypress['spec'] | null specs: Array - xhrRoute: string - xhrUrl: string } interface SuiteConfigOverrides extends Partial< - Pick + Pick >, Partial> { browser?: IsBrowserMatcher | IsBrowserMatcher[] keystrokeDelay?: number } interface TestConfigOverrides extends Partial< - Pick + Pick >, Partial> { browser?: IsBrowserMatcher | IsBrowserMatcher[] keystrokeDelay?: number @@ -3121,7 +3214,7 @@ declare namespace Cypress { type DevServerFn = (cypressDevServerConfig: DevServerConfig, devServerConfig: ComponentDevServerOpts) => ResolvedDevServerConfig | Promise type ConfigHandler = T - | (() => T | Promise) + | (() => T | Promise) type DevServerConfigOptions = { bundler: 'webpack' @@ -3132,15 +3225,15 @@ declare namespace Cypress { framework: 'react' | 'vue' | 'svelte' viteConfig?: ConfigHandler, undefined>, 'base' | 'root'>> } | { - bundler: 'webpack', - framework: 'angular', - webpackConfig?: ConfigHandler>, + bundler: 'webpack' + framework: 'angular' + webpackConfig?: ConfigHandler> options?: { projectConfig: AngularDevServerProjectConfig } } - interface ComponentConfigOptions extends Omit { + interface ComponentConfigOptions extends Omit { devServer: DevServerFn | DevServerConfigOptions devServerConfig?: ComponentDevServerOpts /** @@ -3329,28 +3422,6 @@ declare namespace Cypress { interval: number } - /** - * Setting default options for cy.server() - * @see https://on.cypress.io/server - */ - interface ServerOptions { - delay: number - method: HttpMethod - status: number - headers: object - response: any - onRequest(...args: any[]): void - onResponse(...args: any[]): void - onAbort(...args: any[]): void - enable: boolean - force404: boolean - urlMatchingOptions: object - ignore(xhr: Request): void - onAnyRequest(route: RouteOptions, proxy: any): void - onAnyResponse(route: RouteOptions, proxy: any): void - onAnyAbort(route: RouteOptions, proxy: any): void - } - interface Session { // Clear all saved sessions and re-run the current spec file. clearAllSavedSessions: () => Promise @@ -5770,7 +5841,7 @@ declare namespace Cypress { * Useful for debugging purposes if you're confused about the order in which commands will execute. * @see https://on.cypress.io/catalog-of-events#App-Events */ - (action: 'command:enqueued', fn: (command: EnqueuedCommand) => void): Cypress + (action: 'command:enqueued', fn: (command: EnqueuedCommandAttributes) => void): Cypress /** * Fires when cy begins actually running and executing your command. * Useful for debugging and understanding how the command queue is async. @@ -5898,7 +5969,7 @@ declare namespace Cypress { sameSite?: SameSiteStatus } - interface EnqueuedCommand { + interface EnqueuedCommandAttributes { id: string name: string args: any[] @@ -5906,9 +5977,17 @@ declare namespace Cypress { chainerId: string injected: boolean userInvocationStack?: string + query?: boolean fn(...args: any[]): any } + interface Command { + get(attr: K): EnqueuedCommandAttributes[K] + get(): EnqueuedCommandAttributes + set(key: K, value: EnqueuedCommandAttributes[K]): Log + set(options: Partial): Log + } + interface Exec { code: number stdout: string @@ -5987,28 +6066,6 @@ declare namespace Cypress { viewportHeight: number } - interface WaitXHR { - duration: number - id: string - method: HttpMethod - request: { - body: string | ObjectLike - headers: ObjectLike - } - requestBody: WaitXHR['request']['body'] - requestHeaders: WaitXHR['request']['headers'] - response: { - body: string | ObjectLike - headers: ObjectLike - } - responseBody: WaitXHR['response']['body'] - responseHeaders: WaitXHR['response']['headers'] - status: number - statusMessage: string - url: string - xhr: XMLHttpRequest - } - type Encodings = 'ascii' | 'base64' | 'binary' | 'hex' | 'latin1' | 'utf8' | 'utf-8' | 'ucs2' | 'ucs-2' | 'utf16le' | 'utf-16le' | null type PositionType = 'topLeft' | 'top' | 'topRight' | 'left' | 'center' | 'right' | 'bottomLeft' | 'bottom' | 'bottomRight' type ViewportPreset = 'macbook-16' | 'macbook-15' | 'macbook-13' | 'macbook-11' | 'ipad-2' | 'ipad-mini' | 'iphone-xr' | 'iphone-x' | 'iphone-6+' | 'iphone-se2' | 'iphone-8' | 'iphone-7' | 'iphone-6' | 'iphone-5' | 'iphone-4' | 'iphone-3' | 'samsung-s10' | 'samsung-note9' diff --git a/cli/types/tests/actions.ts b/cli/types/tests/actions.ts index 831aaee0fe84..6ebf7799a69f 100644 --- a/cli/types/tests/actions.ts +++ b/cli/types/tests/actions.ts @@ -46,7 +46,7 @@ Cypress.on('scrolled', ($el) => { }) Cypress.on('command:enqueued', (command) => { - command // $ExpectType EnqueuedCommand + command // $ExpectType EnqueuedCommandAttributes }) Cypress.on('command:start', (command) => { diff --git a/cli/types/tests/cypress-tests.ts b/cli/types/tests/cypress-tests.ts index 2119c9acd35f..7bebba4080ab 100644 --- a/cli/types/tests/cypress-tests.ts +++ b/cli/types/tests/cypress-tests.ts @@ -39,7 +39,7 @@ namespace CypressConfigTests { Cypress.config({ e2e: { baseUrl: '.', }}) // $ExpectError Cypress.config({ component: { baseUrl: '.', devServer: () => ({} as any) } }) // $ExpectError Cypress.config({ e2e: { indexHtmlFile: 'index.html' } }) // $ExpectError - Cypress.config({ testIsolation: 'off' }) // $ExpectError + Cypress.config({ testIsolation: false }) // $ExpectError Cypress.config('taskTimeout') // $ExpectType number Cypress.config('includeShadowDom') // $ExpectType boolean @@ -69,6 +69,7 @@ namespace CypressIsCyTests { declare namespace Cypress { interface Chainable { newCommand: (arg: string) => Chainable + newQuery: (arg: string) => Chainable } } @@ -291,6 +292,27 @@ namespace CypressCommandsTests { return originalFn(element, text, options) }) + + Cypress.Commands.addQuery('newQuery', function(arg) { + this // $ExpectType Command + arg // $ExpectType string + return () => 3 + }) +} + +namespace CypressNowTest { + cy.now('get') // $ExpectType Promise | ((subject: any) => any) +} + +namespace CypressEnsuresTest { + Cypress.ensure.isType('', ['optional', 'element'], 'newQuery', cy) // $ExpectType void + Cypress.ensure.isElement('', 'newQuery', cy) // $ExpectType void + Cypress.ensure.isWindow('', 'newQuery', cy) // $ExpectType void + Cypress.ensure.isDocument('', 'newQuery', cy) // $ExpectType void + + Cypress.ensure.isAttached('', 'newQuery', cy) // $ExpectType void + Cypress.ensure.isNotDisabled('', 'newQuery') // $ExpectType void + Cypress.ensure.isVisible('', 'newQuery') // $ExpectType void } namespace CypressLogsTest { @@ -868,7 +890,7 @@ namespace CypressTestConfigOverridesTests { retries: { run: 3 } // $ExpectError }, () => { }) it('test', { - testIsolation: 'off', // $ExpectError + testIsolation: false, // $ExpectError }, () => { }) it.skip('test', {}, () => {}) @@ -887,7 +909,7 @@ namespace CypressTestConfigOverridesTests { }, () => {}) describe('suite', { - testIsolation: 'off', + testIsolation: false, }, () => {}) context('suite', {}, () => {}) @@ -1062,3 +1084,29 @@ namespace CypressClearCookiesTests { cy.clearCookies({ timeout: '10' }) // $ExpectError cy.clearCookies({ domain: false }) // $ExpectError } + +namespace CypressLocalStorageTests { + cy.getAllLocalStorage().then((result) => { + result // $ExpectType StorageByOrigin + }) + cy.getAllLocalStorage({ log: false }) + cy.getAllLocalStorage({ log: 'true' }) // $ExpectError + + cy.clearAllLocalStorage().then((result) => { + result // $ExpectType null + }) + cy.clearAllLocalStorage({ log: false }) + cy.clearAllLocalStorage({ log: 'true' }) // $ExpectError + + cy.getAllSessionStorage().then((result) => { + result // $ExpectType StorageByOrigin + }) + cy.getAllSessionStorage({ log: false }) + cy.getAllSessionStorage({ log: 'true' }) // $ExpectError + + cy.clearAllSessionStorage().then((result) => { + result // $ExpectType null + }) + cy.clearAllSessionStorage({ log: false }) + cy.clearAllSessionStorage({ log: 'true' }) // $ExpectError +} diff --git a/cli/types/tests/kitchen-sink.ts b/cli/types/tests/kitchen-sink.ts index 5f5085ae8b1c..7ddd77619ae0 100644 --- a/cli/types/tests/kitchen-sink.ts +++ b/cli/types/tests/kitchen-sink.ts @@ -18,14 +18,6 @@ result // $ExpectType boolean Cypress.minimatch('/users/1/comments', '/users/*/comments') // $ExpectType boolean -// check if cy.server() yields default server options -cy.server().should((server) => { - server // $ExpectType ServerOptions - expect(server.delay).to.eq(0) - expect(server.method).to.eq('GET') - expect(server.status).to.eq(200) -}) - cy.visit('https://www.acme.com/', { auth: { username: 'wile', @@ -33,13 +25,6 @@ cy.visit('https://www.acme.com/', { } }) -const serverOptions: Partial = { - delay: 100, - ignore: () => true -} - -cy.server(serverOptions) - Cypress.spec.name // $ExpectType string Cypress.spec.relative // $ExpectType string Cypress.spec.absolute // $ExpectType string diff --git a/npm/cypress-schematic/CHANGELOG.md b/npm/cypress-schematic/CHANGELOG.md index d6834f375ad8..978c569eb4f9 100644 --- a/npm/cypress-schematic/CHANGELOG.md +++ b/npm/cypress-schematic/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/schematic-v2.4.0](https://github.com/cypress-io/cypress/compare/@cypress/schematic-v2.3.0...@cypress/schematic-v2.4.0) (2022-12-02) + + +### Features + +* Queries, Detached DOM, and Retry-Ability ([#24628](https://github.com/cypress-io/cypress/issues/24628)) ([9ae911f](https://github.com/cypress-io/cypress/commit/9ae911f396fa6cac0a1464537d1492d68cbb1898)), closes [#23665](https://github.com/cypress-io/cypress/issues/23665) [#24022](https://github.com/cypress-io/cypress/issues/24022) [#23791](https://github.com/cypress-io/cypress/issues/23791) [#24203](https://github.com/cypress-io/cypress/issues/24203) [#24417](https://github.com/cypress-io/cypress/issues/24417) + # [@cypress/schematic-v2.3.0](https://github.com/cypress-io/cypress/compare/@cypress/schematic-v2.2.0...@cypress/schematic-v2.3.0) (2022-11-01) diff --git a/npm/cypress-schematic/README.md b/npm/cypress-schematic/README.md index c99fc139dd18..2b87a8322483 100644 --- a/npm/cypress-schematic/README.md +++ b/npm/cypress-schematic/README.md @@ -166,7 +166,7 @@ It may be useful to have different Cypress configuration files per environment ( "builder": "@cypress/schematic:cypress", "options": { "devServerTarget": "{project-name}:serve", - "configFile": "cypress.production.json" + "configFile": "cypress.production.js" }, "configurations": { "production": { @@ -226,7 +226,7 @@ Read our docs to learn more about working with [reporters](https://on.cypress.io ### Running the builder with a different baseUrl -You can specify a `baseUrl` that is different than the one in `cypress.json`. There are two ways to do this. +You can specify a `baseUrl` that is different than the one in `cypress.config.js`. There are two ways to do this. 1. Add `baseUrl` to `configurations` like the following: diff --git a/npm/cypress-schematic/src/e2e.spec.ts b/npm/cypress-schematic/src/e2e.spec.ts index 47bd3c434eed..e65ce18c5781 100644 --- a/npm/cypress-schematic/src/e2e.spec.ts +++ b/npm/cypress-schematic/src/e2e.spec.ts @@ -27,7 +27,7 @@ const cypressSchematicPackagePath = path.join(__dirname, '..') const ANGULAR_PROJECTS: ProjectFixtureDir[] = ['angular-13', 'angular-14'] describe('ng add @cypress/schematic / only e2e', function () { - this.timeout(1000 * 60 * 4) + this.timeout(1000 * 60 * 5) for (const project of ANGULAR_PROJECTS) { it('should install e2e files by default', async () => { diff --git a/npm/mount-utils/CHANGELOG.md b/npm/mount-utils/CHANGELOG.md index 97153754cebd..7621fc2ece95 100644 --- a/npm/mount-utils/CHANGELOG.md +++ b/npm/mount-utils/CHANGELOG.md @@ -1,3 +1,15 @@ +# [@cypress/mount-utils-v4.0.0](https://github.com/cypress-io/cypress/compare/@cypress/mount-utils-v3.0.0...@cypress/mount-utils-v4.0.0) (2022-12-02) + + +### chore + +* remove experimentalSessionAndOrigin flag ([#24340](https://github.com/cypress-io/cypress/issues/24340)) ([69873ae](https://github.com/cypress-io/cypress/commit/69873ae9884228f15310fd151e42cbc0cb712817)) + + +### BREAKING CHANGES + +* removed experimentalSessionAndOrigin flag. testIsolation defaults to strict + # [@cypress/mount-utils-v3.0.0](https://github.com/cypress-io/cypress/compare/@cypress/mount-utils-v2.1.0...@cypress/mount-utils-v3.0.0) (2022-11-07) diff --git a/npm/mount-utils/src/index.ts b/npm/mount-utils/src/index.ts index ac22dbfe52b5..87ace86aa7af 100644 --- a/npm/mount-utils/src/index.ts +++ b/npm/mount-utils/src/index.ts @@ -44,6 +44,18 @@ export function setupHooks (optionalCallback?: Function) { ) }) + Cypress.Commands.overwrite('session', () => { + throw new Error( + 'cy.session from a component spec is not allowed', + ) + }) + + Cypress.Commands.overwrite('origin', () => { + throw new Error( + 'cy.origin from a component spec is not allowed', + ) + }) + // @ts-ignore Cypress.on('test:before:run', () => { optionalCallback?.() diff --git a/npm/react/CHANGELOG.md b/npm/react/CHANGELOG.md index eb4ff6d9e418..8d0d642dffd8 100644 --- a/npm/react/CHANGELOG.md +++ b/npm/react/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/react-v7.0.2](https://github.com/cypress-io/cypress/compare/@cypress/react-v7.0.1...@cypress/react-v7.0.2) (2022-12-02) + + +### Bug Fixes + +* remove cypress.server.defaults, cy.server and cy.route ([#24411](https://github.com/cypress-io/cypress/issues/24411)) ([2f18a8c](https://github.com/cypress-io/cypress/commit/2f18a8cbd2d1a90fe1f77a29cdc89571bf54109e)) + # [@cypress/react-v7.0.1](https://github.com/cypress-io/cypress/compare/@cypress/react-v7.0.0...@cypress/react-v7.0.1) (2022-11-08) diff --git a/npm/react/cypress/component/advanced/testing-lib-example/README.md b/npm/react/cypress/component/advanced/testing-lib-example/README.md index 928175a30c66..e05512916a3c 100644 --- a/npm/react/cypress/component/advanced/testing-lib-example/README.md +++ b/npm/react/cypress/component/advanced/testing-lib-example/README.md @@ -7,8 +7,7 @@ You can install and bring [Testing library/Cypress](https://testing-library.com/ ```js it('loads and displays greeting (testing-lib)', () => { - cy.server() - cy.route('/greeting', { greeting: 'Hello there' }).as('greet') + cy.intercept('/greeting', { greeting: 'Hello there' }).as('greet') const url = '/greeting' mount() @@ -19,7 +18,7 @@ it('loads and displays greeting (testing-lib)', () => { cy.findByRole('heading').should('have.text', 'Hello there') cy.findByRole('button').should('be.disabled') cy.get('@greet') - .its('url') + .its('response.url') .should('match', /\/greeting$/) }) ``` diff --git a/npm/react/cypress/component/advanced/testing-lib-example/spec.cy.jsx b/npm/react/cypress/component/advanced/testing-lib-example/spec.cy.jsx index a23403687f54..f364780e6731 100644 --- a/npm/react/cypress/component/advanced/testing-lib-example/spec.cy.jsx +++ b/npm/react/cypress/component/advanced/testing-lib-example/spec.cy.jsx @@ -3,8 +3,7 @@ import { mount } from '@cypress/react' import Fetcher from './fetcher' it('loads and displays greeting', () => { - cy.server() - cy.route('/greeting', { greeting: 'Hello there' }).as('greet') + cy.intercept('/greeting', { greeting: 'Hello there' }).as('greet') const url = '/greeting' @@ -14,6 +13,6 @@ it('loads and displays greeting', () => { cy.get('[role=heading]').should('have.text', 'Hello there') cy.get('[role=button]').should('be.disabled') cy.get('@greet') - .its('url') + .its('response.url') .should('match', /\/greeting$/) }) diff --git a/npm/react/cypress/component/advanced/testing-lib-example/testing-lib.cy.jsx b/npm/react/cypress/component/advanced/testing-lib-example/testing-lib.cy.jsx index 3460b016108d..e7541a3fe7b2 100644 --- a/npm/react/cypress/component/advanced/testing-lib-example/testing-lib.cy.jsx +++ b/npm/react/cypress/component/advanced/testing-lib-example/testing-lib.cy.jsx @@ -7,8 +7,7 @@ import Fetcher from './fetcher' // NOTE: this doesn't work because of update to the @testing/library v7. Looks like build issue with current webpack config it.skip('loads and displays greeting (testing-lib)', () => { - cy.server() - cy.route('/greeting', { greeting: 'Hello there' }).as('greet') + cy.intercept('/greeting', { greeting: 'Hello there' }).as('greet') const url = '/greeting' @@ -21,6 +20,6 @@ it.skip('loads and displays greeting (testing-lib)', () => { cy.findByRole('heading').should('have.text', 'Hello there') cy.findByRole('button').should('be.disabled') cy.get('@greet') - .its('url') + .its('response.url') .should('match', /\/greeting$/) }) diff --git a/npm/react/cypress/component/basic/network/1-users.cy.jsx b/npm/react/cypress/component/basic/network/1-users.cy.jsx index 60feb015c9c2..88d391661512 100644 --- a/npm/react/cypress/component/basic/network/1-users.cy.jsx +++ b/npm/react/cypress/component/basic/network/1-users.cy.jsx @@ -15,14 +15,8 @@ context('Users', () => { }) describe('Network State', () => { - beforeEach(() => { - cy.server() - // mount the component after defining routes in tests - // preventing race conditions where you wait on untouched routes - }) - it('can inspect real data in XHR', () => { - cy.route('/users?_limit=3').as('users') + cy.intercept('/users?_limit=3').as('users') mount() cy.wait('@users') .its('response.body') @@ -34,7 +28,7 @@ context('Users', () => { it('can display mock XHR response', () => { const users = [{ id: 1, name: 'foo' }] - cy.route('GET', '/users?_limit=3', users).as('users') + cy.intercept('GET', '/users?_limit=3', users).as('users') mount() cy.get('li') .should('have.length', 1) @@ -45,7 +39,7 @@ context('Users', () => { it('can inspect mocked XHR', () => { const users = [{ id: 1, name: 'foo' }] - cy.route('GET', '/users?_limit=3', users).as('users') + cy.intercept('GET', '/users?_limit=3', users).as('users') mount() cy.wait('@users') .its('response.body') @@ -55,10 +49,8 @@ context('Users', () => { it('can delay and wait on XHR', () => { const users = [{ id: 1, name: 'foo' }] - cy.route({ - method: 'GET', - url: '/users?_limit=3', - response: users, + cy.intercept('GET', '/users?_limit=3', { + body: users, delay: 1000, }).as('users') diff --git a/npm/react/cypress/component/basic/network/2-users-fetch.cy.jsx b/npm/react/cypress/component/basic/network/2-users-fetch.cy.jsx index a60d6add000c..86dc0541282b 100644 --- a/npm/react/cypress/component/basic/network/2-users-fetch.cy.jsx +++ b/npm/react/cypress/component/basic/network/2-users-fetch.cy.jsx @@ -13,15 +13,9 @@ describe('Users with Fetch', () => { // https://github.com/bahmutov/@cypress/react/issues/347 context('mocking', () => { - beforeEach(() => { - cy.server() - // mount the component after defining routes in tests - // preventing race conditions where you wait on untouched routes - }) - it('can inspect real data from the server', () => { // spy on the request - cy.route('/users?_limit=3').as('users') + cy.intercept('/users?_limit=3').as('users') mount() cy.wait('@users') .its('response.body') @@ -34,7 +28,7 @@ describe('Users with Fetch', () => { const users = [{ id: 1, name: 'foo' }] // stub the request - cy.route('GET', '/users?_limit=3', users).as('users') + cy.intercept('GET', '/users?_limit=3', users).as('users') mount() cy.get('li') .should('have.length', 1) @@ -45,7 +39,7 @@ describe('Users with Fetch', () => { it('can inspect mocked network reaponse', () => { const users = [{ id: 1, name: 'foo' }] - cy.route('GET', '/users?_limit=3', users).as('users') + cy.intercept('GET', '/users?_limit=3', users).as('users') mount() cy.wait('@users') .its('response.body') @@ -55,10 +49,8 @@ describe('Users with Fetch', () => { it('can delay and wait on Ajax call', () => { const users = [{ id: 1, name: 'foo' }] - cy.route({ - method: 'GET', - url: '/users?_limit=3', - response: users, + cy.intercept('GET', '/users?_limit=3', { + body: users, delay: 1000, }).as('users') diff --git a/npm/vite-dev-server/CHANGELOG.md b/npm/vite-dev-server/CHANGELOG.md index 65687aa877a3..07dbe0c0445f 100644 --- a/npm/vite-dev-server/CHANGELOG.md +++ b/npm/vite-dev-server/CHANGELOG.md @@ -1,3 +1,15 @@ +# [@cypress/vite-dev-server-v5.0.0](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v4.0.1...@cypress/vite-dev-server-v5.0.0) (2022-12-02) + + +### chore + +* remove experimentalSessionAndOrigin flag ([#24340](https://github.com/cypress-io/cypress/issues/24340)) ([69873ae](https://github.com/cypress-io/cypress/commit/69873ae9884228f15310fd151e42cbc0cb712817)) + + +### BREAKING CHANGES + +* removed experimentalSessionAndOrigin flag. testIsolation defaults to strict + # [@cypress/vite-dev-server-v4.0.1](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v4.0.0...@cypress/vite-dev-server-v4.0.1) (2022-11-08) diff --git a/npm/vite-dev-server/cypress.config.ts b/npm/vite-dev-server/cypress.config.ts index 9109a38747ae..335561f589b9 100644 --- a/npm/vite-dev-server/cypress.config.ts +++ b/npm/vite-dev-server/cypress.config.ts @@ -3,7 +3,6 @@ import { defineConfig } from 'cypress' export default defineConfig({ projectId: 'ypt4pf', e2e: { - experimentalSessionAndOrigin: true, defaultCommandTimeout: 10000, // these take a bit longer b/c they're e2e open mode test async setupNodeEvents (on, config) { if (!process.env.HTTP_PROXY_TARGET_FOR_ORIGIN_REQUESTS) { diff --git a/npm/vue/CHANGELOG.md b/npm/vue/CHANGELOG.md index 019e48d7ab13..2619fc00a348 100644 --- a/npm/vue/CHANGELOG.md +++ b/npm/vue/CHANGELOG.md @@ -1,3 +1,17 @@ +# [@cypress/vue-v5.0.3](https://github.com/cypress-io/cypress/compare/@cypress/vue-v5.0.2...@cypress/vue-v5.0.3) (2022-12-02) + + +### Bug Fixes + +* remove cypress.server.defaults, cy.server and cy.route ([#24411](https://github.com/cypress-io/cypress/issues/24411)) ([2f18a8c](https://github.com/cypress-io/cypress/commit/2f18a8cbd2d1a90fe1f77a29cdc89571bf54109e)) + +# [@cypress/vue-v5.0.2](https://github.com/cypress-io/cypress/compare/@cypress/vue-v5.0.1...@cypress/vue-v5.0.2) (2022-11-23) + + +### Bug Fixes + +* fix windows-lint CI job ([#24758](https://github.com/cypress-io/cypress/issues/24758)) ([2166ba0](https://github.com/cypress-io/cypress/commit/2166ba0d9496037df843d55f07517f83817171a3)) + # [@cypress/vue-v5.0.1](https://github.com/cypress-io/cypress/compare/@cypress/vue-v5.0.0...@cypress/vue-v5.0.1) (2022-11-08) diff --git a/npm/vue/cypress/component/advanced/fetch-polyfill/Users.cy.js b/npm/vue/cypress/component/advanced/fetch-polyfill/Users.cy.js index 55d4215e5610..00c943821c20 100644 --- a/npm/vue/cypress/component/advanced/fetch-polyfill/Users.cy.js +++ b/npm/vue/cypress/component/advanced/fetch-polyfill/Users.cy.js @@ -10,21 +10,18 @@ describe('Fetching users with polyfill', () => { }) it('can spy on the fetch requests', () => { - cy.server() - cy.route('/users?_limit=3').as('users') + cy.intercept('/users?_limit=3').as('users') mount(Users) cy.wait('@users') - .its('responseBody.length') + .its('response.body.length') .then((length) => { cy.get('.user').should('have.length', length) }) }) it('shows loading UI while fetch is happening', () => { - cy.server() - cy.route({ - url: '/users?_limit=3', - response: 'fixture:users', + cy.intercept('/users?_limit=3', { + fixture: 'users', delay: 1000, }) diff --git a/npm/vue/cypress/component/test-utils-api/TestUtilsApi.vue b/npm/vue/cypress/component/test-utils-api/TestUtilsApi.vue index c1b44058d66a..820dcc9780f3 100644 --- a/npm/vue/cypress/component/test-utils-api/TestUtilsApi.vue +++ b/npm/vue/cypress/component/test-utils-api/TestUtilsApi.vue @@ -6,7 +6,10 @@ diff --git a/packages/app/src/specs/InlineSpecList.cy.tsx b/packages/app/src/specs/InlineSpecList.cy.tsx index 1d721a30db61..b87071603260 100644 --- a/packages/app/src/specs/InlineSpecList.cy.tsx +++ b/packages/app/src/specs/InlineSpecList.cy.tsx @@ -1,11 +1,11 @@ -import { Specs_InlineSpecListFragment, Specs_InlineSpecListFragmentDoc, SpecFilter_SetPreferencesDocument } from '../generated/graphql-test' +import { Specs_InlineSpecListFragment, Specs_InlineSpecListFragmentDoc, SpecFilter_SetPreferencesDocument, RunAllSpecsDocument } from '../generated/graphql-test' import InlineSpecList from './InlineSpecList.vue' import { defaultMessages } from '@cy/i18n' let specs: Array = [] describe('InlineSpecList', () => { - const mountInlineSpecList = (specFilter?: string) => cy.mountFragment(Specs_InlineSpecListFragmentDoc, { + const mountInlineSpecList = ({ specFilter, experimentalRunAllSpecs }: {specFilter?: string, experimentalRunAllSpecs?: boolean} = {}) => cy.mountFragment(Specs_InlineSpecListFragmentDoc, { onResult: (ctx) => { if (!ctx.currentProject?.specs) { return ctx @@ -16,6 +16,10 @@ describe('InlineSpecList', () => { ctx.currentProject.savedState = { specFilter } } + if (experimentalRunAllSpecs) { + ctx.currentProject.config = [{ field: 'experimentalRunAllSpecs', value: true }] + } + return ctx }, render: (gqlValue) => { @@ -147,7 +151,7 @@ describe('InlineSpecList', () => { beforeEach(() => { cy.fixture('found-specs').then((foundSpecs) => specs = foundSpecs) - mountInlineSpecList('saved-search-term 🗑') + mountInlineSpecList({ specFilter: 'saved-search-term 🗑' }) cy.findByLabelText(defaultMessages.specPage.searchPlaceholder) .as('searchField') @@ -184,4 +188,66 @@ describe('InlineSpecList', () => { cy.wrap(setSpecFilterStub).should('have.been.calledWith', '') }) }) + + describe('Run all Specs', () => { + const hoverRunAllSpecs = (directory: string, specNumber: number) => { + let command = cy.contains('[data-cy=directory-item]', directory) + + return command.realHover().then(() => { + cy.get('[data-cy=play-button]').should('exist') + cy.get(`[data-cy="run-all-specs-for-${directory}"]`).realHover().then(() => { + cy.get('[data-cy=tooltip-content]').should('contain.text', `Run ${specNumber} spec`) + }) + }) + } + + beforeEach(() => { + cy.fixture('found-specs').then((foundSpecs) => specs = foundSpecs) + }) + + it('does not show feature unless experimentalRunAllSpecs is enabled', () => { + mountInlineSpecList({ experimentalRunAllSpecs: false }) + + cy.findByTestId('run-all-specs-for-all').should('not.exist') + cy.contains('[data-cy=directory-item]', 'src').realHover() + cy.findByTestId('run-all-specs-for-src').should('not.exist') + }) + + it('displays runAllSpecs when hovering over a spec-list directory row', () => { + mountInlineSpecList({ experimentalRunAllSpecs: true }) + hoverRunAllSpecs('src', 4) + }) + + it('checks if functionality works after a search', () => { + mountInlineSpecList({ experimentalRunAllSpecs: true, specFilter: 'B' }) + hoverRunAllSpecs('src/components', 1) + }) + + it('allows keyboard interactions to run spec groups without toggling sections', () => { + // this test is specifically to catch regressions of a bug caused by nesting controls: https://github.com/cypress-io/cypress/issues/24762 + // TODO: #24966 remove this test when the structure of controls in this area has been flattened out + mountInlineSpecList({ experimentalRunAllSpecs: true }) + + const mutationStub = cy.stub().as('mutationStub') + + cy.stubMutationResolver(RunAllSpecsDocument, () => { + mutationStub() + }) + + cy.findAllByTestId('spec-file-item').should('have.length', 4) + cy.findAllByTestId('run-all-specs-button').eq(0) + .click() + .type(' ') + + // make sure typing didn't change displayed items + cy.findAllByTestId('spec-file-item').should('have.length', 4) + cy.findAllByTestId('run-all-specs-button').eq(1) + .focus() + .type('{enter}') + + // make sure typing didn't change displayed items + cy.findAllByTestId('spec-file-item').should('have.length', 4) + cy.get('@mutationStub').should('have.been.calledThrice') + }) + }) }) diff --git a/packages/app/src/specs/InlineSpecList.vue b/packages/app/src/specs/InlineSpecList.vue index 8a7c0d447482..fc3a976cf5c8 100644 --- a/packages/app/src/specs/InlineSpecList.vue +++ b/packages/app/src/specs/InlineSpecList.vue @@ -9,7 +9,9 @@ (() => { return fuzzySortSpecs(specs, debouncedSpecFilterModel.value) }) +const runAllSpecsStore = useRunAllSpecsStore() + diff --git a/packages/app/src/specs/InlineSpecListHeader.cy.tsx b/packages/app/src/specs/InlineSpecListHeader.cy.tsx index d4949f2ad57a..7964b59307bd 100644 --- a/packages/app/src/specs/InlineSpecListHeader.cy.tsx +++ b/packages/app/src/specs/InlineSpecListHeader.cy.tsx @@ -1,29 +1,32 @@ import InlineSpecListHeader from './InlineSpecListHeader.vue' import { ref } from 'vue' import { defaultMessages } from '@cy/i18n' +import { defineStore } from 'pinia' describe('InlineSpecListHeader', () => { - const mountWithResultCount = (resultCount = 0) => { + const mountWithProps = (props: {resultCount?: number, isRunAllSpecsAllowed?: boolean} = {}) => { const specFilterModel = ref('') - const onNewSpec = cy.spy().as('new-spec') - cy.wrap(specFilterModel).as('specFilterModel') - - const methods = { + const propsWithDefaults = { + resultCount: props.resultCount ?? 0, + isRunAllSpecsAllowed: props.isRunAllSpecsAllowed ?? false, 'onUpdate:specFilterModel': (val: string) => { specFilterModel.value = val }, - onNewSpec, + onNewSpec: cy.spy().as('new-spec'), + onRunAllSpecs: cy.spy().as('run-all-specs'), } + cy.wrap(specFilterModel).as('specFilterModel') + cy.mount(() => (
- +
)) } it('should allow search', () => { - mountWithResultCount(0) + mountWithProps({ resultCount: 0 }) const searchString = 'my/component.cy.tsx' cy.findByLabelText(defaultMessages.specPage.searchPlaceholder) @@ -33,7 +36,7 @@ describe('InlineSpecListHeader', () => { }) it('should emit add spec', () => { - mountWithResultCount(0) + mountWithProps({ resultCount: 0 }) cy.findAllByLabelText(defaultMessages.specPage.newSpecButton) .click() .get('@new-spec') @@ -41,7 +44,7 @@ describe('InlineSpecListHeader', () => { }) it('clears search field when clear button is clicked', () => { - mountWithResultCount(0) + mountWithProps({ resultCount: 0 }) cy.findByTestId('clear-search-button') .should('not.exist') @@ -56,14 +59,37 @@ describe('InlineSpecListHeader', () => { }) it('exposes the result count correctly to assistive tech', () => { - mountWithResultCount(0) + mountWithProps({ resultCount: 0 }) cy.contains('No matches') .should('have.class', 'sr-only') .and('have.attr', 'aria-live', 'polite') - mountWithResultCount(1) + mountWithProps({ resultCount: 1 }) cy.contains('1 match').should('have.class', 'sr-only') - mountWithResultCount(100) + mountWithProps({ resultCount: 100 }) cy.contains('100 matches').should('have.class', 'sr-only') }) + + it('renders "Run All Specs" button with flag and emits on click', () => { + const EXPECTED_SPEC_COUNT = 2 + + // make a small store to simulate some specs existing + // without touching any of the gql used by the real store + const useRunAllSpecsStore = defineStore('runAllSpecs', { + state: () => ({ allSpecsRef: ref(Array(EXPECTED_SPEC_COUNT)) }), + }) + + useRunAllSpecsStore() + + mountWithProps({ isRunAllSpecsAllowed: true }) + cy.percySnapshot() + + cy.get('[data-cy=run-all-specs-for-all]').as('run-all-btn').realHover() + cy.contains(`Run ${EXPECTED_SPEC_COUNT} specs`).should('be.visible') + + cy.percySnapshot('with tooltip') + + cy.get('@run-all-btn').click() + cy.get('@run-all-specs').should('have.been.called') + }) }) diff --git a/packages/app/src/specs/InlineSpecListHeader.vue b/packages/app/src/specs/InlineSpecListHeader.vue index 919f1895b19c..23b27fcaddb5 100644 --- a/packages/app/src/specs/InlineSpecListHeader.vue +++ b/packages/app/src/specs/InlineSpecListHeader.vue @@ -1,14 +1,12 @@