diff --git a/.circleci/workflows.yml b/.circleci/workflows.yml
index 00adf40f7230..9f8c7c1c0c0c 100644
--- a/.circleci/workflows.yml
+++ b/.circleci/workflows.yml
@@ -2134,13 +2134,6 @@ jobs:
path: npm/grep/test_results
- store-npm-logs
- npm-create-cypress-tests:
- <<: *defaults
- resource_class: small
- steps:
- - restore_cached_workspace
- - run: yarn lerna run build --scope create-cypress-tests
-
npm-eslint-plugin-dev:
<<: *defaults
steps:
@@ -2798,9 +2791,6 @@ linux-x64-workflow: &linux-x64-workflow
- npm-mount-utils:
requires:
- build
- - npm-create-cypress-tests:
- requires:
- - build
- npm-eslint-plugin-dev:
requires:
- build
@@ -2820,7 +2810,6 @@ linux-x64-workflow: &linux-x64-workflow
- check-ts
- npm-angular
- npm-eslint-plugin-dev
- - npm-create-cypress-tests
- npm-react
- npm-mount-utils
- npm-vue
@@ -2876,7 +2865,6 @@ linux-x64-workflow: &linux-x64-workflow
- check-ts
- npm-angular
- npm-eslint-plugin-dev
- - npm-create-cypress-tests
- npm-react
- npm-mount-utils
- npm-vue
@@ -3194,9 +3182,6 @@ linux-x64-contributor-workflow: &linux-x64-contributor-workflow
- npm-mount-utils:
requires:
- build
- - npm-create-cypress-tests:
- requires:
- - build
- npm-eslint-plugin-dev:
requires:
- build
@@ -3216,7 +3201,6 @@ linux-x64-contributor-workflow: &linux-x64-contributor-workflow
- check-ts
- npm-angular
- npm-eslint-plugin-dev
- - npm-create-cypress-tests
- npm-puppeteer-unit-tests
- npm-puppeteer-cypress-tests
- npm-react
@@ -3272,7 +3256,6 @@ linux-x64-contributor-workflow: &linux-x64-contributor-workflow
- check-ts
- npm-angular
- npm-eslint-plugin-dev
- - npm-create-cypress-tests
- npm-react
- npm-mount-utils
- npm-vue
diff --git a/.eslintrc.js b/.eslintrc.js
index 0f6bc16d6bd2..999d42521ef8 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -53,8 +53,6 @@ module.exports = {
'tooling/**',
'packages/{app,driver,frontend-shared,launchpad}/cypress/**',
'*.test.ts',
- // ignore in packages that don't run in the Cypress process
- 'npm/create-cypress-tests/**',
],
rules: {
'no-restricted-properties': 'off',
diff --git a/.gitignore b/.gitignore
index b6583eab0c39..cb6f213a1c87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -92,7 +92,7 @@ system-tests/lib/fixtureDirs.ts
/packages/frontend-shared/src/generated
/packages/frontend-shared/cypress/e2e/support/e2eProjectDirs.ts
-# from npm/create-cypress-tests
+# from old npm/create-cypress-tests
/npm/create-cypress-tests/initial-template
/npm/create-cypress-tests/src/test-output
diff --git a/CHANGELOG.md b/CHANGELOG.md
index becc1f915c87..be435cb6b72d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,6 @@
- [Cypress App](https://on.cypress.io/changelog)
- [`@cypress/angular`](https://github.com/cypress-io/cypress/blob/develop/npm/angular/CHANGELOG.md)
-- [`@cypress/create-cypress-tests`](https://github.com/cypress-io/cypress/blob/develop/npm/create-cypress-tests/CHANGELOG.md)
- [`@cypress/eslint-plugin-dev`](https://github.com/cypress-io/cypress/blob/develop/npm/eslint-plugin-dev/CHANGELOG.md)
- [`@cypress/mount-utils`](https://github.com/cypress-io/cypress/blob/develop/npm/mount-utils/CHANGELOG.md)
- [`@cypress/react`](https://github.com/cypress-io/cypress/blob/develop/npm/react/CHANGELOG.md)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index db769e1eedd8..9acb46686376 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -183,7 +183,6 @@ Here is a list of the npm packages in this repository:
| Folder Name | Package Name | Purpose |
| :----------------------------------------------------- | :--------------------------------- | :--------------------------------------------------------------------------- |
| [angular](./npm/angular) | `@cypress/angular` | Cypress component testing for Angular. |
- | [create-cypress-tests](./npm/create-cypress-tests) | `@cypress/create-cypress-tests` | Tooling to scaffold Cypress configuration and demo test files. |
| [eslint-plugin-dev](./npm/eslint-plugin-dev) | `@cypress/eslint-plugin-dev` | Eslint plugin for internal development. |
| [grep](./npm/grep) | `@cypress/grep` | Filter tests using substring |
| [mount-utils](./npm/mount-utils) | `@cypress/mount-utils` | Common functionality for Vue/React/Angular adapters. |
diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md
index 45a27f6fc002..177c29e32d74 100644
--- a/cli/CHANGELOG.md
+++ b/cli/CHANGELOG.md
@@ -1,18 +1,19 @@
## 13.6.1
-_Released 12/5/2023 (PENDING)_
+_Released 12/5/2023_
**Bugfixes:**
- Fixed an issue where pages or downloads opened in a new tab were missing basic auth headers. Fixes [#28350](https://github.com/cypress-io/cypress/issues/28350).
- Fixed an issue where request logging would default the `message` to the `args` of the currently running command even though those `args` would not apply to the request log and are not displayed. If the `args` are sufficiently large (e.g. when running the `cy.task` from the [code-coverage](https://github.com/cypress-io/code-coverage/) plugin) there could be performance/memory implications. Addressed in [#28411](https://github.com/cypress-io/cypress/pull/28411).
-- Fixed an issue where commands would fail with the error `must only be invoked from the spec file or support file` if the project's `baseUrl` included basic auth credentials. Fixes [#28336](https://github.com/cypress-io/cypress/issues/28336).
+- Fixed an issue where commands would fail with the error `must only be invoked from the spec file or support file` if the project's `baseUrl` included basic auth credentials. Fixes [#27457](https://github.com/cypress-io/cypress/issues/27457) and [#28336](https://github.com/cypress-io/cypress/issues/28336).
- Fixed an issue where some URLs would timeout in pre-request correlation. Addressed in [#28427](https://github.com/cypress-io/cypress/pull/28427).
+- Cypress will now correctly log errors and debug logs on Linux machines. Fixes [#5051](https://github.com/cypress-io/cypress/issues/5051) and [#24713](https://github.com/cypress-io/cypress/issues/24713).
**Misc:**
-- Artifact upload duration is now reported to Cypress Cloud. Addressed in [#28418](https://github.com/cypress-io/cypress/pull/28418)
+- Artifact upload duration is now reported to Cypress Cloud. Fixes [#28238](https://github.com/cypress-io/cypress/issues/28238). Addressed in [#28418](https://github.com/cypress-io/cypress/pull/28418).
## 13.6.0
diff --git a/cli/lib/exec/spawn.js b/cli/lib/exec/spawn.js
index d158aa8eb7a9..dabf8f6a3233 100644
--- a/cli/lib/exec/spawn.js
+++ b/cli/lib/exec/spawn.js
@@ -4,7 +4,6 @@ const cp = require('child_process')
const path = require('path')
const Promise = require('bluebird')
const debug = require('debug')('cypress:cli')
-const debugElectron = require('debug')('cypress:electron')
const util = require('../util')
const state = require('../tasks/state')
@@ -122,10 +121,9 @@ module.exports = {
return new Promise((resolve, reject) => {
_.defaults(overrides, {
onStderrData: false,
- electronLogging: false,
})
- const { onStderrData, electronLogging } = overrides
+ const { onStderrData } = overrides
const envOverrides = util.getEnvOverrides(options)
const electronArgs = []
const node11WindowsFix = isPlatform('win32')
@@ -160,10 +158,6 @@ module.exports = {
stdioOptions = _.extend({}, stdioOptions, { windowsHide: false })
}
- if (electronLogging) {
- stdioOptions.env.ELECTRON_ENABLE_LOGGING = true
- }
-
if (util.isPossibleLinuxWithIncorrectDisplay()) {
// make sure we use the latest DISPLAY variable if any
debug('passing DISPLAY', process.env.DISPLAY)
@@ -241,7 +235,7 @@ module.exports = {
// if we have a callback and this explicitly returns
// false then bail
- if (onStderrData && onStderrData(str) === false) {
+ if (onStderrData && onStderrData(str)) {
return
}
@@ -294,13 +288,6 @@ module.exports = {
if (util.isBrokenGtkDisplay(str)) {
brokenGtkDisplay = true
}
-
- // we should attempt to always slurp up
- // the stderr logs unless we've explicitly
- // enabled the electron debug logging
- if (!debugElectron.enabled) {
- return false
- }
},
})
}
diff --git a/cli/lib/tasks/verify.js b/cli/lib/tasks/verify.js
index 826c35e1654f..2d946b301e37 100644
--- a/cli/lib/tasks/verify.js
+++ b/cli/lib/tasks/verify.js
@@ -101,12 +101,8 @@ const runSmokeTest = (binaryDir, options) => {
debug('smoke test command:', smokeTestCommand)
debug('smoke test timeout %d ms', options.smokeTestTimeout)
- const env = _.extend({}, process.env, {
- ELECTRON_ENABLE_LOGGING: true,
- })
-
const stdioOptions = _.extend({}, {
- env,
+ env: process.env,
timeout: options.smokeTestTimeout,
})
diff --git a/cli/test/lib/tasks/verify_spec.js b/cli/test/lib/tasks/verify_spec.js
index b81ff36a55b5..ab4fd5146be0 100644
--- a/cli/test/lib/tasks/verify_spec.js
+++ b/cli/test/lib/tasks/verify_spec.js
@@ -278,35 +278,6 @@ context('lib/tasks/verify', () => {
})
})
- it('sets ELECTRON_ENABLE_LOGGING without mutating process.env', () => {
- createfs({
- alreadyVerified: false,
- executable: mockfs.file({ mode: 0o777 }),
- packageVersion,
- })
-
- expect(process.env.ELECTRON_ENABLE_LOGGING).to.be.undefined
-
- util.exec.resolves()
- sinon.stub(util, 'stdoutLineMatches').returns(true)
-
- return verify
- .start()
- .then(() => {
- expect(process.env.ELECTRON_ENABLE_LOGGING).to.be.undefined
-
- const stdioOptions = util.exec.firstCall.args[2]
-
- expect(stdioOptions).to.include({
- timeout: verify.VERIFY_TEST_RUNNER_TIMEOUT_MS,
- })
-
- expect(stdioOptions.env).to.include({
- ELECTRON_ENABLE_LOGGING: true,
- })
- })
- })
-
describe('with force: true', () => {
beforeEach(() => {
createfs({
diff --git a/npm/create-cypress-tests/.eslintignore b/npm/create-cypress-tests/.eslintignore
deleted file mode 100644
index 341078756065..000000000000
--- a/npm/create-cypress-tests/.eslintignore
+++ /dev/null
@@ -1,9 +0,0 @@
-**/dist
-**/*.d.ts
-**/package-lock.json
-**/tsconfig.json
-**/cypress/fixtures
-**/test/fixtures
-**/__snapshots__
-/initial-template
-/**/*.template.*
\ No newline at end of file
diff --git a/npm/create-cypress-tests/.eslintrc b/npm/create-cypress-tests/.eslintrc
deleted file mode 100644
index d1ad4a04ebbf..000000000000
--- a/npm/create-cypress-tests/.eslintrc
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "plugins": [
- "cypress",
- "@cypress/dev"
- ],
- "extends": [
- "plugin:@cypress/dev/general",
- "plugin:@cypress/dev/tests"
- ],
- "env": {
- "cypress/globals": true
- },
- "rules": {
- "no-console": "off"
- }
-}
diff --git a/npm/create-cypress-tests/.mocharc.json b/npm/create-cypress-tests/.mocharc.json
deleted file mode 100644
index 05d782fced5a..000000000000
--- a/npm/create-cypress-tests/.mocharc.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "watch-ignore": [
- "node_modules"
- ],
- "require": "ts-node/register",
- "exit": true
-}
diff --git a/npm/create-cypress-tests/.npmignore b/npm/create-cypress-tests/.npmignore
deleted file mode 100644
index c9cfa44194a1..000000000000
--- a/npm/create-cypress-tests/.npmignore
+++ /dev/null
@@ -1,4 +0,0 @@
-./src/
-./initial-template/
-scripts/
-__snapshots__/
\ No newline at end of file
diff --git a/npm/create-cypress-tests/CHANGELOG.md b/npm/create-cypress-tests/CHANGELOG.md
deleted file mode 100644
index 720d4a52aab4..000000000000
--- a/npm/create-cypress-tests/CHANGELOG.md
+++ /dev/null
@@ -1,118 +0,0 @@
-# [create-cypress-tests-v2.0.4](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v2.0.3...create-cypress-tests-v2.0.4) (2023-10-16)
-
-# [create-cypress-tests-v2.0.3](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v2.0.2...create-cypress-tests-v2.0.3) (2023-09-07)
-
-# [create-cypress-tests-v2.0.2](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v2.0.1...create-cypress-tests-v2.0.2) (2023-04-07)
-
-# [create-cypress-tests-v2.0.1](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v2.0.0...create-cypress-tests-v2.0.1) (2023-01-03)
-
-
-### Bug Fixes
-
-* change wording for spec creation ([#25271](https://github.com/cypress-io/cypress/issues/25271)) ([c12a7e3](https://github.com/cypress-io/cypress/commit/c12a7e37c73d972eb0514e4b602940df210d86c7))
-
-# [create-cypress-tests-v2.0.0](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v1.3.0...create-cypress-tests-v2.0.0) (2022-06-13)
-
-
-### Bug Fixes
-
-* scope config to current testing type ([#20677](https://github.com/cypress-io/cypress/issues/20677)) ([61f7cfc](https://github.com/cypress-io/cypress/commit/61f7cfc59284a2938e0a1c15d74ee75215ba5f8b))
-* support using create-cypress-tests as part of build process ([#18714](https://github.com/cypress-io/cypress/issues/18714)) ([0501452](https://github.com/cypress-io/cypress/commit/0501452fb9e2df954ee871171052ab9f01367b25))
-* **unified-desktop-gui branch:** initial installation on windows ([#18247](https://github.com/cypress-io/cypress/issues/18247)) ([8614e97](https://github.com/cypress-io/cypress/commit/8614e978029bcbf7155b7ae98ac54feb11f2e7f3))
-
-
-### chore
-
-* prep npm packages for use with Cypress v10 ([b924d08](https://github.com/cypress-io/cypress/commit/b924d086ee2e2ccc93303731e001b2c9e9d0af17))
-
-
-### Features
-
-* Add vue2 package from npm/vue/v2 branch ([#21026](https://github.com/cypress-io/cypress/issues/21026)) ([3aa69e2](https://github.com/cypress-io/cypress/commit/3aa69e2538aae5702bfc48789c54f37263ce08fc))
-* Deprecate run-ct / open-ct, and update all examples to use --ct instead ([#18422](https://github.com/cypress-io/cypress/issues/18422)) ([196e8f6](https://github.com/cypress-io/cypress/commit/196e8f62cc6d27974f235945cb5700624b3dae41))
-* remove testFiles reference ([#20565](https://github.com/cypress-io/cypress/issues/20565)) ([5670344](https://github.com/cypress-io/cypress/commit/567034459089d9d53dfab5556cb9369fb335c3db))
-* update on-links ([#19235](https://github.com/cypress-io/cypress/issues/19235)) ([cc2d734](https://github.com/cypress-io/cypress/commit/cc2d7348185e2a090c60d92d9319ab460d8c7827))
-* Use .config files ([#18578](https://github.com/cypress-io/cypress/issues/18578)) ([081dd19](https://github.com/cypress-io/cypress/commit/081dd19cc6da3da229a7af9c84f62730c85a5cd6))
-* use supportFile by testingType ([#19364](https://github.com/cypress-io/cypress/issues/19364)) ([0366d4f](https://github.com/cypress-io/cypress/commit/0366d4fa8971e5e5189c6fd6450cc3c8d72dcfe1))
-
-
-### BREAKING CHANGES
-
-* new version of packages for Cypress v10
-
-# [create-cypress-tests-v1.3.0](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v1.2.0...create-cypress-tests-v1.3.0) (2021-12-16)
-
-
-### Bug Fixes
-
-* Restore broken gif ([#18987](https://github.com/cypress-io/cypress/issues/18987)) ([f251681](https://github.com/cypress-io/cypress/commit/f251681b814b102ca374abdef148b777c4e72c67))
-
-
-### Features
-
-* use hoisted yarn install in binary build ([#17285](https://github.com/cypress-io/cypress/issues/17285)) ([e4f5b10](https://github.com/cypress-io/cypress/commit/e4f5b106d49d6ac0857c5fdac886f83b99558c88))
-
-# [create-cypress-tests-v1.2.0](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v1.1.3...create-cypress-tests-v1.2.0) (2021-11-10)
-
-
-### Features
-
-* **deps:** update dependency electron to v15 🌟 ([#18317](https://github.com/cypress-io/cypress/issues/18317)) ([3095d73](https://github.com/cypress-io/cypress/commit/3095d733e92527ffd67344c6899211e058ceefa3))
-
-# [create-cypress-tests-v1.1.3](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v1.1.2...create-cypress-tests-v1.1.3) (2021-10-29)
-
-
-### Bug Fixes
-
-* revive type checker ([#18172](https://github.com/cypress-io/cypress/issues/18172)) ([af472b6](https://github.com/cypress-io/cypress/commit/af472b6419ecb2aec1abdb09df99b2fa5f56e033))
-
-# [create-cypress-tests-v1.1.2](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v1.1.1...create-cypress-tests-v1.1.2) (2021-06-17)
-
-
-### Bug Fixes
-
-* case issue create cypress tests with `react/plugins/load-webpack` ([#16961](https://github.com/cypress-io/cypress/issues/16961)) ([c37ecea](https://github.com/cypress-io/cypress/commit/c37ecea3ca462015637515b331d1c9828ac1ed29)), closes [#16960](https://github.com/cypress-io/cypress/issues/16960)
-
-# [create-cypress-tests-v1.1.1](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v1.1.0...create-cypress-tests-v1.1.1) (2021-05-10)
-
-
-### Bug Fixes
-
-* add return config for vitejs templates ([69d9de5](https://github.com/cypress-io/cypress/commit/69d9de581a03dce8e3535917a4cdcea8fa4eb6e9))
-* add return config for vueCli and vueWebpack ([9c12ee6](https://github.com/cypress-io/cypress/commit/9c12ee6d8467c65414ab2d413a9c45b2bbec64e9))
-* remove all of rollup, not supported anymore ([f8a71e7](https://github.com/cypress-io/cypress/commit/f8a71e75ae8208dc628d342cb1054c12f98338e9))
-* typo in the final message (run vs run-ct) ([294db04](https://github.com/cypress-io/cypress/commit/294db04f042dba86b69bb15d847c80a2c4202e80))
-* vueCli and webpack key vue@2 fix when guessing ([89f1bb9](https://github.com/cypress-io/cypress/commit/89f1bb9bc6bd987fbf6679a9d955c3587e69aa61))
-
-# [create-cypress-tests-v1.1.0](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v1.0.1...create-cypress-tests-v1.1.0) (2021-04-05)
-
-
-### Bug Fixes
-
-* **component-testing:** Fix webpack-dev-server deps validation crash ([#15708](https://github.com/cypress-io/cypress/issues/15708)) ([254eb47](https://github.com/cypress-io/cypress/commit/254eb47d91c75a9f56162e7493ab83e5be169935))
-
-
-### Features
-
-* support ct/e2e specific overrides in cypress.json ([#15526](https://github.com/cypress-io/cypress/issues/15526)) ([43c8ae2](https://github.com/cypress-io/cypress/commit/43c8ae2a7c20ba70a0bb0b45b8f6a086e2782f29))
-
-# [create-cypress-tests-v1.0.1](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v1.0.0...create-cypress-tests-v1.0.1) (2021-03-16)
-
-
-### Bug Fixes
-
-* add missing script for building wizard ([#15502](https://github.com/cypress-io/cypress/issues/15502)) ([393a8ca](https://github.com/cypress-io/cypress/commit/393a8ca9cac905e0f6d8623bff889b041dd076b6))
-
-# create-cypress-tests-v1.0.0 (2021-03-15)
-
-
-### Bug Fixes
-
-* **runner-ct:** open link in external browser ([#15420](https://github.com/cypress-io/cypress/issues/15420)) ([d291157](https://github.com/cypress-io/cypress/commit/d291157f07ffebe961527fdd85c7ec51056801e7))
-
-
-### Features
-
-* **@cypress/react:** Make correct plugins for different adapters/bundlers ([#15337](https://github.com/cypress-io/cypress/issues/15337)) ([fc30118](https://github.com/cypress-io/cypress/commit/fc301182523f0a645bfb17ea3b541644b9732dd0)), closes [#9116](https://github.com/cypress-io/cypress/issues/9116)
-* create-cypress-tests installation wizard ([#9563](https://github.com/cypress-io/cypress/issues/9563)) ([c405ee8](https://github.com/cypress-io/cypress/commit/c405ee89ef5321df6151fdeec1e917ac952c0d38)), closes [#9116](https://github.com/cypress-io/cypress/issues/9116)
-* create-cypress-tests wizard ([#8857](https://github.com/cypress-io/cypress/issues/8857)) ([21ee591](https://github.com/cypress-io/cypress/commit/21ee591d1e9c4083a0c67f2062ced92708c0cedd))
diff --git a/npm/create-cypress-tests/README.md b/npm/create-cypress-tests/README.md
deleted file mode 100644
index 528987627d36..000000000000
--- a/npm/create-cypress-tests/README.md
+++ /dev/null
@@ -1,56 +0,0 @@
-# Create Cypress Tests
-
-Installs and injects all the required configuration to run cypress tests.
-
-## Quick overview
-
-```
-cd my-app
-npx create-cypress-tests
-npx cypress open
-```
-
-![demo](./demo.gif)
-
-## Package manager
-
-This wizard will automatically determine which package do you use. If `yarn` available as global dependency it will use yarn to install dependencies and create lock file.
-
-If you need to use `npm` over `yarn` you can do the following
-
-```
-npx create-cypress-tests --use-npm
-```
-
-By the way you can use yarn to run the installation wizard 😉
-
-```
-yarn create cypress-tests
-```
-
-## Typescript
-
-This package will also automatically determine if typescript if available in this project and inject the required typescript configuration for cypress. If you are starting a new project and want to create typescript configuration, please do the following:
-
-```
-npm init
-npm install typescript
-npx create-cypress-tests
-```
-
-## Configuration
-
-Here is a list of available configuration options:
-
-`--use-npm` – use npm if yarn available
-`--ignore-typescript` – will not create typescript configuration if available
-`--ignore-examples` – will create a 1 template spec file (`cypress/integration/spec.js`) to start with
-`--component-tests` – will not ask should setup component testing or not
-
-## License
-
-The project is licensed under the terms of [MIT license](../../LICENSE)
-
-## Changelog
-
-[Changelog](./CHANGELOG.md)
diff --git a/npm/create-cypress-tests/__snapshots__/babel.test.ts.js b/npm/create-cypress-tests/__snapshots__/babel.test.ts.js
deleted file mode 100644
index 182ba10a2fb4..000000000000
--- a/npm/create-cypress-tests/__snapshots__/babel.test.ts.js
+++ /dev/null
@@ -1,13 +0,0 @@
-exports['babel installation template correctly generates plugins config 1'] = `
-const injectDevServer = require('@cypress/react/plugins/babel');
-
-const something = require("something");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- injectDevServer(on, config);
- }
-
- return config; // IMPORTANT to return a config
-};
-`
diff --git a/npm/create-cypress-tests/__snapshots__/init-component-testing.test.ts.js b/npm/create-cypress-tests/__snapshots__/init-component-testing.test.ts.js
deleted file mode 100644
index f1ff8aa8b366..000000000000
--- a/npm/create-cypress-tests/__snapshots__/init-component-testing.test.ts.js
+++ /dev/null
@@ -1,43 +0,0 @@
-exports['injects guessed next.js template cypress.config.ts'] = `
-export default {
- specPattern: "src/**/*.spec.{js,ts,jsx,tsx}"
-};
-
-`
-
-exports['injects guessed next.js template plugins/index.js'] = `
-const injectDevServer = require("@cypress/react/plugins/next");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- injectDevServer(on, config);
- }
-
- return config; // IMPORTANT to return a config
-};
-
-`
-
-exports['Injected overridden webpack template cypress.config.ts'] = `
-export default {
- specPattern: "cypress/component/**/*.spec.{js,ts,jsx,tsx}"
-};
-
-`
-
-exports['Injected overridden webpack template plugins/index.js'] = `
-const injectDevServer = require("@cypress/react/plugins/react-scripts");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- injectDevServer(on, config);
- }
-
- return config; // IMPORTANT to return a config
-};
-
-`
-
-exports['Injected overridden webpack template support/component.js'] = `
-import "./commands.js";
-`
diff --git a/npm/create-cypress-tests/__snapshots__/next.test.ts.js b/npm/create-cypress-tests/__snapshots__/next.test.ts.js
deleted file mode 100644
index 5d8602de1bbd..000000000000
--- a/npm/create-cypress-tests/__snapshots__/next.test.ts.js
+++ /dev/null
@@ -1,13 +0,0 @@
-exports['next.js install template correctly generates plugins config 1'] = `
-const injectDevServer = require('@cypress/react/plugins/next');
-
-const something = require("something");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- injectDevServer(on, config);
- }
-
- return config; // IMPORTANT to return a config
-};
-`
diff --git a/npm/create-cypress-tests/__snapshots__/react-scripts.test.ts.js b/npm/create-cypress-tests/__snapshots__/react-scripts.test.ts.js
deleted file mode 100644
index b960b4be6f6a..000000000000
--- a/npm/create-cypress-tests/__snapshots__/react-scripts.test.ts.js
+++ /dev/null
@@ -1,13 +0,0 @@
-exports['create-react-app install template correctly generates plugins config 1'] = `
-const injectDevServer = require('@cypress/react/plugins/react-scripts');
-
-const something = require("something");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- injectDevServer(on, config);
- }
-
- return config; // IMPORTANT to return a config
-};
-`
diff --git a/npm/create-cypress-tests/__snapshots__/reactWebpackFile.test.ts.js b/npm/create-cypress-tests/__snapshots__/reactWebpackFile.test.ts.js
deleted file mode 100644
index 5e36dd80347c..000000000000
--- a/npm/create-cypress-tests/__snapshots__/reactWebpackFile.test.ts.js
+++ /dev/null
@@ -1,32 +0,0 @@
-exports['webpack-file install template correctly generates plugins config when webpack config path is missing 1'] = `
-const injectDevServer = require("@cypress/react/plugins/load-webpack");
-
-const something = require("something");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- injectDevServer(on, config, {
- // TODO replace with valid webpack config path
- webpackFilename: './webpack.config.js'
- });
- }
-
- return config; // IMPORTANT to return a config
-};
-`
-
-exports['webpack-file install template correctly generates plugins config when webpack config path is provided 1'] = `
-const injectDevServer = require("@cypress/react/plugins/load-webpack");
-
-const something = require("something");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- injectDevServer(on, config, {
- webpackFilename: 'config/webpack.config.js'
- });
- }
-
- return config; // IMPORTANT to return a config
-};
-`
diff --git a/npm/create-cypress-tests/__snapshots__/vite.test.ts.js b/npm/create-cypress-tests/__snapshots__/vite.test.ts.js
deleted file mode 100644
index 5fc7bc31a4fb..000000000000
--- a/npm/create-cypress-tests/__snapshots__/vite.test.ts.js
+++ /dev/null
@@ -1,17 +0,0 @@
-exports['vue: vite template correctly generates plugins config 1'] = `
-const {
- startDevServer
-} = require("@cypress/vite-dev-server");
-
-const something = require("something");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- on("dev-server:start", async options => startDevServer({
- options
- }));
- }
-
- return config; // IMPORTANT to return a config
-};
-`
diff --git a/npm/create-cypress-tests/__snapshots__/vueCli.test.ts.js b/npm/create-cypress-tests/__snapshots__/vueCli.test.ts.js
deleted file mode 100644
index fa70c0ef2db7..000000000000
--- a/npm/create-cypress-tests/__snapshots__/vueCli.test.ts.js
+++ /dev/null
@@ -1,20 +0,0 @@
-exports['vue webpack-file install template correctly generates plugins for vue-cli-service 1'] = `
-const {
- startDevServer
-} = require("@cypress/webpack-dev-server");
-
-const webpackConfig = require("@vue/cli-service/webpack.config.js");
-
-const something = require("something");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- on('dev-server:start', options => startDevServer({
- options,
- webpackConfig
- }));
- }
-
- return config; // IMPORTANT to return a config
-};
-`
diff --git a/npm/create-cypress-tests/__snapshots__/vueWebpackFile.test.ts.js b/npm/create-cypress-tests/__snapshots__/vueWebpackFile.test.ts.js
deleted file mode 100644
index b686b719276e..000000000000
--- a/npm/create-cypress-tests/__snapshots__/vueWebpackFile.test.ts.js
+++ /dev/null
@@ -1,42 +0,0 @@
-exports['vue webpack-file install template correctly generates plugins config when webpack config path is missing 1'] = `
-const {
- startDevServer
-} = require("@cypress/webpack-dev-server");
-
-const webpackConfig = require("./webpack.config.js"); // TODO replace with valid webpack config path
-
-
-const something = require("something");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- on('dev-server:start', options => startDevServer({
- options,
- webpackConfig
- }));
- }
-
- return config; // IMPORTANT to return a config
-};
-`
-
-exports['vue webpack-file install template correctly generates plugins config when webpack config path is provided 1'] = `
-const {
- startDevServer
-} = require("@cypress/webpack-dev-server");
-
-const webpackConfig = require("build/webpack.config.js");
-
-const something = require("something");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- on('dev-server:start', options => startDevServer({
- options,
- webpackConfig
- }));
- }
-
- return config; // IMPORTANT to return a config
-};
-`
diff --git a/npm/create-cypress-tests/__snapshots__/webpackOptions.test.ts.js b/npm/create-cypress-tests/__snapshots__/webpackOptions.test.ts.js
deleted file mode 100644
index f384e4b912a1..000000000000
--- a/npm/create-cypress-tests/__snapshots__/webpackOptions.test.ts.js
+++ /dev/null
@@ -1,40 +0,0 @@
-exports['webpack-options template correctly generates plugins config 1'] = `
-const path = require("path");
-
-const {
- startDevServer
-} = require("@cypress/webpack-dev-Server");
-
-const something = require("something");
-
-module.exports = (on, config) => {
- if (config.testingType === "component") {
- /** @type import("webpack").Configuration */
- const webpackConfig = {
- resolve: {
- extensions: ['.js', '.ts', '.jsx', '.tsx']
- },
- mode: 'development',
- devtool: false,
- output: {
- publicPath: '/',
- chunkFilename: '[name].bundle.js'
- },
- // TODO: update with valid configuration for your components
- module: {
- rules: [{
- test: /\\.(js|jsx|mjs|ts|tsx)$/,
- loader: 'babel-loader',
- options: {
- cacheDirectory: path.resolve(__dirname, '.babel-cache')
- }
- }]
- }
- };
- on('dev-server:start', options => startDevServer({
- options,
- webpackConfig
- }));
- }
-};
-`
diff --git a/npm/create-cypress-tests/cypress.config.js b/npm/create-cypress-tests/cypress.config.js
deleted file mode 100644
index 4ba52ba2c8df..000000000000
--- a/npm/create-cypress-tests/cypress.config.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = {}
diff --git a/npm/create-cypress-tests/demo.gif b/npm/create-cypress-tests/demo.gif
deleted file mode 100644
index 344fc47d3faa..000000000000
Binary files a/npm/create-cypress-tests/demo.gif and /dev/null differ
diff --git a/npm/create-cypress-tests/package.json b/npm/create-cypress-tests/package.json
deleted file mode 100644
index 695a20a2695a..000000000000
--- a/npm/create-cypress-tests/package.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- "name": "create-cypress-tests",
- "version": "0.0.0-development",
- "description": "Cypress smart installation wizard",
- "main": "dist/src/main.js",
- "scripts": {
- "build": "yarn prepare-example && tsc -p ./tsconfig.json && node scripts/example copy-to ./dist/initial-template && yarn prepare-copy-templates",
- "prepare-example": "node scripts/example copy-to ./initial-template",
- "prepare-copy-templates": "node scripts/copy-templates copy-to ./dist/src",
- "test": "cross-env TS_NODE_PROJECT=./tsconfig.test.json mocha --config .mocharc.json './src/**/*.test.ts'",
- "test:watch": "yarn test -w",
- "lint": "eslint --ext .js,.ts,.json, ."
- },
- "dependencies": {
- "@babel/core": "^7.5.4",
- "@babel/plugin-transform-typescript": "^7.2.0",
- "@babel/template": "^7.5.4",
- "@babel/types": "^7.5.0",
- "bluebird": "3.7.2",
- "chalk": "4.1.0",
- "cli-highlight": "2.1.10",
- "commander": "6.2.1",
- "find-up": "5.0.0",
- "fs-extra": "^9.1.0",
- "glob": "^7.1.6",
- "inquirer": "8.2.4",
- "ora": "^5.1.0",
- "recast": "0.20.4",
- "semver": "7.3.7"
- },
- "devDependencies": {
- "@types/babel__core": "^7.1.2",
- "@types/inquirer": "8.2.4",
- "@types/mock-fs": "4.10.0",
- "@types/node": "18.17.5",
- "@types/ora": "^3.2.0",
- "@types/semver": "7.5.0",
- "copy": "0.3.2",
- "mocha": "7.1.1",
- "mock-fs": "5.2.0",
- "snap-shot-it": "7.9.3",
- "typescript": "^4.7.4"
- },
- "files": [
- "dist",
- "bin"
- ],
- "bin": {
- "create-cypress-tests": "dist/src/index.js"
- },
- "license": "MIT",
- "repository": "https://github.com/cypress-io/cypress.git",
- "homepage": "https://github.com/cypress-io/cypress/blob/develop/npm/create-cypress-tests/#readme",
- "nx": {
- "implicitDependencies": [
- "@packages/example"
- ]
- }
-}
diff --git a/npm/create-cypress-tests/scripts/copy-templates.js b/npm/create-cypress-tests/scripts/copy-templates.js
deleted file mode 100644
index 583538450087..000000000000
--- a/npm/create-cypress-tests/scripts/copy-templates.js
+++ /dev/null
@@ -1,40 +0,0 @@
-const globby = require('globby')
-const fs = require('fs-extra')
-const chalk = require('chalk')
-const path = require('path')
-const program = require('commander')
-
-program
-.command('copy-to [destination]')
-.description('copy ./src/**/*.template.js into destination')
-.action(async (destination) => {
- const srcPath = path.resolve(__dirname, '..', 'src')
- const destinationPath = path.resolve(process.cwd(), destination)
-
- const templates = await globby('**/*.template.js', {
- cwd: srcPath,
- onlyFiles: true,
- unique: true,
- })
-
- const srcOutput = './src/'
- let destinationOutput = destination.replace('/\\/g', '/')
-
- if (!destinationOutput.endsWith('/')) {
- destinationOutput += '/'
- }
-
- const relOutput = (template, forSource) => {
- return `${forSource ? srcOutput : destinationOutput}${template}`
- }
-
- const result = await Promise.all(templates.map(async (template) => {
- await fs.copy(path.join(srcPath, template), path.join(destinationPath, template))
-
- return () => console.log(`✅ ${relOutput(template, true)} successfully copied to ${chalk.cyan(relOutput(template, false))}`)
- }))
-
- result.forEach((r) => r())
-})
-
-program.parse(process.argv)
diff --git a/npm/create-cypress-tests/scripts/example.js b/npm/create-cypress-tests/scripts/example.js
deleted file mode 100644
index 0925901447ab..000000000000
--- a/npm/create-cypress-tests/scripts/example.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const fs = require('fs-extra')
-const chalk = require('chalk')
-const path = require('path')
-const program = require('commander')
-
-program
-.command('copy-to [destination]')
-.description('copy cypress/packages/example into destination')
-.action(async (destination) => {
- const exampleFolder = path.resolve(__dirname, '..', '..', '..', 'packages', 'example', 'cypress')
- const destinationPath = path.resolve(process.cwd(), destination)
-
- await fs.remove(destinationPath)
- await fs.copy(exampleFolder, destinationPath, { recursive: true })
-
- console.log(`✅ E2E Examples were successfully created at ${chalk.cyan(destination)}`)
-
- await fs.copy(path.join(__dirname, 'examples', 'cypress'), path.join(destination))
-
- console.log(`✅ Cypress Setup was successfully created at ${chalk.cyan(destination)}`)
-
- await fs.copy(path.join(__dirname, 'examples', 'tsconfig.json'), path.join(destination, 'tsconfig.json'))
-
- console.log(`✅ tsconfig.json was created for ${chalk.cyan(destination)}`)
-})
-
-program.parse(process.argv)
diff --git a/npm/create-cypress-tests/scripts/examples/cypress/fixtures/example.json b/npm/create-cypress-tests/scripts/examples/cypress/fixtures/example.json
deleted file mode 100644
index 02e4254378e9..000000000000
--- a/npm/create-cypress-tests/scripts/examples/cypress/fixtures/example.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "name": "Using fixtures to represent data",
- "email": "hello@cypress.io",
- "body": "Fixtures are a great way to mock data for responses to routes"
-}
diff --git a/npm/create-cypress-tests/scripts/examples/cypress/support/commands.js b/npm/create-cypress-tests/scripts/examples/cypress/support/commands.js
deleted file mode 100644
index 119ab03f7cda..000000000000
--- a/npm/create-cypress-tests/scripts/examples/cypress/support/commands.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// ***********************************************
-// This example commands.js shows you how to
-// create various custom commands and overwrite
-// existing commands.
-//
-// For more comprehensive examples of custom
-// commands please read more here:
-// https://on.cypress.io/custom-commands
-// ***********************************************
-//
-//
-// -- This is a parent command --
-// Cypress.Commands.add('login', (email, password) => { ... })
-//
-//
-// -- This is a child command --
-// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
-//
-//
-// -- This is a dual command --
-// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
-//
-//
-// -- This will overwrite an existing command --
-// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
diff --git a/npm/create-cypress-tests/scripts/examples/cypress/support/component.js b/npm/create-cypress-tests/scripts/examples/cypress/support/component.js
deleted file mode 100644
index 5e450a7b1a4a..000000000000
--- a/npm/create-cypress-tests/scripts/examples/cypress/support/component.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// ***********************************************************
-// This example support/component.js is processed and
-// loaded automatically before your test files.
-//
-// This is a great place to put global configuration and
-// behavior that modifies Cypress.
-//
-// You can change the location of this file or turn off
-// automatically serving support files with the
-// 'supportFile' configuration option.
-//
-// You can read more here:
-// https://on.cypress.io/configuration
-// ***********************************************************
-
-// Import commands.js using ES2015 syntax:
-import './commands'
-
-// Alternatively you can use CommonJS syntax:
-// require('./commands')
diff --git a/npm/create-cypress-tests/scripts/examples/cypress/support/e2e.js b/npm/create-cypress-tests/scripts/examples/cypress/support/e2e.js
deleted file mode 100644
index d1dd1353e812..000000000000
--- a/npm/create-cypress-tests/scripts/examples/cypress/support/e2e.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// ***********************************************************
-// This example support/e2e.js is processed and
-// loaded automatically before your test files.
-//
-// This is a great place to put global configuration and
-// behavior that modifies Cypress.
-//
-// You can change the location of this file or turn off
-// automatically serving support files with the
-// 'supportFile' configuration option.
-//
-// You can read more here:
-// https://on.cypress.io/configuration
-// ***********************************************************
-
-// Import commands.js using ES2015 syntax:
-import './commands'
-
-// Alternatively you can use CommonJS syntax:
-// require('./commands')
diff --git a/npm/create-cypress-tests/scripts/examples/tsconfig.json b/npm/create-cypress-tests/scripts/examples/tsconfig.json
deleted file mode 100644
index 08c029d44419..000000000000
--- a/npm/create-cypress-tests/scripts/examples/tsconfig.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "compilerOptions": {
- "target": "es5",
- "lib": [
- "es5",
- "dom"
- ],
- "types": [
- "cypress"
- ]
- },
- "include": [
- "**/*.ts*"
- ]
-}
\ No newline at end of file
diff --git a/npm/create-cypress-tests/src/component-testing/babel/babelTransform.test.ts b/npm/create-cypress-tests/src/component-testing/babel/babelTransform.test.ts
deleted file mode 100644
index 5bc9e1ed33dc..000000000000
--- a/npm/create-cypress-tests/src/component-testing/babel/babelTransform.test.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-///
-
-import * as babel from '@babel/core'
-import { expect } from 'chai'
-import { createTransformPluginsFileBabelPlugin } from './babelTransform'
-
-describe('babel transform utils', () => {
- context('Plugins config babel plugin', () => {
- it('injects code into the plugins file based on ast', () => {
- const plugin = createTransformPluginsFileBabelPlugin({
- RequireAst: babel.template.ast('require("something")'),
- IfComponentTestingPluginsAst: babel.template.ast('yey()'),
- })
-
- const output = babel.transformSync([
- 'module.exports = (on, config) => {',
- 'on("do")',
- '}',
- ].join('\n'), {
- plugins: [plugin],
- })?.code
-
- expect(output).to.equal([
- 'require("something");',
- '',
- 'module.exports = (on, config) => {',
- ' on("do");',
- '',
- ' if (config.testingType === "component") {',
- ' yey();',
- ' }',
- '};',
- ].join(`\n`))
- })
- })
-})
diff --git a/npm/create-cypress-tests/src/component-testing/babel/babelTransform.ts b/npm/create-cypress-tests/src/component-testing/babel/babelTransform.ts
deleted file mode 100644
index 0c06f49ca80c..000000000000
--- a/npm/create-cypress-tests/src/component-testing/babel/babelTransform.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-import path from 'path'
-import * as fs from 'fs-extra'
-import * as babel from '@babel/core'
-import * as babelTypes from '@babel/types'
-import { prettifyCode } from '../../utils'
-
-type AST = ReturnType
-
-export type PluginsConfigAst = {
- RequireAst: AST
- IfComponentTestingPluginsAst: AST
- requiresReturnConfig?: true
-}
-
-const sharedBabelOptions = {
- // disable user config
- configFile: false,
- babelrc: false,
- presets: [],
- root: process.env.BABEL_TEST_ROOT, // for testing
-}
-
-async function transformFileViaPlugin (filePath: string, babelPlugin: babel.PluginObj) {
- try {
- const initialCode = await fs.readFile(filePath, { encoding: 'utf-8' })
-
- const updatedResult = await babel.transformAsync(initialCode, {
- filename: path.basename(filePath),
- filenameRelative: path.relative(process.cwd(), filePath),
- plugins: [babelPlugin],
- ...sharedBabelOptions,
- })
-
- if (!updatedResult) {
- return false
- }
-
- let finalCode = updatedResult.code
-
- if (finalCode === initialCode) {
- return false
- }
-
- finalCode = await prettifyCode(finalCode)
-
- await fs.writeFile(filePath, finalCode)
-
- return true
- } catch (e) {
- return false
- }
-}
-
-const returnConfigAst = babel.template.ast('return config; // IMPORTANT to return a config', { preserveComments: true })
-
-export function createTransformPluginsFileBabelPlugin (ast: PluginsConfigAst): babel.PluginObj {
- return {
- visitor: {
- Program: (path) => {
- path.unshiftContainer('body', ast.RequireAst)
- },
- Function: (path) => {
- if (!babelTypes.isAssignmentExpression(path.parent)) {
- return
- }
-
- const assignment = path.parent.left
-
- const isModuleExports =
- babelTypes.isMemberExpression(assignment)
- && babelTypes.isIdentifier(assignment.object)
- && assignment.object.name === 'module'
- && babelTypes.isIdentifier(assignment.property)
- && assignment.property.name === 'exports'
-
- if (isModuleExports && babelTypes.isFunction(path.parent.right)) {
- const paramsLength = path.parent.right.params.length
-
- if (paramsLength === 0) {
- path.parent.right.params.push(babelTypes.identifier('on'))
- path.parent.right.params.push(babelTypes.identifier('config'))
- }
-
- if (paramsLength === 1) {
- path.parent.right.params.push(babelTypes.identifier('config'))
- }
-
- const statementToInject = Array.isArray(ast.IfComponentTestingPluginsAst)
- ? ast.IfComponentTestingPluginsAst
- : [ast.IfComponentTestingPluginsAst]
-
- const ifComponentMode = babelTypes.ifStatement(
- babelTypes.binaryExpression(
- '===',
- babelTypes.identifier('config.testingType'),
- babelTypes.stringLiteral('component'),
- ),
- babelTypes.blockStatement(statementToInject as babelTypes.Statement[] | babelTypes.Statement[]),
- )
-
- path.get('body').pushContainer('body' as never, ifComponentMode as never)
-
- if (ast.requiresReturnConfig) {
- path.get('body').pushContainer('body' as never, returnConfigAst as never)
- }
- }
- },
- },
- }
-}
-
-export async function injectPluginsCode (pluginsFilePath: string, ast: PluginsConfigAst) {
- return transformFileViaPlugin(pluginsFilePath, createTransformPluginsFileBabelPlugin(ast))
-}
-
-export async function getPluginsSourceExample (ast: PluginsConfigAst) {
- const exampleCode = [
- 'module.exports = (on, config) => {',
- '',
- '}',
- ].join('\n')
-
- try {
- const babelResult = await babel.transformAsync(exampleCode, {
- filename: 'nothing.js',
- plugins: [createTransformPluginsFileBabelPlugin(ast)],
- ...sharedBabelOptions,
- })
-
- if (!babelResult?.code) {
- throw new Error()
- }
-
- return babelResult.code
- } catch (e) {
- throw new Error('Can not generate code example for plugins file because of unhandled error. Please update the plugins file manually.')
- }
-}
diff --git a/npm/create-cypress-tests/src/component-testing/config-file-updater/configFileUpdater.test.ts b/npm/create-cypress-tests/src/component-testing/config-file-updater/configFileUpdater.test.ts
deleted file mode 100644
index 8a2dee76b5ff..000000000000
--- a/npm/create-cypress-tests/src/component-testing/config-file-updater/configFileUpdater.test.ts
+++ /dev/null
@@ -1,405 +0,0 @@
-///
-
-import { expect } from 'chai'
-import { insertValueInJSString } from './configFileUpdater'
-
-// Test util - if needed outside the tests we can move it to utils
-const stripIndent = (strings: any, ...args: any) => {
- const parts = []
-
- for (let i = 0; i < strings.length; i++) {
- parts.push(strings[i])
-
- if (i < strings.length - 1) {
- parts.push(`<<${i}>>`)
- }
- }
-
- const lines = parts.join('').split('\n')
- const firstLine = lines[0].length === 0 ? lines[1] : lines[0]
- let indentSize = 0
-
- for (let i = 0; i < firstLine.length; i++) {
- if (firstLine[i] === ' ') {
- indentSize++
- continue
- }
-
- break
- }
-
- const strippedLines = lines.map((line) => line.substring(indentSize))
-
- let result = strippedLines.join('\n').trimLeft()
-
- args.forEach((arg: any, i: any) => {
- result = result.replace(`<<${i}>>`, `${arg}`)
- })
-
- return result
-}
-
-describe('lib/util/config-file-updater', () => {
- context('with js files', () => {
- describe('#insertValueInJSString', () => {
- describe('es6 vs es5', () => {
- it('finds the object literal and adds the values to it es6', async () => {
- const src = stripIndent`\
- export default {
- foo: 42,
- }
- `
-
- const expectedOutput = stripIndent`\
- export default {
- projectId: "id1234",
- viewportWidth: 400,
- foo: 42,
- }
- `
-
- const output = await insertValueInJSString(src, { projectId: 'id1234', viewportWidth: 400 })
-
- expect(output).to.equal(expectedOutput)
- })
-
- it('finds the object literal and adds the values to it es5', async () => {
- const src = stripIndent`\
- module.exports = {
- foo: 42,
- }
- `
-
- const expectedOutput = stripIndent`\
- module.exports = {
- projectId: "id1234",
- viewportWidth: 400,
- foo: 42,
- }
- `
-
- const output = await insertValueInJSString(src, { projectId: 'id1234', viewportWidth: 400 })
-
- expect(output).to.equal(expectedOutput)
- })
-
- it('works with and without the quotes around keys', async () => {
- const src = stripIndent`\
- export default {
- "foo": 42,
- }
- `
-
- const expectedOutput = stripIndent`\
- export default {
- projectId: "id1234",
- viewportWidth: 400,
- "foo": 42,
- }
- `
-
- const output = await insertValueInJSString(src, { projectId: 'id1234', viewportWidth: 400 })
-
- expect(output).to.equal(expectedOutput)
- })
- })
-
- describe('defineConfig', () => {
- it('skips defineConfig and add to the object inside', async () => {
- const src = stripIndent`\
- import { defineConfig } from "cypress"
- export default defineConfig({
- foo: 42,
- })
- `
-
- const expectedOutput = stripIndent`\
- import { defineConfig } from "cypress"
- export default defineConfig({
- projectId: "id1234",
- viewportWidth: 400,
- foo: 42,
- })
- `
-
- const output = await insertValueInJSString(src, { projectId: 'id1234', viewportWidth: 400 })
-
- expect(output).to.equal(expectedOutput)
- })
-
- it('skips defineConfig even if it renamed in an import (es6)', async () => {
- const src = stripIndent`\
- import { defineConfig as cy_defineConfig } from "cypress"
- export default cy_defineConfig({
- foo: 42,
- })
- `
-
- const expectedOutput = stripIndent`\
- import { defineConfig as cy_defineConfig } from "cypress"
- export default cy_defineConfig({
- projectId: "id1234",
- viewportWidth: 400,
- foo: 42,
- })
- `
-
- const output = await insertValueInJSString(src, { projectId: 'id1234', viewportWidth: 400 })
-
- expect(output).to.equal(expectedOutput)
- })
-
- it('skips defineConfig even if it renamed in a require (es5)', async () => {
- const src = stripIndent`\
- const { defineConfig: cy_defineConfig } = require("cypress")
- module.exports = cy_defineConfig({
- foo: 42,
- })
- `
-
- const expectedOutput = stripIndent`\
- const { defineConfig: cy_defineConfig } = require("cypress")
- module.exports = cy_defineConfig({
- projectId: "id1234",
- viewportWidth: 400,
- foo: 42,
- })
- `
-
- const output = await insertValueInJSString(src, { projectId: 'id1234', viewportWidth: 400 })
-
- expect(output).to.equal(expectedOutput)
- })
- })
-
- describe('updates', () => {
- it('updates a value if the same value is found in resolved config', async () => {
- const src = stripIndent`\
- export default {
- foo: 42,
- }
- `
- const expectedOutput = stripIndent`\
- export default {
- foo: 1000,
- }
- `
-
- const output = await insertValueInJSString(src, { foo: 1000 })
-
- expect(output).to.equal(expectedOutput)
- })
-
- it('accepts inline comments', async () => {
- const src = stripIndent`\
- export default {
- foo: 12, // will do this later
- viewportWidth: 800,
- }
- `
- const expectedOutput = stripIndent`\
- export default {
- foo: 1000, // will do this later
- viewportWidth: 800,
- }
- `
-
- const output = await insertValueInJSString(src, { foo: 1000 })
-
- expect(output).to.equal(expectedOutput)
- })
-
- it('updates a value even when this value is explicitely undefined', async () => {
- const src = stripIndent`\
- export default {
- foo: undefined, // will do this later
- viewportWidth: 800,
- }
- `
- const expectedOutput = stripIndent`\
- export default {
- foo: 1000, // will do this later
- viewportWidth: 800,
- }
- `
-
- const output = await insertValueInJSString(src, { foo: 1000 })
-
- expect(output).to.equal(expectedOutput)
- })
-
- it('updates values and inserts config', async () => {
- const src = stripIndent`\
- export default {
- foo: 42,
- bar: 84,
- component: {
- devServer() {
- return null
- }
- }
- }
- `
-
- const expectedOutput = stripIndent`\
- export default {
- projectId: "id1234",
- foo: 1000,
- bar: 3000,
- component: {
- devServer() {
- return null
- }
- }
- }
- `
-
- const output = await insertValueInJSString(src, { foo: 1000, bar: 3000, projectId: 'id1234' })
-
- expect(output).to.equal(expectedOutput)
- })
- })
-
- describe('subkeys', () => {
- it('inserts nested values', async () => {
- const src = stripIndent`\
- module.exports = {
- foo: 42
- }
- `
-
- const output = await insertValueInJSString(src, { component: { specPattern: 'src/**/*.spec.cy.js' } })
-
- const expectedOutput = stripIndent`\
- module.exports = {
- component: {
- specPattern: "src/**/*.spec.cy.js",
- },
- foo: 42
- }
- `
-
- expect(output).to.equal(expectedOutput)
- })
-
- it('inserts nested values into existing keys', async () => {
- const src = stripIndent`\
- module.exports = {
- component: {
- viewportWidth: 800
- },
- foo: 42
- }
- `
-
- const output = await insertValueInJSString(src, { component: { specPattern: 'src/**/*.spec.cy.js' } })
-
- const expectedOutput = stripIndent`\
- module.exports = {
- component: {
- specPattern: "src/**/*.spec.cy.js",
- viewportWidth: 800
- },
- foo: 42
- }
- `
-
- expect(output).to.equal(expectedOutput)
- })
-
- it('updates nested values', async () => {
- const src = stripIndent`\
- module.exports = {
- foo: 42,
- component: {
- specPattern: 'components/**/*.spec.cy.js',
- foo: 82
- }
- }`
-
- const output = await insertValueInJSString(src, { component: { specPattern: 'src/**/*.spec.cy.js' } })
-
- const expectedOutput = stripIndent`\
- module.exports = {
- foo: 42,
- component: {
- specPattern: "src/**/*.spec.cy.js",
- foo: 82
- }
- }`
-
- expect(output).to.equal(expectedOutput)
- })
- })
-
- describe('failures', () => {
- it('fails if not an object literal', () => {
- const src = [
- 'const foo = {}',
- 'export default foo',
- ].join('\n')
-
- return insertValueInJSString(src, { bar: 10 })
- .then(() => {
- throw Error('this should not succeed')
- })
- .catch((err) => {
- expect(err.message).to.equal('Cypress was unable to add/update values in your configuration file.')
- })
- })
-
- it('fails if one of the values to update is not a literal', () => {
- const src = [
- 'const bar = 12',
- 'export default {',
- ' foo: bar',
- '}',
- ].join('\n')
-
- return insertValueInJSString(src, { foo: 10 })
- .then(() => {
- throw Error('this should not succeed')
- })
- .catch((err) => {
- expect(err.message).to.equal('Cypress was unable to add/update values in your configuration file.')
- })
- })
-
- it('fails with inlined values', () => {
- const src = stripIndent`\
- const foo = 12
- export default {
- foo
- }
- `
-
- return insertValueInJSString(src, { foo: 10 })
- .then(() => {
- throw Error('this should not succeed')
- })
- .catch((err) => {
- expect(err.message).to.equal('Cypress was unable to add/update values in your configuration file.')
- })
- })
-
- it('fails if there is a spread', () => {
- const src = stripIndent`\
- const foo = { bar: 12 }
- export default {
- bar: 8,
- ...foo
- }
- `
-
- return insertValueInJSString(src, { bar: 10 })
- .then(() => {
- throw Error('this should not succeed')
- })
- .catch((err) => {
- expect(err.message).to.equal('Cypress was unable to add/update values in your configuration file.')
- })
- })
- })
- })
- })
-})
diff --git a/npm/create-cypress-tests/src/component-testing/config-file-updater/configFileUpdater.ts b/npm/create-cypress-tests/src/component-testing/config-file-updater/configFileUpdater.ts
deleted file mode 100644
index b2e587f9ee3c..000000000000
--- a/npm/create-cypress-tests/src/component-testing/config-file-updater/configFileUpdater.ts
+++ /dev/null
@@ -1,294 +0,0 @@
-import { parse } from '@babel/parser'
-import type { File } from '@babel/types'
-import type { NodePath } from 'ast-types/lib/node-path'
-import { visit } from 'recast'
-import type { namedTypes } from 'ast-types'
-import * as fs from 'fs-extra'
-import { prettifyCode } from '../../utils'
-
-export async function insertValuesInConfigFile (filePath: string, obj: Record = {}) {
- await insertValuesInJavaScript(filePath, obj)
-
- return true
-}
-
-export async function insertValuesInJavaScript (filePath: string, obj: Record) {
- const fileContents = await fs.readFile(filePath, { encoding: 'utf8' })
-
- let finalCode = await insertValueInJSString(fileContents, obj)
-
- const prettifiedCode = await prettifyCode(finalCode)
-
- if (prettifiedCode) {
- finalCode = prettifiedCode
- }
-
- await fs.writeFile(filePath, finalCode)
-}
-
-export async function insertValueInJSString (fileContents: string, obj: Record): Promise {
- const ast = parse(fileContents, { plugins: ['typescript'], sourceType: 'module' })
-
- let objectLiteralNode: namedTypes.ObjectExpression | undefined
-
- function handleExport (nodePath: NodePath | NodePath): void {
- if (nodePath.node.type === 'CallExpression'
- && nodePath.node.callee.type === 'Identifier') {
- const functionName = nodePath.node.callee.name
-
- if (isDefineConfigFunction(ast, functionName)) {
- return handleExport(nodePath.get('arguments', 0))
- }
- }
-
- if (nodePath.node.type === 'ObjectExpression' && !nodePath.node.properties.find((prop) => prop.type !== 'ObjectProperty')) {
- objectLiteralNode = nodePath.node
-
- return
- }
-
- throw new Error('Cypress was unable to add/update values in your configuration file.')
- }
-
- visit(ast, {
- visitAssignmentExpression (nodePath) {
- if (nodePath.node.left.type === 'MemberExpression') {
- if (nodePath.node.left.object.type === 'Identifier' && nodePath.node.left.object.name === 'module'
- && nodePath.node.left.property.type === 'Identifier' && nodePath.node.left.property.name === 'exports') {
- handleExport(nodePath.get('right'))
- }
- }
-
- return false
- },
- visitExportDefaultDeclaration (nodePath) {
- handleExport(nodePath.get('declaration'))
-
- return false
- },
- })
-
- const splicers: Splicer[] = []
-
- if (!objectLiteralNode) {
- // if the export is no object literal
- throw new Error('Cypress was unable to add/update values in your configuration file.')
- }
-
- setRootKeysSplicers(splicers, obj, objectLiteralNode!, ' ')
- setSubKeysSplicers(splicers, obj, objectLiteralNode!, ' ', ' ')
-
- // sort splicers to keep the order of the original file
- const sortedSplicers = splicers.sort((a, b) => a.start === b.start ? 0 : a.start > b.start ? 1 : -1)
-
- if (!sortedSplicers.length) return fileContents
-
- let nextStartingIndex = 0
- let resultCode = ''
-
- sortedSplicers.forEach((splicer) => {
- resultCode += fileContents.slice(nextStartingIndex, splicer.start) + splicer.replaceString
- nextStartingIndex = splicer.end
- })
-
- return resultCode + fileContents.slice(nextStartingIndex)
-}
-
-export function isDefineConfigFunction (ast: File, functionName: string): boolean {
- let value = false
-
- visit(ast, {
- visitVariableDeclarator (nodePath) {
- // if this is a require of cypress
- if (nodePath.node.init?.type === 'CallExpression'
- && nodePath.node.init.callee.type === 'Identifier'
- && nodePath.node.init.callee.name === 'require'
- && nodePath.node.init.arguments[0].type === 'StringLiteral'
- && nodePath.node.init.arguments[0].value === 'cypress') {
- if (nodePath.node.id?.type === 'ObjectPattern') {
- const defineConfigFunctionNode = nodePath.node.id.properties.find((prop) => {
- return prop.type === 'ObjectProperty'
- && prop.key.type === 'Identifier'
- && prop.key.name === 'defineConfig'
- })
-
- if (defineConfigFunctionNode) {
- value = (defineConfigFunctionNode as any).value?.name === functionName
- }
- }
- }
-
- return false
- },
- visitImportDeclaration (nodePath) {
- if (nodePath.node.source.type === 'StringLiteral'
- && nodePath.node.source.value === 'cypress') {
- const defineConfigFunctionNode = nodePath.node.specifiers?.find((specifier) => {
- return specifier.type === 'ImportSpecifier'
- && specifier.imported.type === 'Identifier'
- && specifier.imported.name === 'defineConfig'
- })
-
- if (defineConfigFunctionNode) {
- value = (defineConfigFunctionNode as any).local?.name === functionName
- }
- }
-
- return false
- },
- })
-
- return value
-}
-
-function setRootKeysSplicers (
- splicers: Splicer[],
- obj: Record,
- objectLiteralNode: namedTypes.ObjectExpression,
- lineStartSpacer: string,
-) {
- const objectLiteralStartIndex = (objectLiteralNode as any).start + 1
- // add values
- const objKeys = Object.keys(obj).filter((key) => ['boolean', 'number', 'string'].includes(typeof obj[key]))
-
- // update values
- const keysToUpdate = objKeys.filter((key) => {
- return objectLiteralNode.properties.find((prop) => {
- return prop.type === 'ObjectProperty'
- && prop.key.type === 'Identifier'
- && prop.key.name === key
- })
- })
-
- keysToUpdate.forEach(
- (key) => {
- const propertyToUpdate = propertyFromKey(objectLiteralNode, key)
-
- if (propertyToUpdate) {
- setSplicerToUpdateProperty(splicers, propertyToUpdate, obj[key], key, obj)
- }
- },
- )
-
- const keysToInsert = objKeys.filter((key) => !keysToUpdate.includes(key))
-
- if (keysToInsert.length) {
- const valuesInserted = `\n${lineStartSpacer}${ keysToInsert.map((key) => `${key}: ${JSON.stringify(obj[key])},`).join(`\n${lineStartSpacer}`)}`
-
- splicers.push({
- start: objectLiteralStartIndex,
- end: objectLiteralStartIndex,
- replaceString: valuesInserted,
- })
- }
-}
-
-function setSubKeysSplicers (
- splicers: Splicer[],
- obj: Record,
- objectLiteralNode: namedTypes.ObjectExpression,
- lineStartSpacer: string,
- parentLineStartSpacer: string,
-) {
- const objectLiteralStartIndex = (objectLiteralNode as any).start + 1
-
- const keysToUpdateWithObjects: string[] = []
-
- const objSubkeys = Object.keys(obj).filter((key) => typeof obj[key] === 'object').reduce((acc: Array<{parent: string, subkey: string}>, key) => {
- keysToUpdateWithObjects.push(key)
- Object.entries(obj[key]).forEach(([subkey, value]) => {
- if (['boolean', 'number', 'string'].includes(typeof value)) {
- acc.push({ parent: key, subkey })
- }
- })
-
- return acc
- }, [])
-
- // add values where the parent key needs to be created
- const subkeysToInsertWithoutKey = objSubkeys.filter(({ parent }) => {
- return !objectLiteralNode.properties.find((prop) => {
- return prop.type === 'ObjectProperty'
- && prop.key.type === 'Identifier'
- && prop.key.name === parent
- })
- })
- const keysToInsertForSubKeys: Record = {}
-
- subkeysToInsertWithoutKey.forEach((keyTuple) => {
- const subkeyList = keysToInsertForSubKeys[keyTuple.parent] || []
-
- subkeyList.push(keyTuple.subkey)
- keysToInsertForSubKeys[keyTuple.parent] = subkeyList
- })
-
- let subvaluesInserted = ''
-
- for (const key in keysToInsertForSubKeys) {
- subvaluesInserted += `\n${parentLineStartSpacer}${key}: {`
- keysToInsertForSubKeys[key].forEach((subkey) => {
- subvaluesInserted += `\n${parentLineStartSpacer}${lineStartSpacer}${subkey}: ${JSON.stringify(obj[key][subkey])},`
- })
-
- subvaluesInserted += `\n${parentLineStartSpacer}},`
- }
-
- if (subkeysToInsertWithoutKey.length) {
- splicers.push({
- start: objectLiteralStartIndex,
- end: objectLiteralStartIndex,
- replaceString: subvaluesInserted,
- })
- }
-
- // add/update values where parent key already exists
- keysToUpdateWithObjects.filter((parent) => {
- return objectLiteralNode.properties.find((prop) => {
- return prop.type === 'ObjectProperty'
- && prop.key.type === 'Identifier'
- && prop.key.name === parent
- })
- }).forEach((key) => {
- const propertyToUpdate = propertyFromKey(objectLiteralNode, key)
-
- if (propertyToUpdate?.value.type === 'ObjectExpression') {
- setRootKeysSplicers(splicers, obj[key], propertyToUpdate.value, parentLineStartSpacer + lineStartSpacer)
- }
- })
-}
-
-function setSplicerToUpdateProperty (splicers: Splicer[],
- propertyToUpdate: namedTypes.ObjectProperty,
- updatedValue: any,
- key: string,
- obj: Record) {
- if (propertyToUpdate && (isPrimitive(propertyToUpdate.value) || isUndefinedOrNull(propertyToUpdate.value))) {
- splicers.push({
- start: (propertyToUpdate.value as any).start,
- end: (propertyToUpdate.value as any).end,
- replaceString: JSON.stringify(updatedValue),
- })
- } else {
- throw new Error('Cypress was unable to add/update values in your configuration file.')
- }
-}
-
-function propertyFromKey (objectLiteralNode: namedTypes.ObjectExpression | undefined, key: string): namedTypes.ObjectProperty | undefined {
- return objectLiteralNode?.properties.find((prop) => {
- return prop.type === 'ObjectProperty' && prop.key.type === 'Identifier' && prop.key.name === key
- }) as namedTypes.ObjectProperty
-}
-
-function isPrimitive (value: NodePath['node']): value is namedTypes.NumericLiteral | namedTypes.StringLiteral | namedTypes.BooleanLiteral {
- return value.type === 'NumericLiteral' || value.type === 'StringLiteral' || value.type === 'BooleanLiteral'
-}
-
-function isUndefinedOrNull (value: NodePath['node']): value is namedTypes.Identifier {
- return value.type === 'Identifier' && ['undefined', 'null'].includes(value.name)
-}
-
-interface Splicer{
- start: number
- end: number
- replaceString: string
-}
diff --git a/npm/create-cypress-tests/src/component-testing/init-component-testing.test.ts b/npm/create-cypress-tests/src/component-testing/init-component-testing.test.ts
deleted file mode 100644
index 2db6b20baf13..000000000000
--- a/npm/create-cypress-tests/src/component-testing/init-component-testing.test.ts
+++ /dev/null
@@ -1,340 +0,0 @@
-import path from 'path'
-import fs from 'fs-extra'
-import snapshot from 'snap-shot-it'
-import { expect, use } from 'chai'
-import sinon, { SinonStub, SinonSpy } from 'sinon'
-import chalk from 'chalk'
-import mockFs from 'mock-fs'
-import { initComponentTesting } from './init-component-testing'
-import inquirer from 'inquirer'
-import sinonChai from 'sinon-chai'
-import childProcess from 'child_process'
-import { someOfSpyCallsIncludes } from '../test-utils'
-
-use(sinonChai)
-
-describe('init component tests script', () => {
- let promptSpy: SinonStub | null = null
- let logSpy: SinonSpy | null = null
- let processExitStub: SinonStub | null = null
- let execStub: SinonStub | null = null
-
- const e2eTestOutputPath = path.resolve(__dirname, '..', 'test-output')
- const cypressConfigPath = path.join(e2eTestOutputPath, 'cypress.config.ts')
-
- beforeEach(async () => {
- logSpy = sinon.spy(global.console, 'log')
- // @ts-ignores
- execStub = sinon.stub(childProcess, 'exec').callsFake((command, callback) => callback())
- processExitStub = sinon.stub(process, 'exit').callsFake(() => {
- throw new Error(`${chalk.red('process.exit')} should not be called`)
- })
-
- await fs.remove(e2eTestOutputPath)
- await fs.mkdir(e2eTestOutputPath)
-
- process.env.BABEL_TEST_ROOT = e2eTestOutputPath
- })
-
- afterEach(() => {
- mockFs.restore()
- logSpy?.restore()
- promptSpy?.restore()
- processExitStub?.restore()
- execStub?.restore()
- })
-
- function createTempFiles (tempFiles: Record) {
- Object.entries(tempFiles).forEach(([fileName, content]) => {
- fs.outputFileSync(
- path.join(e2eTestOutputPath, fileName),
- content,
- )
- })
- }
-
- function snapshotGeneratedFiles (name: string) {
- snapshot(
- `${name} cypress.config.ts`,
- fs.readFileSync(
- path.join(e2eTestOutputPath, 'cypress.config.ts'),
- { encoding: 'utf-8' },
- ),
- )
-
- snapshot(
- `${name} plugins/index.js`,
- fs.readFileSync(
- path.join(e2eTestOutputPath, 'cypress', 'plugins', 'index.js'),
- { encoding: 'utf-8' },
- ),
- )
-
- const supportFile = fs.readFileSync(
- path.join(e2eTestOutputPath, 'cypress', 'support', 'component.js'),
- { encoding: 'utf-8' },
- )
-
- // Comparing empty snapshot errors.
- if (supportFile.length === 0) {
- return
- }
-
- snapshot(
- `${name} support/component.js`,
- fs.readFileSync(
- path.join(e2eTestOutputPath, 'cypress', 'support', 'component.js'),
- { encoding: 'utf-8' },
- ),
- )
- }
-
- it('determines more presumable configuration to suggest', async () => {
- createTempFiles({
- '/cypress.config.ts': 'export default {}',
- '/cypress/support/component.js': '',
- '/cypress/plugins/index.js': 'module.exports = (on, config) => {}',
- // For next.js user will have babel config, but we want to suggest to use the closest config for the application code
- '/babel.config.js': 'module.exports = { }',
- '/package.json': JSON.stringify({ dependencies: { react: '^17.x', next: '^9.2.0' } }),
- })
-
- promptSpy = sinon.stub(inquirer, 'prompt').returns(Promise.resolve({
- chosenTemplateName: 'next.js',
- componentFolder: 'src',
- }) as any)
-
- await initComponentTesting({ config: {}, cypressConfigPath, useYarn: true })
-
- const [{ choices }] = (inquirer.prompt as any).args[0][0]
-
- expect(choices[0]).to.equal('next.js')
- snapshotGeneratedFiles('injects guessed next.js template')
- })
-
- it('automatically suggests to the user which config to use', async () => {
- createTempFiles({
- '/cypress.config.ts': 'export default {}',
- '/cypress/support/component.js': 'import "./commands.js";',
- '/cypress/plugins/index.js': 'module.exports = () => {}',
- '/package.json': JSON.stringify({
- dependencies: {
- react: '^16.10.0',
- },
- }),
- '/webpack.config.js': 'module.exports = { }',
- })
-
- promptSpy = sinon.stub(inquirer, 'prompt').returns(Promise.resolve({
- chosenTemplateName: 'create-react-app',
- componentFolder: 'cypress/component',
- }) as any)
-
- await initComponentTesting({ config: {}, cypressConfigPath, useYarn: true })
- const [{ choices, message }] = (inquirer.prompt as any).args[0][0]
-
- expect(choices[0]).to.equal('webpack')
- expect(message).to.contain(
- `Press ${chalk.inverse(' Enter ')} to continue with ${chalk.green(
- 'webpack',
- )} configuration`,
- )
-
- snapshotGeneratedFiles('Injected overridden webpack template')
- })
-
- it('Asks for preferred bundling tool if can not determine the right one', async () => {
- createTempFiles({
- '/cypress.config.ts': 'export default {}',
- '/webpack.config.js': 'module.exports = { }',
- '/package.json': JSON.stringify({ dependencies: { } }),
- })
-
- promptSpy = sinon.stub(inquirer, 'prompt')
- .onCall(0)
- .returns(Promise.resolve({
- framework: 'vue@2',
- }) as any)
- .onCall(1)
- .returns(Promise.resolve({
- chosenTemplateName: 'webpack',
- componentFolder: 'src',
- }) as any)
-
- await initComponentTesting({ config: {}, cypressConfigPath, useYarn: true })
-
- expect(
- someOfSpyCallsIncludes(global.console.log, 'We were unable to automatically determine your framework 😿'),
- ).to.be.true
- })
-
- it('Asks for framework if more than 1 option was auto detected', async () => {
- createTempFiles({
- '/cypress.config.ts': 'export default {}',
- '/webpack.config.js': 'module.exports = { }',
- '/package.json': JSON.stringify({ dependencies: { react: '*', vue: '^2.4.5' } }),
- })
-
- promptSpy = sinon.stub(inquirer, 'prompt')
- .onCall(0)
- .returns(Promise.resolve({
- framework: 'vue@3',
- }) as any)
- .onCall(1)
- .returns(Promise.resolve({
- chosenTemplateName: 'webpack',
- componentFolder: 'src',
- }) as any)
-
- await initComponentTesting({ config: {}, cypressConfigPath, useYarn: true })
-
- expect(
- someOfSpyCallsIncludes(global.console.log, `It looks like all these frameworks: ${chalk.yellow('react, vue@2')} are available from this directory.`),
- ).to.be.true
- })
-
- it('installs the right adapter', async () => {
- createTempFiles({
- '/cypress.config.ts': 'export default {}',
- '/webpack.config.js': 'module.exports = { }',
- '/package.json': JSON.stringify({ dependencies: { react: '16.4.5' } }),
- })
-
- promptSpy = sinon.stub(inquirer, 'prompt')
- .onCall(0)
- .returns(Promise.resolve({
- chosenTemplateName: 'vite',
- componentFolder: 'src',
- }) as any)
-
- await initComponentTesting({ config: {}, cypressConfigPath, useYarn: true })
- expect(execStub).to.be.calledWith('yarn add @cypress/react --dev')
- })
-
- it('installs the right adapter for vue 3', async () => {
- createTempFiles({
- '/cypress.config.ts': 'export default {}',
- '/vite.config.js': 'module.exports = { }',
- '/package.json': JSON.stringify({ dependencies: { vue: '^3.0.0' } }),
- })
-
- promptSpy = sinon.stub(inquirer, 'prompt')
- .onCall(0)
- .returns(Promise.resolve({
- chosenTemplateName: 'vite',
- componentFolder: 'src',
- }) as any)
-
- await initComponentTesting({ config: {}, cypressConfigPath, useYarn: true })
- expect(execStub).to.be.calledWith('yarn add @cypress/vue --dev')
- })
-
- it('suggest the right instruction based on user template choice', async () => {
- createTempFiles({
- '/package.json': JSON.stringify({
- dependencies: {
- react: '^16.0.0',
- },
- }),
- '/cypress.config.ts': 'export default {}',
- })
-
- promptSpy = sinon.stub(inquirer, 'prompt').returns(Promise.resolve({
- chosenTemplateName: 'create-react-app',
- componentFolder: 'src',
- }) as any)
-
- await initComponentTesting({ config: {}, cypressConfigPath, useYarn: true })
- expect(
- someOfSpyCallsIncludes(
- global.console.log,
- 'https://github.com/cypress-io/cypress/tree/develop/npm/react/examples/react-scripts',
- ),
- ).to.be.true
- })
-
- it('suggests right docs example and cypress.config.ts config based on the `componentFolder` answer', async () => {
- createTempFiles({
- '/cypress.config.ts': 'export default {}',
- '/package.json': JSON.stringify({
- dependencies: {
- react: '^16.0.0',
- },
- }),
- })
-
- sinon.stub(inquirer, 'prompt').returns(Promise.resolve({
- chosenTemplateName: 'create-react-app',
- componentFolder: 'cypress/component',
- }) as any)
-
- await initComponentTesting({ config: {}, cypressConfigPath, useYarn: true })
-
- const injectedCode = require(path.join(e2eTestOutputPath, 'cypress.config.ts'))
-
- expect(JSON.stringify(injectedCode.default, null, 2)).to.equal(JSON.stringify(
- {
- specPattern: 'cypress/component/**/*.spec.{js,ts,jsx,tsx}',
- },
- null,
- 2,
- ))
- })
-
- it('Shows help message if cypress files are not created', async () => {
- createTempFiles({
- '/cypress.config.ts': 'export default {}',
- '/package.json': JSON.stringify({
- dependencies: {
- react: '^16.0.0',
- },
- }),
- })
-
- sinon.stub(inquirer, 'prompt').returns(Promise.resolve({
- chosenTemplateName: 'create-react-app',
- componentFolder: 'cypress/component',
- }) as any)
-
- await initComponentTesting({ config: {}, cypressConfigPath, useYarn: true })
-
- expect(
- someOfSpyCallsIncludes(
- global.console.log,
- 'was not updated automatically. Please add the following config manually:',
- ),
- ).to.be.true
- })
-
- it(`Doesn't affect injected code if user has custom babel.config.js`, async () => {
- createTempFiles({
- '/cypress/plugins/index.js': 'module.exports = (on, config) => {}',
- '/cypress.config.ts': 'export default {}',
- 'babel.config.js': `module.exports = ${JSON.stringify({
- presets: [
- '@babel/preset-env',
- ],
- })}`,
- '/package.json': JSON.stringify({
- dependencies: {
- babel: '*',
- react: '^16.0.0',
- },
- }),
- })
-
- sinon.stub(inquirer, 'prompt').returns(Promise.resolve({
- chosenTemplateName: 'create-react-app',
- componentFolder: 'cypress/component',
- }) as any)
-
- await initComponentTesting({ config: {}, cypressConfigPath, useYarn: true })
- const babelPluginsOutput = await fs.readFile(
- path.join(e2eTestOutputPath, 'cypress', 'plugins', 'index.js'),
- 'utf-8',
- )
-
- expect(babelPluginsOutput).not.to.contain('use strict')
- expect(babelPluginsOutput).to.contain('module.exports = (on, config) => {')
- })
-})
diff --git a/npm/create-cypress-tests/src/component-testing/init-component-testing.ts b/npm/create-cypress-tests/src/component-testing/init-component-testing.ts
deleted file mode 100644
index a79908088fef..000000000000
--- a/npm/create-cypress-tests/src/component-testing/init-component-testing.ts
+++ /dev/null
@@ -1,194 +0,0 @@
-import fs from 'fs-extra'
-import path from 'path'
-import chalk from 'chalk'
-import inquirer from 'inquirer'
-import highlight from 'cli-highlight'
-import { Template } from './templates/Template'
-import { guessTemplate } from './templates/guessTemplate'
-import { installFrameworkAdapter } from './installFrameworkAdapter'
-import { injectPluginsCode, getPluginsSourceExample } from './babel/babelTransform'
-import { installDependency } from '../utils'
-import { insertValuesInConfigFile } from './config-file-updater/configFileUpdater'
-
-async function injectOrShowConfigCode (injectFn: () => Promise, {
- code,
- filePath,
- fallbackFileMessage,
- language,
-}: {
- code: string
- filePath: string
- language: string
- fallbackFileMessage: string
-}) {
- const fileExists = fs.existsSync(filePath)
- const readableFilePath = fileExists ? path.relative(process.cwd(), filePath) : fallbackFileMessage
-
- const printCode = () => {
- console.log()
- console.log(highlight(code, { language }))
- console.log()
- }
-
- const printSuccess = () => {
- console.log(`✅ ${chalk.bold.green(readableFilePath)} was updated with the following config:`)
- printCode()
- }
-
- const printFailure = () => {
- console.log(`❌ ${chalk.bold.red(readableFilePath)} was not updated automatically. Please add the following config manually: `)
- printCode()
- }
-
- if (!fileExists) {
- printFailure()
-
- return
- }
-
- // something get completely wrong when using babel or something. Print error message.
- const injected = await injectFn().catch(() => false)
-
- injected ? printSuccess() : printFailure()
-}
-
-async function injectAndShowCypressConfig (
- cypressJsonPath: string,
- componentFolder: string,
-) {
- const configToInject = {
- specPattern: `${componentFolder}/**/*.spec.{js,ts,jsx,tsx}`,
- }
-
- await injectOrShowConfigCode(() => insertValuesInConfigFile(cypressJsonPath, configToInject), {
- code: JSON.stringify(configToInject, null, 2),
- language: 'js',
- filePath: cypressJsonPath,
- fallbackFileMessage: 'cypress.json config file',
- })
-}
-
-async function injectAndShowPluginConfig (template: Template, {
- templatePayload,
- pluginsFilePath,
- cypressProjectRoot,
-}: {
- templatePayload: T | null
- pluginsFilePath: string
- cypressProjectRoot: string
-}) {
- const ast = template.getPluginsCodeAst(templatePayload, { cypressProjectRoot })
-
- await injectOrShowConfigCode(() => injectPluginsCode(pluginsFilePath, ast), {
- code: await getPluginsSourceExample(ast),
- language: 'js',
- filePath: pluginsFilePath,
- fallbackFileMessage: 'plugins file (https://on.cypress.io/plugins-file)',
- })
-}
-
-type InitComponentTestingOptions = {
- config: Record
- cypressConfigPath: string
- useYarn: boolean
-}
-
-export async function initComponentTesting ({ config, useYarn, cypressConfigPath }: InitComponentTestingOptions) {
- const cypressProjectRoot = path.resolve(cypressConfigPath, '..')
-
- const framework = await installFrameworkAdapter(cypressProjectRoot, { useYarn })
- const {
- possibleTemplates,
- defaultTemplate,
- defaultTemplateName,
- templatePayload,
- } = await guessTemplate(framework, cypressProjectRoot)
-
- const pluginsFilePath = path.resolve(
- cypressProjectRoot,
- config.pluginsFile ?? './cypress/plugins/index.js',
- )
-
- const templateChoices = Object.keys(possibleTemplates).sort((key) => {
- return key === defaultTemplateName ? -1 : 0
- })
-
- const {
- chosenTemplateName,
- componentFolder,
- }: Record = await inquirer.prompt([
- {
- type: 'list',
- name: 'chosenTemplateName',
- choices: templateChoices,
- default: defaultTemplate ? 0 : undefined,
- message: defaultTemplate?.message
- ? `${defaultTemplate?.message}\n\n Press ${chalk.inverse(
- ' Enter ',
- )} to continue with ${chalk.green(
- defaultTemplateName,
- )} configuration or select another template from the list:`
- : 'We were not able to automatically determine which framework or bundling tool you are using. Please choose one from the list:',
- },
- {
- type: 'input',
- name: 'componentFolder',
- filter: (input) => input.trim(),
- validate: (input) => {
- return input === '' || !/^[a-zA-Z].*/.test(input)
- ? `Directory "${input}" is invalid`
- : true
- },
- message: 'Which folder would you like to use for your component tests?',
- default: (answers: { chosenTemplateName: keyof typeof possibleTemplates }) => {
- return possibleTemplates[answers.chosenTemplateName].recommendedComponentFolder
- },
- },
- ])
-
- const chosenTemplate = possibleTemplates[chosenTemplateName] as Template
-
- console.log()
- console.log(`Installing required dependencies`)
- console.log()
-
- for (const dependency of chosenTemplate.dependencies) {
- await installDependency(dependency, { useYarn })
- }
-
- console.log()
- console.log(`Let's setup everything for component testing with ${chalk.cyan(chosenTemplateName)}:`)
- console.log()
-
- await injectAndShowCypressConfig(cypressConfigPath, componentFolder)
- await injectAndShowPluginConfig(chosenTemplate, {
- templatePayload,
- pluginsFilePath,
- cypressProjectRoot,
- })
-
- if (chosenTemplate.printHelper) {
- chosenTemplate.printHelper()
- }
-
- console.log(
- `Find examples of component tests for ${chalk.green(
- chosenTemplateName,
- )} in ${chalk.underline(chosenTemplate.getExampleUrl({ componentFolder }))}.`,
- )
-
- if (framework === 'react') {
- console.log()
-
- console.log(
- `Docs for different recipes of bundling tools: ${chalk.bold.underline(
- 'https://github.com/cypress-io/cypress/tree/develop/npm/react/docs/recipes.md',
- )}`,
- )
- }
-
- // render delimiter
- console.log()
- console.log(new Array(process.stdout.columns).fill('═').join(''))
- console.log()
-}
diff --git a/npm/create-cypress-tests/src/component-testing/installFrameworkAdapter.ts b/npm/create-cypress-tests/src/component-testing/installFrameworkAdapter.ts
deleted file mode 100644
index 18e669a02eab..000000000000
--- a/npm/create-cypress-tests/src/component-testing/installFrameworkAdapter.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import chalk from 'chalk'
-import inquirer from 'inquirer'
-import { scanFSForAvailableDependency } from '../findPackageJson'
-import { installDependency } from '../utils'
-
-async function guessOrAskForFramework (cwd: string): Promise<'react' | 'vue@2' | 'vue@3'> {
- // please sort this alphabetically
- const frameworks = {
- react: () => scanFSForAvailableDependency(cwd, { react: '*', 'react-dom': '*' }),
- 'vue@2': () => scanFSForAvailableDependency(cwd, { vue: '2.x' }),
- 'vue@3': () => scanFSForAvailableDependency(cwd, { vue: '3.x' }),
- }
-
- const guesses = Object.keys(frameworks).filter((framework) => {
- return frameworks[framework as keyof typeof frameworks]()
- }) as Array<'react' | 'vue@2' | 'vue@3'>
-
- // found 1 precise guess. Continue
- if (guesses.length === 1) {
- const framework = guesses[0]
-
- console.log(`\nThis project is using ${chalk.bold.cyan(framework)}. Let's install the right adapter:`)
-
- return framework
- }
-
- if (guesses.length === 0) {
- console.log(`We were unable to automatically determine your framework 😿. ${chalk.grey('Make sure to run this command from the directory where your components located in order to make smart detection works. Or continue with manual setup:')}`)
- }
-
- if (guesses.length > 0) {
- console.log(`It looks like all these frameworks: ${chalk.yellow(guesses.join(', '))} are available from this directory. ${chalk.grey('Make sure to run this command from the directory where your components located in order to make smart detection works. Or continue with manual setup:')}`)
- }
-
- const { framework } = await inquirer.prompt([
- {
- type: 'list',
- name: 'framework',
- choices: Object.keys(frameworks),
- message: `Which framework do you use?`,
- },
- ])
-
- return framework
-}
-
-type InstallAdapterOptions = {
- useYarn: boolean
-}
-
-const frameworkDependencies = {
- react: '@cypress/react',
- 'vue@2': '@cypress/vue2',
- 'vue@3': '@cypress/vue',
-}
-
-export async function installFrameworkAdapter (cwd: string, options: InstallAdapterOptions) {
- const framework = await guessOrAskForFramework(cwd)
-
- await installDependency(frameworkDependencies[framework], options)
-
- return framework
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/Template.ts b/npm/create-cypress-tests/src/component-testing/templates/Template.ts
deleted file mode 100644
index 72ea8de09d2b..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/Template.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { PluginsConfigAst } from '../babel/babelTransform'
-
-export interface Template {
- message: string
- getExampleUrl: ({ componentFolder }: { componentFolder: string }) => string
- recommendedComponentFolder: string
- test(rootPath: string): { success: boolean, payload?: T }
- getPluginsCodeAst: (
- payload: T | null,
- options: { cypressProjectRoot: string },
- ) => PluginsConfigAst
- dependencies: string[]
- printHelper?: () => void
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/_shared/index.ts b/npm/create-cypress-tests/src/component-testing/templates/_shared/index.ts
deleted file mode 100644
index 58f0af7bbb8f..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/_shared/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { Template } from '../Template'
-import { ViteTemplate } from './vite'
-
-export const frameworkAgnosticTemplates: Record> = {
- vite: ViteTemplate,
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/_shared/vite.test.ts b/npm/create-cypress-tests/src/component-testing/templates/_shared/vite.test.ts
deleted file mode 100644
index 78b557d86091..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/_shared/vite.test.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { ViteTemplate } from './vite'
-import { snapshotPluginsAstCode } from '../../../test-utils'
-
-describe('vue: vite template', () => {
- it('correctly generates plugins config', () => snapshotPluginsAstCode(ViteTemplate))
-})
diff --git a/npm/create-cypress-tests/src/component-testing/templates/_shared/vite.ts b/npm/create-cypress-tests/src/component-testing/templates/_shared/vite.ts
deleted file mode 100644
index b9b6f8f93c57..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/_shared/vite.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import * as babel from '@babel/core'
-import { scanFSForAvailableDependency } from '../../../findPackageJson'
-import { Template } from '../Template'
-
-export const ViteTemplate: Template = {
- message:
- 'It looks like you are using vitejs to run and build an application.',
- getExampleUrl: () => 'https://github.com/cypress-io/cypress/tree/develop/npm/vue/examples/vite',
- recommendedComponentFolder: 'src',
- dependencies: ['@cypress/vite-dev-server'],
- getPluginsCodeAst: () => {
- return {
- requiresReturnConfig: true,
- RequireAst: babel.template.ast(
- 'const { startDevServer } = require("@cypress/vite-dev-server");',
- ),
- IfComponentTestingPluginsAst: babel.template.ast([
- 'on("dev-server:start", async (options) => startDevServer({ options }))',
- ].join('\n'), { preserveComments: true }),
- }
- },
- test: (root) => {
- return {
- success: scanFSForAvailableDependency(root, { vite: '*' }),
- }
- },
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/guessTemplate.ts b/npm/create-cypress-tests/src/component-testing/templates/guessTemplate.ts
deleted file mode 100644
index 10bcdfaa93a8..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/guessTemplate.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { Template } from './Template'
-import { reactTemplates } from './react'
-import { vueTemplates } from './vue'
-import { frameworkAgnosticTemplates } from './_shared'
-
-const frameworkSpecificTemplates = {
- react: reactTemplates,
- 'vue@2': vueTemplates,
- 'vue@3': vueTemplates,
-}
-
-export async function guessTemplate (framework: keyof typeof frameworkSpecificTemplates, cwd: string) {
- const templates = { ...frameworkAgnosticTemplates, ...frameworkSpecificTemplates[framework] }
-
- for (const [name, template] of Object.entries(templates)) {
- const typedTemplate = template as Template
- const { success, payload } = typedTemplate.test(cwd)
-
- if (success) {
- return {
- defaultTemplate: typedTemplate,
- defaultTemplateName: name,
- templatePayload: payload ?? null,
- possibleTemplates: templates,
- }
- }
- }
-
- return {
- templatePayload: null,
- defaultTemplate: null,
- defaultTemplateName: null,
- possibleTemplates: templates,
- }
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/babel.test.ts b/npm/create-cypress-tests/src/component-testing/templates/react/babel.test.ts
deleted file mode 100644
index 1bff7af467af..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/babel.test.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { expect } from 'chai'
-import mockFs from 'mock-fs'
-import { BabelTemplate } from './babel'
-import { snapshotPluginsAstCode } from '../../../test-utils'
-
-describe('babel installation template', () => {
- beforeEach(mockFs.restore)
-
- it('resolves babel.config.json', () => {
- mockFs({
- '/babel.config.json': JSON.stringify({
- presets: [],
- plugins: [],
- }),
- })
-
- const { success } = BabelTemplate.test('/')
-
- expect(success).to.equal(true)
- })
-
- it('resolves babel.config.js', () => {
- mockFs({
- '/project/babel.config.js':
- 'module.exports = { presets: [], plugins: [] };',
- '/project/index/package.json': 'dev/null',
- })
-
- const { success } = BabelTemplate.test('/project/index')
-
- expect(success).to.equal(true)
- })
-
- it('resolves babel config from the deep folder', () => {
- mockFs({
- '/some/.babelrc': JSON.stringify({
- presets: [],
- plugins: [],
- }),
- '/some/deep/folder/text.txt': '1',
- })
-
- const { success } = BabelTemplate.test('/some/deep/folder')
-
- expect(success).to.equal(true)
- })
-
- it('fails if no babel config found', () => {
- mockFs({
- '/some.txt': '1',
- })
-
- const { success } = BabelTemplate.test('/')
-
- expect(success).to.equal(false)
- })
-
- it('resolves babel.config from package.json', () => {
- mockFs({
- '/package.json': JSON.stringify({
- babel: {
- presets: [],
- },
- }),
- })
-
- const { success } = BabelTemplate.test('/')
-
- expect(success).to.equal(true)
- })
-
- it('correctly generates plugins config', () => snapshotPluginsAstCode(BabelTemplate))
-})
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/babel.ts b/npm/create-cypress-tests/src/component-testing/templates/react/babel.ts
deleted file mode 100644
index 0202d05b4400..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/babel.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import chalk from 'chalk'
-import findUp from 'find-up'
-import * as babel from '@babel/core'
-import { Template } from '../Template'
-import { createFindPackageJsonIterator } from '../../../findPackageJson'
-
-export const BabelTemplate: Template = {
- message: `It looks like you have babel config defined. We can use it to transpile your components for testing.\n ${chalk.red(
- '>>',
- )} This is not a replacement for bundling tool. We will use ${chalk.red(
- 'webpack',
- )} to bundle the components for testing.`,
- recommendedComponentFolder: 'cypress/component',
- dependencies: ['webpack', '@cypress/webpack-dev-server'],
- getExampleUrl: () => 'https://github.com/cypress-io/cypress/tree/develop/npm/react/examples/babel',
- getPluginsCodeAst: () => {
- return {
- requiresReturnConfig: true,
- RequireAst: babel.template.ast('const injectDevServer = require(\'@cypress/react/plugins/babel\')'),
- IfComponentTestingPluginsAst: babel.template.ast([
- 'injectDevServer(on, config)',
- ].join('\n'), { preserveComments: true }),
- }
- },
- test: (cwd) => {
- const babelConfig = findUp.sync(
- ['babel.config.js', 'babel.config.json', '.babelrc', '.babelrc.json'],
- { type: 'file', cwd },
- )
-
- if (babelConfig) {
- return { success: true }
- }
-
- // babel config can also be declared in package.json with `babel` key https://babeljs.io/docs/en/configuration#packagejson
- const packageJsonIterator = createFindPackageJsonIterator(cwd)
-
- return packageJsonIterator.map(({ babel }) => {
- return {
- success: Boolean(babel),
- }
- })
- },
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/index.ts b/npm/create-cypress-tests/src/component-testing/templates/react/index.ts
deleted file mode 100644
index bbbfca5178fb..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/index.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { Template } from '../Template'
-import { NextTemplate } from './next'
-import { WebpackTemplate } from './reactWebpackFile'
-import { ReactScriptsTemplate } from './react-scripts'
-import { BabelTemplate } from './babel'
-import { WebpackOptions } from './webpack-options'
-
-export const reactTemplates: Record> = {
- 'create-react-app': ReactScriptsTemplate,
- 'next.js': NextTemplate,
- webpack: WebpackTemplate,
- babel: BabelTemplate,
- 'default (webpack options)': WebpackOptions,
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/next.test.ts b/npm/create-cypress-tests/src/component-testing/templates/react/next.test.ts
deleted file mode 100644
index 4701791877e3..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/next.test.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import sinon, { SinonSpy } from 'sinon'
-import { expect, use } from 'chai'
-import sinonChai from 'sinon-chai'
-import mockFs from 'mock-fs'
-import { NextTemplate } from './next'
-import { snapshotPluginsAstCode } from '../../../test-utils'
-
-use(sinonChai)
-
-describe('next.js install template', () => {
- let warnSpy: SinonSpy | null = null
-
- beforeEach(() => {
- warnSpy = sinon.spy(global.console, 'warn')
- })
-
- afterEach(() => {
- mockFs.restore()
- warnSpy?.restore()
- })
-
- it('finds the closest package.json and checks that next is declared as dependency', () => {
- mockFs({
- '/package.json': JSON.stringify({
- dependencies: {
- next: '^9.2.3',
- },
- scripts: {
- build: 'next',
- },
- }),
- })
-
- const { success } = NextTemplate.test('/')
-
- expect(success).to.equal(true)
- })
-
- it('works if next is declared in the devDependencies as well', () => {
- mockFs({
- './package.json': JSON.stringify({
- devDependencies: {
- next: '^9.2.3',
- },
- scripts: {
- build: 'next',
- },
- }),
- })
-
- const { success } = NextTemplate.test(process.cwd())
-
- expect(success).to.equal(true)
- })
-
- it('warns and fails if version is not supported', () => {
- mockFs({
- './package.json': JSON.stringify({
- devDependencies: {
- next: '^8.2.3',
- },
- scripts: {
- build: 'next',
- },
- }),
- })
-
- const { success } = NextTemplate.test('i/am/in/some/deep/folder')
-
- console.log(global.console.warn)
- expect(success).to.equal(false)
-
- expect(global.console.warn).to.be.called
- })
-
- it('correctly generates plugins config', () => snapshotPluginsAstCode(NextTemplate))
-})
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/next.ts b/npm/create-cypress-tests/src/component-testing/templates/react/next.ts
deleted file mode 100644
index 2f7ef89adfa1..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/next.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import * as babel from '@babel/core'
-import { createFindPackageJsonIterator } from '../../../findPackageJson'
-import { Template } from '../Template'
-import { validateSemverVersion } from '../../../utils'
-import { MIN_SUPPORTED_VERSION } from '../../versions'
-
-export const NextTemplate: Template = {
- message: 'It looks like you are using next.js.',
- getExampleUrl: () => {
- return 'https://github.com/cypress-io/cypress/tree/develop/npm/react/examples/nextjs'
- },
- recommendedComponentFolder: 'cypress/component',
- dependencies: ['@cypress/webpack-dev-server'],
- getPluginsCodeAst: () => {
- return {
- requiresReturnConfig: true,
- RequireAst: babel.template.ast('const injectDevServer = require(\'@cypress/react/plugins/next\')'),
- IfComponentTestingPluginsAst: babel.template.ast([
- 'injectDevServer(on, config)',
- ].join('\n'), { preserveComments: true }),
- }
- },
- test: (cwd) => {
- const packageJsonIterator = createFindPackageJsonIterator(cwd)
-
- return packageJsonIterator.map(({ dependencies, devDependencies }, path) => {
- if (!dependencies && !devDependencies) {
- return { success: false }
- }
-
- const allDeps = {
- ...(devDependencies || {}),
- ...(dependencies || {}),
- } as Record
-
- const nextVersion = allDeps['next']
-
- if (!nextVersion) {
- return { success: false }
- }
-
- if (
- !validateSemverVersion(
- nextVersion,
- MIN_SUPPORTED_VERSION['next'],
- 'next.js',
- )
- ) {
- return { success: false }
- }
-
- return { success: true }
- })
- },
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/react-scripts.test.ts b/npm/create-cypress-tests/src/component-testing/templates/react/react-scripts.test.ts
deleted file mode 100644
index 7bf01624006a..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/react-scripts.test.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import sinon, { SinonSpy } from 'sinon'
-import { expect, use } from 'chai'
-import sinonChai from 'sinon-chai'
-import mockFs from 'mock-fs'
-import { ReactScriptsTemplate } from './react-scripts'
-import { snapshotPluginsAstCode } from '../../../test-utils'
-
-use(sinonChai)
-
-describe('create-react-app install template', () => {
- let warnSpy: SinonSpy | null = null
-
- beforeEach(() => {
- warnSpy = sinon.spy(global.console, 'warn')
- })
-
- afterEach(() => {
- mockFs.restore()
- warnSpy?.restore()
- })
-
- it('finds the closest package.json and checks that react-scripts is declared as dependency', () => {
- mockFs({
- '/package.json': JSON.stringify({
- dependencies: {
- 'react-scripts': '^3.2.3',
- },
- }),
- })
-
- const { success } = ReactScriptsTemplate.test(process.cwd())
-
- expect(success).to.equal(true)
- })
-
- it('works if react-scripts is declared in the devDependencies as well', () => {
- mockFs({
- './package.json': JSON.stringify({
- devDependencies: {
- 'react-scripts': '^3.2.3',
- },
- }),
- })
-
- const { success } = ReactScriptsTemplate.test(process.cwd())
-
- expect(success).to.equal(true)
- })
-
- it('warns and fails if version is not supported', () => {
- mockFs({
- './package.json': JSON.stringify({
- devDependencies: {
- 'react-scripts': '^2.2.3',
- },
- }),
- })
-
- const { success } = ReactScriptsTemplate.test(process.cwd())
-
- expect(success).to.equal(false)
- expect(global.console.warn).to.be.called
- })
-
- it('correctly generates plugins config', () => snapshotPluginsAstCode(ReactScriptsTemplate))
-})
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/react-scripts.ts b/npm/create-cypress-tests/src/component-testing/templates/react/react-scripts.ts
deleted file mode 100644
index 860106b74b24..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/react-scripts.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import chalk from 'chalk'
-import { createFindPackageJsonIterator } from '../../../findPackageJson'
-import { Template } from '../Template'
-import { validateSemverVersion } from '../../../utils'
-import { MIN_SUPPORTED_VERSION } from '../../versions'
-import * as babel from '@babel/core'
-
-export const ReactScriptsTemplate: Template = {
- recommendedComponentFolder: 'src',
- message: 'It looks like you are using create-react-app.',
- dependencies: ['@cypress/webpack-dev-server'],
- getExampleUrl: ({ componentFolder }) => {
- return componentFolder === 'src'
- ? 'https://github.com/cypress-io/cypress/tree/develop/npm/react/examples/react-scripts'
- : 'https://github.com/cypress-io/cypress/tree/develop/npm/react/examples/react-scripts-folder'
- },
- getPluginsCodeAst: () => {
- return {
- requiresReturnConfig: true,
- RequireAst: babel.template.ast('const injectDevServer = require(\'@cypress/react/plugins/react-scripts\')'),
- IfComponentTestingPluginsAst: babel.template.ast([
- 'injectDevServer(on, config)',
- ].join('\n'), { preserveComments: true }),
- }
- },
- test: () => {
- // TODO also determine ejected create react app
- const packageJsonIterator = createFindPackageJsonIterator(process.cwd())
-
- return packageJsonIterator.map(({ dependencies, devDependencies }) => {
- if (dependencies || devDependencies) {
- const allDeps = { ...devDependencies, ...dependencies } || {}
-
- if (!allDeps['react-scripts']) {
- return { success: false }
- }
-
- if (
- !validateSemverVersion(
- allDeps['react-scripts'],
- MIN_SUPPORTED_VERSION['react-scripts'],
- )
- ) {
- console.warn(
- `It looks like you are using ${chalk.green(
- 'create-react-app',
- )}, but we support only projects with version ${chalk.bold(
- MIN_SUPPORTED_VERSION['react-scripts'],
- )} of react-scripts.`,
- )
-
- // yey found the template
- return { success: false }
- }
-
- return { success: true }
- }
-
- return { success: false }
- })
- },
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/reactWebpackFile.test.ts b/npm/create-cypress-tests/src/component-testing/templates/react/reactWebpackFile.test.ts
deleted file mode 100644
index 4212fcc04f51..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/reactWebpackFile.test.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import { expect } from 'chai'
-import mockFs from 'mock-fs'
-import { snapshotPluginsAstCode } from '../../../test-utils'
-import { WebpackTemplate } from './reactWebpackFile'
-
-describe('webpack-file install template', () => {
- afterEach(mockFs.restore)
-
- it('resolves webpack.config.js', () => {
- mockFs({
- '/webpack.config.js': 'module.exports = { }',
- })
-
- const { success, payload } = WebpackTemplate.test(process.cwd())
-
- expect(success).to.equal(true)
- expect(payload?.webpackConfigPath).to.equal('/webpack.config.js')
- })
-
- it('finds the closest package.json and tries to fetch webpack config path from scrips', () => {
- mockFs({
- '/configs/webpack.js': 'module.exports = { }',
- '/package.json': JSON.stringify({
- scripts: {
- build: 'webpack --config configs/webpack.js',
- },
- }),
- })
-
- const { success, payload } = WebpackTemplate.test(process.cwd())
-
- expect(success).to.equal(true)
- expect(payload?.webpackConfigPath).to.equal('/configs/webpack.js')
- })
-
- it('looks for package.json in the upper folder', () => {
- mockFs({
- '/i/am/in/some/deep/folder/withFile': 'test',
- '/somewhere/configs/webpack.js': 'module.exports = { }',
- '/package.json': JSON.stringify({
- scripts: {
- build: 'webpack --config somewhere/configs/webpack.js',
- },
- }),
- })
-
- const { success, payload } = WebpackTemplate.test(
- 'i/am/in/some/deep/folder',
- )
-
- expect(success).to.equal(true)
- expect(payload?.webpackConfigPath).to.equal('/somewhere/configs/webpack.js')
- })
-
- it('returns success:false if cannot find webpack config', () => {
- mockFs({
- '/a.js': '1',
- '/b.js': '2',
- })
-
- const { success, payload } = WebpackTemplate.test('/')
-
- expect(success).to.equal(false)
- expect(payload).to.equal(undefined)
- })
-
- it('correctly generates plugins config when webpack config path is missing', () => {
- snapshotPluginsAstCode(WebpackTemplate)
- })
-
- it('correctly generates plugins config when webpack config path is provided', () => {
- snapshotPluginsAstCode(WebpackTemplate, { webpackConfigPath: '/config/webpack.config.js' })
- })
-})
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/reactWebpackFile.ts b/npm/create-cypress-tests/src/component-testing/templates/react/reactWebpackFile.ts
deleted file mode 100644
index 6bc89f7fe0fe..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/reactWebpackFile.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import * as babel from '@babel/core'
-import path from 'path'
-import { Template } from '../Template'
-import { findWebpackConfig } from '../templateUtils'
-
-export const WebpackTemplate: Template<{ webpackConfigPath: string }> = {
- message:
- 'It looks like you have custom `webpack.config.js`. We can use it to bundle the components for testing.',
- getExampleUrl: () => {
- return 'https://github.com/cypress-io/cypress/tree/develop/npm/react/examples/webpack-file'
- },
- recommendedComponentFolder: 'cypress/component',
- dependencies: ['@cypress/webpack-dev-server'],
- getPluginsCodeAst: (payload, { cypressProjectRoot }) => {
- const includeWarnComment = !payload
- const webpackConfigPath = payload
- ? path.relative(cypressProjectRoot, payload.webpackConfigPath)
- : './webpack.config.js'
-
- return {
- requiresReturnConfig: true,
- RequireAst: babel.template.ast('const injectDevServer = require("@cypress/react/plugins/load-webpack")'),
- IfComponentTestingPluginsAst: babel.template.ast([
- 'injectDevServer(on, config, {',
- includeWarnComment
- ? ' // TODO replace with valid webpack config path'
- : '',
- ` webpackFilename: '${webpackConfigPath}'`,
- '})',
- ].join('\n'), { preserveComments: true }),
- }
- },
- test: (root) => {
- const webpackConfigPath = findWebpackConfig(root)
-
- return webpackConfigPath ? {
- success: true,
- payload: { webpackConfigPath },
- } : {
- success: false,
- }
- },
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/webpack-options-module-exports.template.js b/npm/create-cypress-tests/src/component-testing/templates/react/webpack-options-module-exports.template.js
deleted file mode 100644
index cffd3bce12ff..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/webpack-options-module-exports.template.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/** @type import("webpack").Configuration */
-const webpackConfig = {
- resolve: {
- extensions: ['.js', '.ts', '.jsx', '.tsx'],
- },
- mode: 'development',
- devtool: false,
- output: {
- publicPath: '/',
- chunkFilename: '[name].bundle.js',
- },
- // TODO: update with valid configuration for your components
- module: {
- rules: [
- {
- test: /\.(js|jsx|mjs|ts|tsx)$/,
- loader: 'babel-loader',
- options: { cacheDirectory: path.resolve(__dirname, '.babel-cache') },
- },
- ]
- },
-}
-
-on('dev-server:start', (options) => startDevServer({ options, webpackConfig }))
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/webpack-options.ts b/npm/create-cypress-tests/src/component-testing/templates/react/webpack-options.ts
deleted file mode 100644
index 8765be52910c..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/webpack-options.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import fs from 'fs'
-import path from 'path'
-import * as babel from '@babel/core'
-import chalk from 'chalk'
-import { Template } from '../Template'
-
-export const WebpackOptions: Template = {
- // this should never show ideally
- message: `Unable to detect where webpack options are.`,
- getExampleUrl: () => {
- return 'https://github.com/cypress-io/cypress/tree/develop/npm/react/examples/webpack-options'
- },
- test: () => ({ success: false }),
- recommendedComponentFolder: 'src',
- dependencies: ['webpack', '@cypress/webpack-dev-server'],
- getPluginsCodeAst: () => {
- return {
- RequireAst: babel.template.ast([
- 'const path = require("path")',
- 'const { startDevServer } = require("@cypress/webpack-dev-Server")',
- ].join('\n')),
- IfComponentTestingPluginsAst: babel.template.ast(
- fs.readFileSync(path.resolve(__dirname, 'webpack-options-module-exports.template.js'), { encoding: 'utf-8' }),
- { preserveComments: true },
- ),
- }
- },
- printHelper: () => {
- console.log(
- `${chalk.inverse('Important:')} this configuration is using ${chalk.blue(
- 'new webpack configuration',
- )} to bundle components. If you are using some framework (e.g. next) or bundling tool (e.g. rollup/vite) consider using them to bundle component specs for cypress. \n`,
- )
- },
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/react/webpackOptions.test.ts b/npm/create-cypress-tests/src/component-testing/templates/react/webpackOptions.test.ts
deleted file mode 100644
index c7b7e2e6f9a3..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/react/webpackOptions.test.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { WebpackOptions } from './webpack-options'
-import { snapshotPluginsAstCode } from '../../../test-utils'
-
-describe('webpack-options template', () => {
- it('correctly generates plugins config', () => snapshotPluginsAstCode(WebpackOptions))
-})
diff --git a/npm/create-cypress-tests/src/component-testing/templates/templateUtils.ts b/npm/create-cypress-tests/src/component-testing/templates/templateUtils.ts
deleted file mode 100644
index 8b1f8e978f3e..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/templateUtils.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import findUp from 'find-up'
-import path from 'path'
-import { createFindPackageJsonIterator } from '../../findPackageJson'
-
-export function extractWebpackConfigPathFromScript (script: string) {
- if (script.includes('webpack ') || script.includes('webpack-dev-server ')) {
- const webpackCliArgs = script.split(' ').map((part) => part.trim())
- const configArgIndex = webpackCliArgs.findIndex((arg) => arg === '--config')
-
- return configArgIndex === -1 ? null : webpackCliArgs[configArgIndex + 1]
- }
-
- return null
-}
-
-export function findWebpackConfig (root: string) {
- const webpackConfigPath = findUp.sync('webpack.config.js', { cwd: root })
-
- if (webpackConfigPath) {
- return webpackConfigPath
- }
-
- const packageJsonIterator = createFindPackageJsonIterator(root)
-
- const { success, payload } = packageJsonIterator.map(({ scripts }, packageJsonPath) => {
- if (!scripts) {
- return { success: false }
- }
-
- for (const script of Object.values(scripts)) {
- const webpackConfigRelativePath = extractWebpackConfigPathFromScript(
- script,
- )
-
- if (webpackConfigRelativePath) {
- const directoryRoot = path.resolve(packageJsonPath, '..')
- const webpackConfigPath = path.resolve(
- directoryRoot,
- webpackConfigRelativePath,
- )
-
- return {
- success: true,
- payload: { webpackConfigPath },
- }
- }
- }
-
- return { success: false }
- })
-
- return success ? payload?.webpackConfigPath : null
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/vue/index.ts b/npm/create-cypress-tests/src/component-testing/templates/vue/index.ts
deleted file mode 100644
index 512f4ff6ee8d..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/vue/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { Template } from '../Template'
-import { VueCliTemplate } from './vueCli'
-import { VueWebpackTemplate } from './vueWebpackFile'
-
-export const vueTemplates: Record> = {
- webpack: VueWebpackTemplate,
- 'vue-cli': VueCliTemplate,
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/vue/vueCli.test.ts b/npm/create-cypress-tests/src/component-testing/templates/vue/vueCli.test.ts
deleted file mode 100644
index 29bb76b76d2f..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/vue/vueCli.test.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { expect } from 'chai'
-import mockFs from 'mock-fs'
-import { snapshotPluginsAstCode } from '../../../test-utils'
-import { VueCliTemplate } from './vueCli'
-
-describe('vue webpack-file install template', () => {
- beforeEach(mockFs.restore)
-
- it('resolves webpack.config.js', () => {
- mockFs({
- '/package.json': JSON.stringify({
- 'devDependencies': {
- '@vue/cli-plugin-babel': '~4.5.0',
- '@vue/cli-plugin-eslint': '~4.5.0',
- '@vue/cli-plugin-router': '~4.5.0',
- '@vue/cli-service': '~4.5.0',
- },
- }),
- })
-
- const { success } = VueCliTemplate.test('/')
-
- expect(success).to.equal(true)
- })
-
- it('returns success:false if vue-cli-service is not installed', () => {
- mockFs({
- '/package.json': JSON.stringify({
- 'devDependencies': {
- 'webpack': '*',
- 'vue': '2.x',
- },
- }),
- })
-
- const { success } = VueCliTemplate.test('/')
-
- expect(success).to.equal(false)
- })
-
- it('correctly generates plugins for vue-cli-service', () => {
- snapshotPluginsAstCode(VueCliTemplate)
- })
-})
diff --git a/npm/create-cypress-tests/src/component-testing/templates/vue/vueCli.ts b/npm/create-cypress-tests/src/component-testing/templates/vue/vueCli.ts
deleted file mode 100644
index f920c85fa89a..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/vue/vueCli.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import * as babel from '@babel/core'
-import { scanFSForAvailableDependency } from '../../../findPackageJson'
-import { Template } from '../Template'
-
-export const VueCliTemplate: Template = {
- message:
- 'It looks like you are using vue-cli-service to run and build an application.',
- getExampleUrl: () => 'https://github.com/cypress-io/cypress/tree/develop/npm/vue/examples/cli',
- recommendedComponentFolder: 'src',
- dependencies: ['@cypress/webpack-dev-server'],
- getPluginsCodeAst: () => {
- return {
- requiresReturnConfig: true,
- RequireAst: babel.template.ast([
- 'const { startDevServer } = require("@cypress/webpack-dev-server")',
- `const webpackConfig = require("@vue/cli-service/webpack.config.js")`,
- ].join('\n')),
- IfComponentTestingPluginsAst: babel.template.ast([
- `on('dev-server:start', (options) => startDevServer({ options, webpackConfig }))`,
- ].join('\n'), { preserveComments: true }),
- }
- },
- test: (root) => {
- const hasVueCliService = scanFSForAvailableDependency(root, { '@vue/cli-service': '>=4' })
-
- return {
- success: hasVueCliService,
- }
- },
-}
diff --git a/npm/create-cypress-tests/src/component-testing/templates/vue/vueWebpackFile.test.ts b/npm/create-cypress-tests/src/component-testing/templates/vue/vueWebpackFile.test.ts
deleted file mode 100644
index e0b058958ef2..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/vue/vueWebpackFile.test.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import { expect } from 'chai'
-import mockFs from 'mock-fs'
-import { snapshotPluginsAstCode } from '../../../test-utils'
-import { VueWebpackTemplate } from './vueWebpackFile'
-
-describe('vue webpack-file install template', () => {
- beforeEach(mockFs.restore)
-
- it('resolves webpack.config.js', () => {
- mockFs({
- '/webpack.config.js': 'module.exports = { }',
- })
-
- const { success, payload } = VueWebpackTemplate.test(process.cwd())
-
- expect(success).to.equal(true)
- expect(payload?.webpackConfigPath).to.equal('/webpack.config.js')
- })
-
- it('finds the closest package.json and tries to fetch webpack config path from scrips', () => {
- mockFs({
- '/configs/webpack.js': 'module.exports = { }',
- '/package.json': JSON.stringify({
- scripts: {
- build: 'webpack --config configs/webpack.js',
- },
- }),
- })
-
- const { success, payload } = VueWebpackTemplate.test(process.cwd())
-
- expect(success).to.equal(true)
- expect(payload?.webpackConfigPath).to.equal('/configs/webpack.js')
- })
-
- it('looks for package.json in the upper folder', () => {
- mockFs({
- '/some/deep/folder/withFile': 'test',
- '/somewhere/configs/webpack.js': 'module.exports = { }',
- '/package.json': JSON.stringify({
- scripts: {
- build: 'webpack --config somewhere/configs/webpack.js',
- },
- }),
- })
-
- const { success, payload } = VueWebpackTemplate.test(
- '/some/deep/folder',
- )
-
- expect(success).to.equal(true)
- expect(payload?.webpackConfigPath).to.equal('/somewhere/configs/webpack.js')
- })
-
- it('returns success:false if cannot find webpack config', () => {
- mockFs({
- '/a.js': '1',
- '/b.js': '2',
- })
-
- const { success, payload } = VueWebpackTemplate.test('/')
-
- expect(success).to.equal(false)
- expect(payload).to.equal(undefined)
- })
-
- it('correctly generates plugins config when webpack config path is missing', () => {
- snapshotPluginsAstCode(VueWebpackTemplate)
- })
-
- it('correctly generates plugins config when webpack config path is provided', () => {
- snapshotPluginsAstCode(VueWebpackTemplate, { webpackConfigPath: '/build/webpack.config.js' })
- })
-})
diff --git a/npm/create-cypress-tests/src/component-testing/templates/vue/vueWebpackFile.ts b/npm/create-cypress-tests/src/component-testing/templates/vue/vueWebpackFile.ts
deleted file mode 100644
index 106145b4067c..000000000000
--- a/npm/create-cypress-tests/src/component-testing/templates/vue/vueWebpackFile.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import * as babel from '@babel/core'
-import path from 'path'
-import { Template } from '../Template'
-import { findWebpackConfig } from '../templateUtils'
-
-export const VueWebpackTemplate: Template<{ webpackConfigPath: string }> = {
- message:
- 'It looks like you have custom `webpack.config.js`. We can use it to bundle the components for testing.',
- getExampleUrl: () => 'https://github.com/cypress-io/cypress/tree/develop/npm/vue/examples/cli',
- recommendedComponentFolder: 'cypress/component',
- dependencies: ['@cypress/webpack-dev-server'],
- getPluginsCodeAst: (payload, { cypressProjectRoot }) => {
- const includeWarnComment = !payload
- const webpackConfigPath = payload
- ? path.relative(cypressProjectRoot, payload.webpackConfigPath)
- : './webpack.config.js'
-
- return {
- requiresReturnConfig: true,
- RequireAst: babel.template.ast([
- 'const { startDevServer } = require("@cypress/webpack-dev-server")',
-
- `const webpackConfig = require("${webpackConfigPath}")`,
- includeWarnComment
- ? '// TODO replace with valid webpack config path'
- : '',
- ].join('\n'), { preserveComments: true }),
- IfComponentTestingPluginsAst: babel.template.ast([
- `on('dev-server:start', (options) => startDevServer({ options, webpackConfig }))`,
- ].join('\n')),
- }
- },
- test: (root) => {
- const webpackConfigPath = findWebpackConfig(root)
-
- return webpackConfigPath ? {
- success: true,
- payload: { webpackConfigPath },
- } : {
- success: false,
- }
- },
-}
diff --git a/npm/create-cypress-tests/src/component-testing/versions.ts b/npm/create-cypress-tests/src/component-testing/versions.ts
deleted file mode 100644
index 734122ff5fe2..000000000000
--- a/npm/create-cypress-tests/src/component-testing/versions.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export const MIN_SUPPORTED_VERSION = {
- 'react-scripts': '^=3.x || ^=4.x',
- next: '^=9.x || ^=10.x',
-}
diff --git a/npm/create-cypress-tests/src/findPackageJson.ts b/npm/create-cypress-tests/src/findPackageJson.ts
deleted file mode 100644
index 81858d319c95..000000000000
--- a/npm/create-cypress-tests/src/findPackageJson.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import path from 'path'
-import fs from 'fs'
-import findUp from 'find-up'
-import { validateSemverVersion } from './utils'
-
-type PackageJsonLike = {
- name?: string
- scripts?: Record
- dependencies?: Record
- devDependencies?: Record
- [key: string]: unknown
-}
-
-type FindPackageJsonResult =
- | {
- packageData: PackageJsonLike
- filename: string
- done: false
- }
- | {
- packageData: undefined
- filename: undefined
- done: true
- }
-
-/**
- * Return the parsed package.json that we find in a parent folder.
- *
- * @returns {Object} Value, filename and indication if the iteration is done.
- */
-export function createFindPackageJsonIterator (rootPath = process.cwd()) {
- function scanForPackageJson (cwd: string): FindPackageJsonResult {
- const packageJsonPath = findUp.sync('package.json', { cwd })
-
- if (!packageJsonPath) {
- return {
- packageData: undefined,
- filename: undefined,
- done: true,
- }
- }
-
- const packageData = JSON.parse(
- fs.readFileSync(packageJsonPath, {
- encoding: 'utf-8',
- }),
- )
-
- return {
- packageData,
- filename: packageJsonPath,
- done: false,
- }
- }
-
- return {
- map: (
- cb: (
- data: PackageJsonLike,
- packageJsonPath: string,
- ) => { success: boolean, payload?: TPayload },
- ) => {
- let stepPathToScan = rootPath
-
- // eslint-disable-next-line
- while (true) {
- const result = scanForPackageJson(stepPathToScan)
-
- if (result.done) {
- // didn't find the package.json
- return { success: false }
- }
-
- if (result.packageData) {
- const cbResult = cb(result.packageData, result.filename)
-
- if (cbResult.success) {
- return { success: true, payload: cbResult.payload }
- }
- }
-
- const nextStepPathToScan = path.resolve(stepPathToScan, '..')
-
- if (nextStepPathToScan === stepPathToScan) {
- // we are at the root. Give up
- return { success: false }
- }
-
- stepPathToScan = nextStepPathToScan
- }
- },
- }
-}
-
-export function scanFSForAvailableDependency (cwd: string, lookingForDeps: Record) {
- const { success } = createFindPackageJsonIterator(cwd)
- .map(({ dependencies, devDependencies }, path) => {
- if (!dependencies && !devDependencies) {
- return { success: false }
- }
-
- return {
- success: Object.entries({ ...dependencies, ...devDependencies })
- .some(([dependency, version]) => {
- return (
- Boolean(lookingForDeps[dependency])
- && validateSemverVersion(version, lookingForDeps[dependency] as string, dependency)
- )
- }),
- }
- })
-
- return success
-}
-
-export type PackageJsonIterator = ReturnType
diff --git a/npm/create-cypress-tests/src/index.ts b/npm/create-cypress-tests/src/index.ts
deleted file mode 100644
index 9e6e68e3f4ec..000000000000
--- a/npm/create-cypress-tests/src/index.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env node
-import { program } from 'commander'
-import { main } from './main'
-import { version } from '../package.json'
-
-program
-.option('--ignore-examples', 'Ignore generating example tests and fixtures by creating one ready-to-fill spec file')
-.option('--use-npm', 'Use npm even if yarn is available')
-.option('--ignore-ts', 'Ignore typescript if available')
-.option('--component-tests', 'Run component testing installation without asking')
-
-program.version(version, '-v --version')
-program.parse(process.argv)
-
-main({
- useNpm: program.useNpm,
- ignoreTs: program.ignoreTs,
- ignoreExamples: Boolean(program.ignoreExamples),
- setupComponentTesting: program.componentTests,
-}).catch(console.error)
diff --git a/npm/create-cypress-tests/src/initialTemplate.ts b/npm/create-cypress-tests/src/initialTemplate.ts
deleted file mode 100644
index 332df33e3899..000000000000
--- a/npm/create-cypress-tests/src/initialTemplate.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import path from 'path'
-import fs from 'fs-extra'
-
-const INITIAL_TEMPLATE_PATH = path.resolve(__dirname, '..', 'initial-template')
-
-export async function getInitialSupportFilesPaths () {
- return (
- await fs.readdir(path.join(INITIAL_TEMPLATE_PATH, 'support'))
- ).map((filename) => path.join(INITIAL_TEMPLATE_PATH, 'support', filename))
-}
-
-export function getInitialPluginsFilePath () {
- return path.join(INITIAL_TEMPLATE_PATH, 'plugins', 'index.js')
-}
-
-export function getInitialTsConfigPath () {
- return path.join(INITIAL_TEMPLATE_PATH, 'tsconfig.json')
-}
diff --git a/npm/create-cypress-tests/src/installCypress.ts b/npm/create-cypress-tests/src/installCypress.ts
deleted file mode 100644
index 9abd21345b52..000000000000
--- a/npm/create-cypress-tests/src/installCypress.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-import fs from 'fs-extra'
-import findUp from 'find-up'
-import path from 'path'
-import { installDependency } from './utils'
-import chalk from 'chalk'
-import ora from 'ora'
-import * as initialTemplate from './initialTemplate'
-
-type InstallCypressOpts = {
- useYarn: boolean
- useTypescript: boolean
- ignoreExamples: boolean
-}
-
-async function copyFiles ({ ignoreExamples, useTypescript }: InstallCypressOpts) {
- let fileSpinner = ora('Creating config files').start()
-
- await fs.outputFile(path.resolve(process.cwd(), useTypescript ? 'cypress.config.ts' : 'cypress.config.js'), useTypescript ? `export default {}` : `module.exports = {}\n`)
- await fs.copy(
- initialTemplate.getInitialPluginsFilePath(),
- path.resolve('cypress', 'plugins/index.js'),
- )
-
- const supportFiles: string[] = await initialTemplate.getInitialSupportFilesPaths()
-
- await Promise.all(
- supportFiles.map((supportFilePath) => {
- const newSupportFilePath = path.resolve('cypress', 'support', path.basename(supportFilePath))
-
- return fs.copy(supportFilePath, newSupportFilePath)
- }),
- )
-
- if (useTypescript) {
- await fs.copy(initialTemplate.getInitialTsConfigPath(), path.resolve('cypress', 'tsconfig.json'))
- }
-
- // TODO think about better approach
- if (ignoreExamples) {
- const dummySpec = [
- 'describe("Spec", () => {',
- '',
- '})',
- '',
- ].join('\n')
-
- const specFileName = useTypescript ? 'spec.cy.ts' : 'spec.cy.js'
- const specFileToCreate = path.resolve('cypress', 'e2e', specFileName)
-
- await fs.outputFile(specFileToCreate, dummySpec)
- console.log(`In order to ignore examples a spec file ${chalk.green(path.relative(process.cwd(), specFileToCreate))}.`)
- }
-
- fileSpinner.succeed()
-}
-
-export async function findInstalledOrInstallCypress (options: InstallCypressOpts) {
- const configFile = options.useTypescript ? 'cypress.config.ts' : 'cypress.config.js'
- let cypressConfigPath = await findUp(configFile)
-
- if (!cypressConfigPath) {
- await installDependency('cypress', options)
- await copyFiles(options)
-
- cypressConfigPath = await findUp(configFile)
- }
-
- if (!cypressConfigPath) {
- throw new Error('Unexpected error during cypress installation.')
- }
-
- const config = await import(cypressConfigPath)
-
- return {
- cypressConfigPath,
- config: config.default,
- }
-}
diff --git a/npm/create-cypress-tests/src/main.test.ts b/npm/create-cypress-tests/src/main.test.ts
deleted file mode 100644
index 3b3a81eefa1b..000000000000
--- a/npm/create-cypress-tests/src/main.test.ts
+++ /dev/null
@@ -1,170 +0,0 @@
-import { expect, use } from 'chai'
-import path from 'path'
-import sinon, { SinonStub, SinonSpy, SinonSpyCallApi } from 'sinon'
-import mockFs from 'mock-fs'
-import fsExtra from 'fs-extra'
-import { main } from './main'
-import sinonChai from 'sinon-chai'
-import childProcess from 'child_process'
-
-use(sinonChai)
-
-function mockFsWithInitialTemplate (...args: Parameters) {
- const [fsConfig, options] = args
-
- mockFs({
- ...fsConfig,
- // @ts-expect-error Load required template files
- [path.resolve(__dirname, '..', 'initial-template')]: mockFs.load(path.resolve(__dirname, '..', 'initial-template')),
- }, options)
-}
-
-function someOfSpyCallsIncludes (spy: any, logPart: string) {
- return spy.getCalls().some(
- (spy: SinonSpyCallApi) => {
- return spy.args.some((callArg) => typeof callArg === 'string' && callArg.includes(logPart))
- },
- )
-}
-
-describe('create-cypress-tests', () => {
- let promptSpy: SinonStub | null = null
- let logSpy: SinonSpy | null = null
- let errorSpy: SinonSpy | null = null
- let execStub: SinonStub | null = null
- let fsCopyStub: SinonStub | null = null
- let processExitStub: SinonStub | null = null
-
- beforeEach(() => {
- logSpy = sinon.spy(global.console, 'log')
- errorSpy = sinon.spy(global.console, 'error')
- // @ts-ignore
- execStub = sinon.stub(childProcess, 'exec').callsFake((command, callback) => callback())
- // @ts-ignore
- fsCopyStub = sinon.stub(fsExtra, 'copy').returns(Promise.resolve())
- processExitStub = sinon.stub(process, 'exit').callsFake(() => {
- throw new Error('process.exit should not be called')
- })
- })
-
- afterEach(() => {
- mockFs.restore()
- logSpy?.restore()
- promptSpy?.restore()
- execStub?.restore()
- fsCopyStub?.restore()
- processExitStub?.restore()
- execStub?.restore()
- errorSpy?.restore()
- })
-
- it('Install cypress if no config found', async () => {
- mockFsWithInitialTemplate({
- '/package.json': JSON.stringify({ }),
- })
-
- await main({ useNpm: false, ignoreTs: false, ignoreExamples: false, setupComponentTesting: false })
-
- expect(execStub).calledWith('yarn add cypress --dev')
- })
-
- it('Uses npm if yarn is not available', async () => {
- execStub
- ?.onFirstCall().callsFake((command, callback) => callback('yarn is not available'))
- ?.onSecondCall().callsFake((command, callback) => callback())
- ?.onThirdCall().callsFake((command, callback) => callback())
-
- mockFsWithInitialTemplate({
- '/package.json': JSON.stringify({ }),
- })
-
- await main({ useNpm: false, ignoreTs: false, ignoreExamples: false, setupComponentTesting: false })
- expect(execStub).calledWith('npm install -D cypress')
- })
-
- it('Uses npm if --use-npm was provided', async () => {
- mockFsWithInitialTemplate({
- '/package.json': JSON.stringify({ }),
- })
-
- await main({ useNpm: true, ignoreTs: false, ignoreExamples: false, setupComponentTesting: false })
-
- expect(execStub).calledWith('npm install -D cypress')
- })
-
- it('Prints correct commands helper for npm', async () => {
- mockFsWithInitialTemplate({
- '/package.json': JSON.stringify({ }),
- })
-
- await main({ useNpm: true, ignoreTs: false, ignoreExamples: false, setupComponentTesting: false })
- expect(someOfSpyCallsIncludes(logSpy, 'npx cypress open')).to.be.true
- })
-
- it('Prints correct commands helper for yarn', async () => {
- mockFsWithInitialTemplate({
- '/package.json': JSON.stringify({ }),
- })
-
- await main({ useNpm: false, ignoreTs: false, ignoreExamples: false, setupComponentTesting: false })
- expect(someOfSpyCallsIncludes(logSpy, 'yarn cypress open')).to.be.true
- })
-
- it('Fails if git repository have untracked or uncommitted files', async () => {
- mockFsWithInitialTemplate({
- '/package.json': JSON.stringify({ }),
- })
-
- execStub?.callsFake((_, callback) => callback(null, { stdout: 'test' }))
- processExitStub?.callsFake(() => {})
-
- await main({ useNpm: true, ignoreTs: false, ignoreExamples: false, setupComponentTesting: false })
-
- expect(
- someOfSpyCallsIncludes(errorSpy, 'This repository has untracked files or uncommitted changes.'),
- ).to.equal(true)
-
- expect(processExitStub).to.be.called
- })
-
- context('e2e fs tests', () => {
- const e2eTestOutputPath = path.resolve(__dirname, 'test-output')
-
- beforeEach(async () => {
- fsCopyStub?.restore()
- mockFs.restore()
- sinon.stub(process, 'cwd').returns(e2eTestOutputPath)
-
- await fsExtra.remove(e2eTestOutputPath)
- await fsExtra.mkdir(e2eTestOutputPath)
- })
-
- it('Copies plugins and support files', async () => {
- await fsExtra.outputFile(
- path.join(e2eTestOutputPath, 'package.json'),
- JSON.stringify({ name: 'test' }, null, 2),
- )
-
- await main({ useNpm: true, ignoreTs: false, ignoreExamples: false, setupComponentTesting: false })
-
- expect(await fsExtra.pathExists(path.resolve(e2eTestOutputPath, 'cypress', 'plugins', 'index.js'))).to.equal(true)
- expect(await fsExtra.pathExists(path.resolve(e2eTestOutputPath, 'cypress', 'support', 'e2e.js'))).to.equal(true)
- expect(await fsExtra.pathExists(path.resolve(e2eTestOutputPath, 'cypress', 'support', 'commands.js'))).to.equal(true)
- expect(await fsExtra.pathExists(path.resolve(e2eTestOutputPath, 'cypress.config.ts'))).to.equal(true)
- })
-
- it('Copies tsconfig if typescript is installed', async () => {
- await fsExtra.outputFile(
- path.join(e2eTestOutputPath, 'package.json'),
- JSON.stringify({
- name: 'test-typescript',
- dependencies: { typescript: '^4.0.0' },
- }, null, 2),
- )
-
- await main({ useNpm: false, ignoreTs: false, ignoreExamples: false, setupComponentTesting: false })
- await fsExtra.pathExists(path.resolve(e2eTestOutputPath, 'cypress', 'tsconfig.json'))
- console.log(path.resolve(e2eTestOutputPath, 'cypress', 'tsconfig.json'))
- })
- })
-})
diff --git a/npm/create-cypress-tests/src/main.ts b/npm/create-cypress-tests/src/main.ts
deleted file mode 100644
index fc28840559e6..000000000000
--- a/npm/create-cypress-tests/src/main.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-import fs from 'fs'
-import findUp from 'find-up'
-import chalk from 'chalk'
-import util from 'util'
-import inquirer from 'inquirer'
-import { initComponentTesting } from './component-testing/init-component-testing'
-import { exec } from 'child_process'
-import { scanFSForAvailableDependency } from './findPackageJson'
-import { findInstalledOrInstallCypress } from './installCypress'
-
-type MainArgv = {
- useNpm: boolean
- ignoreTs: boolean
- ignoreExamples: boolean
- setupComponentTesting: boolean
-}
-
-async function getGitStatus () {
- const execAsync = util.promisify(exec)
-
- try {
- let { stdout } = await execAsync(`git status --porcelain`)
-
- console.log(stdout)
-
- return stdout.trim()
- } catch (e) {
- return ''
- }
-}
-
-async function shouldUseYarn () {
- const execAsync = util.promisify(exec)
-
- return execAsync('yarn --version')
- .then(() => true)
- .catch(() => false)
-}
-
-function shouldUseTypescript () {
- return scanFSForAvailableDependency(process.cwd(), { typescript: '*' })
-}
-
-async function askForComponentTesting () {
- const { shouldSetupComponentTesting } = await inquirer.prompt({
- type: 'confirm',
- name: 'shouldSetupComponentTesting',
- message: `Do you want to setup ${chalk.cyan('component testing')}? ${chalk.grey('You can do this later by rerunning this command')}.`,
- })
-
- return shouldSetupComponentTesting
-}
-
-function printCypressCommandsHelper (options: { shouldSetupComponentTesting: boolean, useYarn: boolean }) {
- const printCommand = (command: string, description: string) => {
- const displayedRunner = options.useYarn ? 'yarn' : 'npx'
-
- console.log()
- console.log(chalk.cyan(` ${displayedRunner} ${command}`))
- console.log(` ${description}`)
- }
-
- printCommand('cypress open', 'Opens cypress local development app.')
- printCommand('cypress run', 'Runs tests in headless mode.')
-
- if (options.shouldSetupComponentTesting) {
- printCommand('cypress open --component', 'Opens Cypress component testing interactive mode.')
- printCommand('cypress run-ct', 'Runs all Cypress component testing suites.')
- }
-}
-
-export async function main ({ useNpm, ignoreTs, setupComponentTesting, ignoreExamples }: MainArgv) {
- const rootPackageJsonPath = await findUp('package.json')
- const useYarn = useNpm === true ? false : await shouldUseYarn()
- const useTypescript = ignoreTs ? false : shouldUseTypescript()
-
- if (!rootPackageJsonPath) {
- console.log(`${chalk.bold.red(`It looks like you are running cypress installation wizard outside of npm module.`)}\nIf you would like to setup a new project for cypress tests please run the ${chalk.inverse(useNpm ? ' npm init ' : ' yarn init ')} first.`)
- process.exit(1)
- }
-
- const { name = 'unknown', version = '0.0.0' } = JSON.parse(fs.readFileSync(rootPackageJsonPath).toString())
-
- console.log(`Running ${chalk.green('cypress 🌲')} installation wizard for ${chalk.cyan(`${name}@${version}`)}`)
-
- const gitStatus = await getGitStatus()
-
- if (gitStatus) {
- console.error(`\n${chalk.bold.red('This repository has untracked files or uncommitted changes.')}\nThis command will ${chalk.cyan('make changes in the codebase')}, so please remove untracked files, stash or commit any changes, and try again.`)
- process.exit(1)
- }
-
- const { config, cypressConfigPath } = await findInstalledOrInstallCypress({ useYarn, useTypescript, ignoreExamples })
- const shouldSetupComponentTesting = setupComponentTesting ?? await askForComponentTesting()
-
- if (shouldSetupComponentTesting) {
- await initComponentTesting({ config, cypressConfigPath, useYarn })
- }
-
- console.log(`\n👍 Success! Cypress is installed and ready to run tests.`)
- printCypressCommandsHelper({ useYarn, shouldSetupComponentTesting })
-
- console.log(`\nHappy testing with ${chalk.green('cypress.io')} 🌲\n`)
-}
-
-export { scanFSForAvailableDependency }
diff --git a/npm/create-cypress-tests/src/test-utils.ts b/npm/create-cypress-tests/src/test-utils.ts
deleted file mode 100644
index 6021690678b9..000000000000
--- a/npm/create-cypress-tests/src/test-utils.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import * as babel from '@babel/core'
-import snapshot from 'snap-shot-it'
-import mockFs from 'mock-fs'
-import { SinonSpyCallApi } from 'sinon'
-import { createTransformPluginsFileBabelPlugin } from './component-testing/babel/babelTransform'
-import { Template } from './component-testing/templates/Template'
-
-export function someOfSpyCallsIncludes (spy: any, logPart: string) {
- return spy.getCalls().some(
- (spy: SinonSpyCallApi) => {
- return spy.args.some((callArg) => typeof callArg === 'string' && callArg.includes(logPart))
- },
- )
-}
-
-export function snapshotPluginsAstCode (template: Template, payload?: T) {
- mockFs.restore()
- const code = [
- 'const something = require("something")',
- 'module.exports = (on) => {',
- '};',
- ].join('\n')
-
- const babelPlugin = createTransformPluginsFileBabelPlugin(template.getPluginsCodeAst(payload ?? null, { cypressProjectRoot: '/' }))
- const output = babel.transformSync(code, {
- plugins: [babelPlugin],
- })
-
- if (!output || !output.code) {
- throw new Error('Babel transform output is empty.')
- }
-
- snapshot(output.code)
-}
diff --git a/npm/create-cypress-tests/src/utils.ts b/npm/create-cypress-tests/src/utils.ts
deleted file mode 100644
index e79055e60283..000000000000
--- a/npm/create-cypress-tests/src/utils.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import semver from 'semver'
-import chalk from 'chalk'
-import ora from 'ora'
-import util from 'util'
-import { exec } from 'child_process'
-
-/**
- * Compare available version range with the provided version from package.json
- * @param packageName Package name used to display a helper message to user.
- */
-export function validateSemverVersion (
- version: string,
- allowedVersionRange: string,
- packageName?: string,
-) {
- let isValid: boolean
-
- try {
- const minAvailableVersion = semver.minVersion(version)?.raw
-
- isValid = Boolean(
- minAvailableVersion &&
- semver.satisfies(minAvailableVersion, allowedVersionRange),
- )
- } catch (e) {
- // handle not semver versions like "latest", "git:" or "file:"
- isValid = false
- }
-
- if (!isValid && packageName) {
- const packageNameSymbol = chalk.green(packageName)
-
- console.warn(
- `It seems like you are using ${packageNameSymbol} with version ${chalk.bold(
- version,
- )}, however we support only ${packageNameSymbol} projects with version ${chalk.bold(
- allowedVersionRange,
- )}. \n`,
- )
- }
-
- return isValid
-}
-
-export async function installDependency (name: string, options: { useYarn: boolean}) {
- const commandToRun = options.useYarn ? `yarn add ${name} --dev` : `npm install -D ${name}`
- let cliSpinner = ora(`Installing ${name} ${chalk.gray(`(${commandToRun})`)}`).start()
-
- try {
- // do this inside function for test stubbing
- const execAsync = util.promisify(exec)
-
- await execAsync(commandToRun)
- } catch (e) {
- cliSpinner.fail(`Can not install ${name} using ${chalk.inverse(commandToRun)})}`)
- console.log(e)
-
- process.exit(1)
- }
-
- cliSpinner.succeed()
-}
-
-export async function prettifyCode (finalCode?: string | null) {
- try {
- const maybePrettier = require('prettier')
-
- if (maybePrettier && maybePrettier.format) {
- finalCode = maybePrettier.format(finalCode, { parser: 'babel' })
- }
- } catch (e) {
- return null
- } finally {
- return finalCode
- }
-}
diff --git a/npm/create-cypress-tests/tsconfig.json b/npm/create-cypress-tests/tsconfig.json
deleted file mode 100644
index 5cf13aaaaa09..000000000000
--- a/npm/create-cypress-tests/tsconfig.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "compilerOptions": {
- "outDir": "./dist",
- "rootDir": ".",
- "esModuleInterop": true,
- "allowJs": true,
- "allowSyntheticDefaultImports": true,
- "declaration": true,
- "moduleResolution": "node",
- "strict": true,
- "strictNullChecks": true,
- "resolveJsonModule": true,
- "module": "CommonJS",
- "target": "ES2018",
- "types": [
- "node",
- ],
- "lib": [
- "ES2018"
- ],
- "noImplicitAny": true
- },
- "exclude": [
- "./src/**/*.test.ts",
- "node_modules"
- ],
- "include": [
- "./src/**/*.ts",
- ]
-}
diff --git a/npm/create-cypress-tests/tsconfig.test.json b/npm/create-cypress-tests/tsconfig.test.json
deleted file mode 100644
index df01205d9a40..000000000000
--- a/npm/create-cypress-tests/tsconfig.test.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "noEmit": true,
- "types": [
- "mocha"
- ]
- },
- "include": [
- "./src/**/*.test.ts"
- ]
-}
\ No newline at end of file
diff --git a/package.json b/package.json
index 12c90c4de0ef..93e19fa435b0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cypress",
- "version": "13.6.0",
+ "version": "13.6.1",
"description": "Cypress is a next generation front end testing tool built for the modern web",
"private": true,
"scripts": {
@@ -15,7 +15,7 @@
"binary-package": "cross-env NODE_OPTIONS=--max_old_space_size=8192 node ./scripts/binary.js package",
"check-binary-on-cdn": "node ./scripts/binary.js checkIfBinaryExistsOnCdn",
"build": "lerna run build --stream && lerna run build-cli --stream",
- "build-prod": "lerna run build-prod --stream --ignore create-cypress-tests && node ./cli/scripts/post-build.js && lerna run build-prod --stream --scope create-cypress-tests --scope",
+ "build-prod": "lerna run build-prod --stream && node ./cli/scripts/post-build.js && lerna run build-prod --stream --scope",
"build-v8-snapshot-dev": "node --max-old-space-size=8192 tooling/v8-snapshot/scripts/setup-v8-snapshot-in-cypress.js --env=dev",
"build-v8-snapshot-prod": "node --max-old-space-size=8192 tooling/v8-snapshot/scripts/setup-v8-snapshot-in-cypress.js",
"check-node-version": "node scripts/check-node-version.js",
@@ -162,7 +162,7 @@
"fs-extra": "9.1.0",
"getenv": "^1.0.0",
"glob": "7.1.6",
- "got": "11.8.5",
+ "got": "11.8.6",
"graphql": "^15.5.1",
"graphql-executor": "0.0.23",
"gulp": "4.0.2",
diff --git a/packages/config/__snapshots__/validation.spec.ts.js b/packages/config/__snapshots__/validation.spec.ts.js
index 210fc4785340..491f2c5e08ff 100644
--- a/packages/config/__snapshots__/validation.spec.ts.js
+++ b/packages/config/__snapshots__/validation.spec.ts.js
@@ -36,7 +36,7 @@ exports['invalid retry object'] = {
'value': {
'fakeMode': 1,
},
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'type': 'an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls',
}
exports['not qualified url'] = {
@@ -263,233 +263,138 @@ exports['invalid upper bound'] = {
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with invalid strategy 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'foo',
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalStrategy',
+ 'value': 'foo',
+ 'type': 'one of "detect-flake-but-always-fail", "detect-flake-and-pass-on-threshold"',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with invalid strategy w/ other options (valid) 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'runMode': true,
- 'openMode': false,
- 'experimentalStrategy': 'bar',
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
-}
-
-exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-but-always-fail: valid strategy w/ other invalid options with experiment 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'runMode': 1,
- 'openMode': 0,
- 'experimentalStrategy': 'detect-flake-but-always-fail',
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalStrategy',
+ 'value': 'bar',
+ 'type': 'one of "detect-flake-but-always-fail", "detect-flake-and-pass-on-threshold"',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-but-always-fail: maxRetries is negative 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-but-always-fail',
- 'experimentalOptions': {
- 'maxRetries': -2,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.maxRetries',
+ 'value': -2,
+ 'type': 'a positive whole number greater than or equals 1 or null',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-but-always-fail: maxRetries is 0 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-but-always-fail',
- 'experimentalOptions': {
- 'maxRetries': 0,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
-}
-
-exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-but-always-fail: maxRetries is floating 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-but-always-fail',
- 'experimentalOptions': {
- 'maxRetries': 3.5,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
-}
-
-exports['config/src/validation .isValidRetriesConfig experimental options fails with experimentalStrategy is "detect-flake-but-always-fail" with only "maxRetries" in "experimentalOptions" 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-but-always-fail',
- 'experimentalOptions': {
- 'maxRetries': 4,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
-}
-
-exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold: valid strategy w/ other invalid options with experiment 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'runMode': 1,
- 'openMode': 0,
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.maxRetries',
+ 'value': 0,
+ 'type': 'a positive whole number greater than or equals 1 or null',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold: maxRetries is negative 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- 'experimentalOptions': {
- 'maxRetries': -2,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.maxRetries',
+ 'value': -2,
+ 'type': 'a positive whole number greater than or equals 1 or null',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold: maxRetries is 0 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- 'experimentalOptions': {
- 'maxRetries': 0,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.maxRetries',
+ 'value': 0,
+ 'type': 'a positive whole number greater than or equals 1 or null',
}
-exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold: maxRetries is floating 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- 'experimentalOptions': {
- 'maxRetries': 3.5,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-but-always-fail: maxRetries is floating 1'] = {
+ 'key': 'mockConfigKey.experimentalOptions.maxRetries',
+ 'value': 3.5,
+ 'type': 'a positive whole number greater than or equals 1 or null',
}
-exports['config/src/validation .isValidRetriesConfig experimental options fails with experimentalStrategy is "detect-flake-and-pass-on-threshold" with only "maxRetries" in "experimentalOptions" 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- 'experimentalOptions': {
- 'maxRetries': 4,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold: maxRetries is floating 1'] = {
+ 'key': 'mockConfigKey.experimentalOptions.maxRetries',
+ 'value': 3.5,
+ 'type': 'a positive whole number greater than or equals 1 or null',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold passesRequired is negative 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- 'experimentalOptions': {
- 'maxRetries': 1,
- 'passesRequired': -4,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.passesRequired',
+ 'value': -4,
+ 'type': 'a positive whole number less than or equals to maxRetries',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold passesRequired is 0 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- 'experimentalOptions': {
- 'maxRetries': 1,
- 'passesRequired': 0,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.passesRequired',
+ 'value': 0,
+ 'type': 'a positive whole number less than or equals to maxRetries',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold passesRequired is floating 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- 'experimentalOptions': {
- 'maxRetries': 1,
- 'passesRequired': 3.5,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.passesRequired',
+ 'value': 3.5,
+ 'type': 'a positive whole number less than or equals to maxRetries',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold provides passesRequired without maxRetries 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- 'experimentalOptions': {
- 'passesRequired': 3,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.maxRetries',
+ 'type': 'a positive whole number greater than or equals 1 or null',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold provides passesRequired that is greater than maxRetries 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- 'experimentalOptions': {
- 'maxRetries': 3,
- 'passesRequired': 5,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.passesRequired',
+ 'value': 5,
+ 'type': 'a positive whole number less than or equals to maxRetries',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold provides stopIfAnyPassed option 1'] = {
- 'key': 'mockConfigKey',
+ 'key': 'mockConfigKey.experimentalOptions',
'value': {
- 'experimentalStrategy': 'detect-flake-and-pass-on-threshold',
- 'experimentalOptions': {
- 'maxRetries': 3,
- 'stopIfAnyPassed': true,
- },
+ 'maxRetries': 3,
+ 'passesRequired': 2,
+ 'stopIfAnyPassed': true,
},
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'type': 'an object with keys maxRetries, passesRequired',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-but-always-fail provides passesRequired option 1'] = {
- 'key': 'mockConfigKey',
+ 'key': 'mockConfigKey.experimentalOptions',
'value': {
- 'experimentalStrategy': 'detect-flake-but-always-fail',
- 'experimentalOptions': {
- 'maxRetries': 3,
- 'passesRequired': 2,
- },
+ 'maxRetries': 3,
+ 'passesRequired': 2,
+ 'stopIfAnyPassed': true,
},
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'type': 'an object with keys maxRetries, stopIfAnyPassed',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-but-always-fail provides stopIfAnyPassed without maxRetries 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-but-always-fail',
- 'experimentalOptions': {
- 'stopIfAnyPassed': false,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.maxRetries',
+ 'type': 'a positive whole number greater than or equals 1 or null',
}
exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-but-always-fail stopIfAnyPassed is a number (0 and 1 do not work) 1'] = {
- 'key': 'mockConfigKey',
- 'value': {
- 'experimentalStrategy': 'detect-flake-but-always-fail',
- 'experimentalOptions': {
- 'maxRetries': 2,
- 'stopIfAnyPassed': 1,
- },
- },
- 'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
+ 'key': 'mockConfigKey.experimentalOptions.stopIfAnyPassed',
+ 'value': 1,
+ 'type': 'a boolean',
+}
+
+exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-but-always-fail: valid strategy w/ other invalid options with experiment 1'] = {
+ 'key': 'mockConfigKey.runMode',
+ 'value': 1,
+ 'type': 'a boolean since an experimental strategy is provided',
+}
+
+exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-and-pass-on-threshold: valid strategy w/ other invalid options with experiment 1'] = {
+ 'key': 'mockConfigKey.runMode',
+ 'value': 1,
+ 'type': 'a boolean since an experimental strategy is provided',
+}
+
+exports['config/src/validation .isValidRetriesConfig returns error message for openMode as boolean without strategy 1'] = {
+ 'key': 'mockConfigKey.openMode',
+ 'value': true,
+ 'type': 'a number since no experimental strategy is provided',
+}
+
+exports['config/src/validation .isValidRetriesConfig returns error message for runMode as boolean without strategy 1'] = {
+ 'key': 'mockConfigKey.runMode',
+ 'value': true,
+ 'type': 'a number since no experimental strategy is provided',
+}
+
+exports['config/src/validation .isValidRetriesConfig experimental options fails with detect-flake-but-always-fail provides maxRetries without stopIfAnyPassed 1'] = {
+ 'key': 'mockConfigKey.experimentalOptions.stopIfAnyPassed',
+ 'type': 'is required when using the "detect-flake-but-always-fail" strategy',
}
diff --git a/packages/config/src/validation.ts b/packages/config/src/validation.ts
index 27b385aa3664..8143038e5b7c 100644
--- a/packages/config/src/validation.ts
+++ b/packages/config/src/validation.ts
@@ -119,67 +119,95 @@ export const isValidBrowserList = (_key: string, browsers: any): ErrResult | tru
return true
}
-const isValidExperimentalRetryOptionsConfig = (options: any, strategy: 'detect-flake-but-always-fail' | 'detect-flake-and-pass-on-threshold'): boolean => {
- if (options == null) return true
+const isValidExperimentalRetryOptionsConfig = (key: string, value: any, strategy: 'detect-flake-but-always-fail' | 'detect-flake-and-pass-on-threshold') => {
+ if (value == null) return true
- // retries must be an integer of 1 or greater
- const isValidMaxRetries = _.isInteger(options.maxRetries) && options.maxRetries > 0
+ const isValidMaxRetries = isValidRetryValue(`${key}.maxRetries`, value.maxRetries, 1)
- if (!isValidMaxRetries) {
- return false
+ if (isValidMaxRetries !== true) {
+ return isValidMaxRetries
}
- // if the strategy is 'detect-flake-but-always-fail', stopIfAnyPassed must be provided and must be a boolean
+ const validKeys = ['maxRetries']
+
+ // if the strategy is 'detect-flake-but-always-fail' and the stopIfAnyPassed is required and must be a boolean
if (strategy === 'detect-flake-but-always-fail') {
- if (options.passesRequired !== undefined) {
- return false
+ validKeys.push('stopIfAnyPassed')
+ if (_.isNull(value.stopIfAnyPassed) || value.stopIfAnyPassed === undefined) {
+ return errMsg(`${key}.stopIfAnyPassed`, value.stopIfAnyPassed, 'is required when using the "detect-flake-but-always-fail" strategy')
}
- const isValidStopIfAnyPasses = _.isBoolean(options.stopIfAnyPassed)
+ const isValidStopIfAnyPasses = _.isBoolean(value.stopIfAnyPassed)
if (!isValidStopIfAnyPasses) {
- return false
+ return errMsg(`${key}.stopIfAnyPassed`, value.stopIfAnyPassed, 'a boolean')
}
}
- // if the strategy is 'detect-flake-and-pass-on-threshold', passesRequired must be provided and must be an integer greater than 0
+ // if the strategy is 'detect-flake-and-pass-on-threshold' then passesRequired is required and must be a valid retry value and less than or equal to maxRetries
if (strategy === 'detect-flake-and-pass-on-threshold') {
- if (options.stopIfAnyPassed !== undefined) {
- return false
+ validKeys.push('passesRequired')
+
+ if (_.isNull(value.passesRequired) || value.passesRequired === undefined) {
+ return errMsg(`${key}.passesRequired`, value.stopIfAnyPassed, 'is required when using the "detect-flake-and-pass-on-threshold" strategy')
}
- const isValidPassesRequired = _.isInteger(options.passesRequired) && options.passesRequired > 0 && options.passesRequired <= options.maxRetries
+ const isValidPassesRequired = Number.isInteger(value.passesRequired) && value.passesRequired >= 1 && value.passesRequired <= value.maxRetries
if (!isValidPassesRequired) {
- return false
+ return errMsg(`${key}.passesRequired`, value.passesRequired, 'a positive whole number less than or equals to maxRetries')
}
}
+ const extraneousKeys = _.difference(Object.keys(value), validKeys)
+
+ if (extraneousKeys.length > 0) {
+ return errMsg(key, value, `an object with keys ${validKeys.join(', ')}`)
+ }
+
return true
}
+const isValidRetryValue = (key: string, value: any, minimumValue: 0|1): ErrResult | true => {
+ if (_.isNull(value)) return true
+
+ if (Number.isInteger(value) && value >= minimumValue) return true
+
+ return errMsg(key, value, `a positive whole number greater than or equals ${minimumValue} or null`)
+}
+
export const isValidRetriesConfig = (key: string, value: any): ErrResult | true => {
const optionalKeys = ['runMode', 'openMode']
const experimentalOptions = ['experimentalStrategy', 'experimentalOptions']
const experimentalStrategyOptions = ['detect-flake-but-always-fail', 'detect-flake-and-pass-on-threshold']
- const isValidRetryValue = (val: any) => _.isNull(val) || (Number.isInteger(val) && val >= 0)
- const optionalKeysAreValid = (val: any, k: string) => optionalKeys.includes(k) && isValidRetryValue(val)
+ const optionalKeysAreValid = (key: string) => {
+ return (parentVal: object, optionName: string) => {
+ if (!optionalKeys.includes(optionName)) {
+ return errMsg(key, parentVal, 'an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls')
+ }
+
+ const optionValue = _.get(parentVal, optionName)
- if (isValidRetryValue(value)) {
- return true
+ if (_.isBoolean(optionValue)) return true
+
+ return isValidRetryValue(`${key}.${optionName}`, _.get(parentVal, optionName), 0)
+ }
}
if (_.isObject(value)) {
const traditionalConfigOptions = _.omit(value, experimentalOptions)
const experimentalConfigOptions = _.pick(value, experimentalOptions)
+ const openAndRunModeConfigOptions = _.pick(value, optionalKeys)
- const isTraditionalConfigValid = _.every(traditionalConfigOptions, optionalKeysAreValid)
+ for (const optionKey in traditionalConfigOptions) {
+ if (Object.prototype.hasOwnProperty.call(traditionalConfigOptions, optionKey)) {
+ const optionValidation = optionalKeysAreValid(key)(value, optionKey)
- // if optionalKeys are only present and are valid, return true.
- // The defaults for 'experimentalStrategy' and 'experimentalOptions' are undefined, but the keys exist, so we need to check for this
- if (isTraditionalConfigValid && !Object.keys(experimentalConfigOptions).filter((key) => experimentalConfigOptions[key] !== undefined).length) {
- return true
+ if (optionValidation !== true || _.isObject(optionValidation)) {
+ return optionValidation
+ }
+ }
}
// check experimental configuration. experimentalStrategy MUST be present if experimental config is provided and set to one of the provided enumerations
@@ -187,20 +215,56 @@ export const isValidRetriesConfig = (key: string, value: any): ErrResult | true
// make sure the strategy provided is one of our valid enums
const isValidStrategy = experimentalStrategyOptions.includes(experimentalConfigOptions.experimentalStrategy)
+ if (!isValidStrategy) {
+ return errMsg(`${key}.experimentalStrategy`, experimentalConfigOptions.experimentalStrategy, `one of ${experimentalStrategyOptions.map((s) => `"${s}"`).join(', ')}`)
+ }
+
// if a strategy is provided, and traditional options are also provided, such as runMode and openMode, then these values need to be booleans
- const openAndRunModeConfigOptions = _.pick(value, optionalKeys)
- const isValidRunAndOpenModeConfigWithStrategy = _.every(openAndRunModeConfigOptions, _.isBoolean)
+
+ for (const optionalKey in openAndRunModeConfigOptions) {
+ if (Object.prototype.hasOwnProperty.call(openAndRunModeConfigOptions, optionalKey)) {
+ const optionalConfigVal = _.get(openAndRunModeConfigOptions, optionalKey)
+
+ if (!_.isBoolean(optionalConfigVal)) {
+ return errMsg(`${key}.${optionalKey}`, optionalConfigVal, 'a boolean since an experimental strategy is provided')
+ }
+ }
+ }
// if options aren't present (either undefined or null) or are configured correctly, return true
- if (isValidStrategy && isValidRunAndOpenModeConfigWithStrategy && (
- experimentalConfigOptions.experimentalOptions == null ||
- isValidExperimentalRetryOptionsConfig(experimentalConfigOptions.experimentalOptions, experimentalConfigOptions.experimentalStrategy))) {
+ if (
+ experimentalConfigOptions.experimentalOptions == null) {
return true
}
+
+ const isValidExperimentalRetryOptions = isValidExperimentalRetryOptionsConfig(`${key}.experimentalOptions`, experimentalConfigOptions.experimentalOptions, experimentalConfigOptions.experimentalStrategy)
+
+ if (isValidExperimentalRetryOptions !== true) {
+ return isValidExperimentalRetryOptions
+ }
+ } else {
+ for (const optionalKey in openAndRunModeConfigOptions) {
+ if (Object.prototype.hasOwnProperty.call(openAndRunModeConfigOptions, optionalKey)) {
+ const optionalConfigVal = _.get(openAndRunModeConfigOptions, optionalKey)
+
+ if (!_.isNumber(optionalConfigVal)) {
+ return errMsg(`${key}.${optionalKey}`, optionalConfigVal, 'a number since no experimental strategy is provided')
+ }
+ }
+ }
+ if (experimentalConfigOptions.experimentalOptions) {
+ return errMsg(`${key}.experimentalOptions`, experimentalConfigOptions.experimentalOptions, 'provided only if an experimental strategy is provided')
+ }
+ }
+ } else {
+ const isValidValue = isValidRetryValue(key, value, 0)
+
+ if (isValidValue !== true) {
+ return errMsg(key, value, 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy')
}
}
- return errMsg(key, value, 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy')
+ return true
}
/**
diff --git a/packages/config/test/validation.spec.ts b/packages/config/test/validation.spec.ts
index 9b68eb8a1a14..a698dbef73af 100644
--- a/packages/config/test/validation.spec.ts
+++ b/packages/config/test/validation.spec.ts
@@ -138,6 +138,9 @@ describe('config/src/validation', () => {
result = validation.isValidRetriesConfig(mockKey, 2)
expect(result).to.be.true
+
+ result = validation.isValidRetriesConfig(mockKey, 250)
+ expect(result).to.be.true
})
it('returns true for valid retry objects', () => {
@@ -145,9 +148,15 @@ describe('config/src/validation', () => {
expect(result).to.be.true
+ result = validation.isValidRetriesConfig(mockKey, { runMode: 250 })
+ expect(result).to.be.true
+
result = validation.isValidRetriesConfig(mockKey, { openMode: 1 })
expect(result).to.be.true
+ result = validation.isValidRetriesConfig(mockKey, { openMode: 250 })
+ expect(result).to.be.true
+
result = validation.isValidRetriesConfig(mockKey, {
runMode: 3,
openMode: 0,
@@ -167,6 +176,20 @@ describe('config/src/validation', () => {
snapshot('invalid retry object', result)
})
+ it('returns error message for openMode as boolean without strategy', () => {
+ let result = validation.isValidRetriesConfig(mockKey, { openMode: true })
+
+ expect(result).to.not.be.true
+ snapshot(result)
+ })
+
+ it('returns error message for runMode as boolean without strategy', () => {
+ let result = validation.isValidRetriesConfig(mockKey, { runMode: true })
+
+ expect(result).to.not.be.true
+ snapshot(result)
+ })
+
it('returns true for valid retry object with experimental keys (default)', () => {
let result = validation.isValidRetriesConfig(mockKey, {
openMode: 0,
@@ -196,6 +219,17 @@ describe('config/src/validation', () => {
expect(result).to.be.true
})
+
+ it(`experimentalStrategy is "${strategy}" with only "maxRetries" in "experimentalOptions"`, () => {
+ const result = validation.isValidRetriesConfig(mockKey, {
+ experimentalStrategy: strategy,
+ experimentalOptions: {
+ maxRetries: 4,
+ },
+ })
+
+ expect(result).to.not.be.true
+ })
})
it('experimentalStrategy is "detect-flake-but-always-fail" and has option "stopIfAnyPassed"', () => {
@@ -259,8 +293,8 @@ describe('config/src/validation', () => {
it('invalid strategy w/ other options (valid)', () => {
const result = validation.isValidRetriesConfig(mockKey, {
- runMode: true,
- openMode: false,
+ runMode: 1,
+ openMode: 2,
experimentalStrategy: 'bar',
})
@@ -315,18 +349,6 @@ describe('config/src/validation', () => {
expect(result).to.not.be.true
snapshot(result)
})
-
- it(`experimentalStrategy is "${strategy}" with only "maxRetries" in "experimentalOptions"`, () => {
- const result = validation.isValidRetriesConfig(mockKey, {
- experimentalStrategy: strategy,
- experimentalOptions: {
- maxRetries: 4,
- },
- })
-
- expect(result).to.not.be.true
- snapshot(result)
- })
})
describe('detect-flake-and-pass-on-threshold', () => {
@@ -399,6 +421,7 @@ describe('config/src/validation', () => {
experimentalStrategy: 'detect-flake-and-pass-on-threshold',
experimentalOptions: {
maxRetries: 3,
+ passesRequired: 2,
stopIfAnyPassed: true,
},
})
@@ -415,6 +438,7 @@ describe('config/src/validation', () => {
experimentalOptions: {
maxRetries: 3,
passesRequired: 2,
+ stopIfAnyPassed: true,
},
})
@@ -434,6 +458,18 @@ describe('config/src/validation', () => {
snapshot(result)
})
+ it('provides maxRetries without stopIfAnyPassed', () => {
+ const result = validation.isValidRetriesConfig(mockKey, {
+ experimentalStrategy: 'detect-flake-but-always-fail',
+ experimentalOptions: {
+ maxRetries: 2,
+ },
+ })
+
+ expect(result).to.not.be.true
+ snapshot(result)
+ })
+
it('stopIfAnyPassed is a number (0 and 1 do not work)', () => {
const result = validation.isValidRetriesConfig(mockKey, {
experimentalStrategy: 'detect-flake-but-always-fail',
diff --git a/packages/example/README.md b/packages/example/README.md
index 8d57d43339f8..377f5f731eb4 100644
--- a/packages/example/README.md
+++ b/packages/example/README.md
@@ -2,7 +2,7 @@
This package is responsible for copying the `cypress/e2e` and `app` files from [`cypress-example-kitchensink`](https://github.com/cypress-io/cypress-example-kitchensink) into the cypress repository.
-The `cypress/e2e` tests, pulled into this package from the [kitchen sink app](https://github.com/cypress-io/cypress-example-kitchensink), are used for scaffolding user's e2e tests in `packages/data-context` and in `npm/create-cypress-tests`.
+The `cypress/e2e` tests, pulled into this package from the [kitchen sink app](https://github.com/cypress-io/cypress-example-kitchensink), are used for scaffolding user's e2e tests in `packages/data-context`.
The `app` content, pulled into this package from the [kitchen sink app](https://github.com/cypress-io/cypress-example-kitchensink), is published to `cypress-io/cypress` repository's Github page, [https://example.cypress.io](https://example.cypress.io).
diff --git a/packages/server/test/unit/config_spec.js b/packages/server/test/unit/config_spec.js
index 343cd75fb527..69ead5c1a0f4 100644
--- a/packages/server/test/unit/config_spec.js
+++ b/packages/server/test/unit/config_spec.js
@@ -883,29 +883,27 @@ describe('lib/config', () => {
})
context('retries', () => {
- const retriesError = 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy'
-
// need to keep the const here or it'll get stripped by the build
// eslint-disable-next-line no-unused-vars
const cases = [
- [{ retries: null }, 'with null', true],
- [{ retries: 3 }, 'when a number', true],
- [{ retries: 3.2 }, 'when a float', false],
- [{ retries: -1 }, 'with a negative number', false],
- [{ retries: true }, 'when true', false],
- [{ retries: false }, 'when false', false],
- [{ retries: {} }, 'with an empty object', true],
- [{ retries: { runMode: 3 } }, 'when runMode is a positive number', true],
- [{ retries: { runMode: -1 } }, 'when runMode is a negative number', false],
- [{ retries: { openMode: 3 } }, 'when openMode is a positive number', true],
- [{ retries: { openMode: -1 } }, 'when openMode is a negative number', false],
- [{ retries: { openMode: 3, TypoRunMode: 3 } }, 'when there is an additional unknown key', false],
- [{ retries: { openMode: 3, runMode: 3 } }, 'when both runMode and openMode are positive numbers', true],
- ].forEach(([config, expectation, shouldPass]) => {
- it(`${shouldPass ? 'passes' : 'fails'} ${expectation}`, function () {
+ [{ retries: null }, 'with null', null],
+ [{ retries: 3 }, 'when a number', null],
+ [{ retries: 3.2 }, 'when a float', 'Expected retries to be a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy.'],
+ [{ retries: -1 }, 'with a negative number', 'Expected retries to be a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy.'],
+ [{ retries: true }, 'when true', 'Expected retries to be a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy.'],
+ [{ retries: false }, 'when false', 'Expected retries to be a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy.'],
+ [{ retries: {} }, 'with an empty object', null],
+ [{ retries: { runMode: 3 } }, 'when runMode is a positive number', null],
+ [{ retries: { runMode: -1 } }, 'when runMode is a negative number', 'Expected retries.runMode to be a positive whole number greater than or equals 0 or null.'],
+ [{ retries: { openMode: 3 } }, 'when openMode is a positive number', null],
+ [{ retries: { openMode: -1 } }, 'when openMode is a negative number', 'Expected retries.openMode to be a positive whole number greater than or equals 0 or null'],
+ [{ retries: { openMode: 3, TypoRunMode: 3 } }, 'when there is an additional unknown key', 'Expected retries to be an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls.'],
+ [{ retries: { openMode: 3, runMode: 3 } }, 'when both runMode and openMode are positive numbers', null],
+ ].forEach(([config, expectation, expectedError]) => {
+ it(`${expectedError ? 'fails' : 'passes'} ${expectation}`, function () {
this.setup(config)
- return shouldPass ? this.expectValidationPasses() : this.expectValidationFails(retriesError)
+ return expectedError ? this.expectValidationFails(expectedError) : this.expectValidationPasses()
})
})
})
diff --git a/scripts/binary/util/packages.ts b/scripts/binary/util/packages.ts
index a45c7827e02f..9653d8faf0c4 100644
--- a/scripts/binary/util/packages.ts
+++ b/scripts/binary/util/packages.ts
@@ -140,7 +140,7 @@ export const replaceLocalNpmVersions = async function (basePath: string) {
let shouldWriteFile = false
for (const [depName, version] of Object.entries(dependencies)) {
- const matchedPkg = Boolean(depName.startsWith('@cypress/') || depName === 'create-cypress-tests')
+ const matchedPkg = Boolean(depName.startsWith('@cypress/'))
if (!matchedPkg || version !== '0.0.0-development') {
continue
diff --git a/yarn.lock b/yarn.lock
index 45a874b3a362..cc41777b7945 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -16339,24 +16339,7 @@ gopd@^1.0.1:
dependencies:
get-intrinsic "^1.1.3"
-got@11.8.5:
- version "11.8.5"
- resolved "https://registry.yarnpkg.com/got/-/got-11.8.5.tgz#ce77d045136de56e8f024bebb82ea349bc730046"
- integrity sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==
- dependencies:
- "@sindresorhus/is" "^4.0.0"
- "@szmarczak/http-timer" "^4.0.5"
- "@types/cacheable-request" "^6.0.1"
- "@types/responselike" "^1.0.0"
- cacheable-lookup "^5.0.3"
- cacheable-request "^7.0.2"
- decompress-response "^6.0.0"
- http2-wrapper "^1.0.0-beta.5.2"
- lowercase-keys "^2.0.0"
- p-cancelable "^2.0.0"
- responselike "^2.0.0"
-
-got@^11.7.0, got@^11.8.5:
+got@11.8.6, got@^11.7.0, got@^11.8.5:
version "11.8.6"
resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a"
integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==