cypress 15.1.0 → 15.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/bin/cypress +3 -1
  2. package/dist/VerboseRenderer.js +61 -0
  3. package/dist/cli.js +544 -0
  4. package/dist/cypress.js +104 -0
  5. package/dist/errors.js +391 -0
  6. package/dist/exec/info.js +103 -0
  7. package/dist/exec/open.js +103 -0
  8. package/dist/exec/run.js +177 -0
  9. package/dist/exec/shared.js +55 -0
  10. package/dist/exec/spawn.js +301 -0
  11. package/dist/exec/versions.js +67 -0
  12. package/dist/exec/xvfb.js +118 -0
  13. package/dist/index.js +52 -0
  14. package/dist/index.mjs +9 -0
  15. package/dist/logger.js +55 -0
  16. package/dist/tasks/cache.js +144 -0
  17. package/dist/tasks/download.js +304 -0
  18. package/dist/tasks/get-folder-size.js +44 -0
  19. package/dist/tasks/install.js +326 -0
  20. package/dist/tasks/state.js +184 -0
  21. package/dist/tasks/unzip.js +192 -0
  22. package/dist/tasks/verify.js +303 -0
  23. package/dist/util.js +452 -0
  24. package/package.json +10 -13
  25. package/types/cypress-automation.d.ts +2 -1
  26. package/types/cypress.d.ts +1 -0
  27. package/index.js +0 -27
  28. package/index.mjs +0 -17
  29. package/lib/VerboseRenderer.js +0 -58
  30. package/lib/cli.js +0 -411
  31. package/lib/cypress.js +0 -98
  32. package/lib/errors.js +0 -392
  33. package/lib/exec/info.js +0 -92
  34. package/lib/exec/open.js +0 -90
  35. package/lib/exec/run.js +0 -176
  36. package/lib/exec/shared.js +0 -62
  37. package/lib/exec/spawn.js +0 -247
  38. package/lib/exec/versions.js +0 -53
  39. package/lib/exec/xvfb.js +0 -93
  40. package/lib/fs.js +0 -4
  41. package/lib/logger.js +0 -50
  42. package/lib/tasks/cache.js +0 -132
  43. package/lib/tasks/download.js +0 -324
  44. package/lib/tasks/get-folder-size.js +0 -33
  45. package/lib/tasks/install.js +0 -368
  46. package/lib/tasks/state.js +0 -185
  47. package/lib/tasks/unzip.js +0 -200
  48. package/lib/tasks/verify.js +0 -300
  49. package/lib/util.js +0 -448
@@ -1,368 +0,0 @@
1
- "use strict";
2
-
3
- const _ = require('lodash');
4
- const os = require('os');
5
- const path = require('path');
6
- const chalk = require('chalk');
7
- const debug = require('debug')('cypress:cli');
8
- const {
9
- Listr
10
- } = require('listr2');
11
- const Promise = require('bluebird');
12
- const logSymbols = require('log-symbols');
13
- const {
14
- stripIndent
15
- } = require('common-tags');
16
- const fs = require('../fs');
17
- const download = require('./download');
18
- const util = require('../util');
19
- const state = require('./state');
20
- const unzip = require('./unzip');
21
- const logger = require('../logger');
22
- const {
23
- throwFormErrorText,
24
- errors
25
- } = require('../errors');
26
- const verbose = require('../VerboseRenderer');
27
- const {
28
- buildInfo,
29
- version
30
- } = require('../../package.json');
31
- function _getBinaryUrlFromBuildInfo(arch, {
32
- commitSha,
33
- commitBranch
34
- }) {
35
- const platform = os.platform();
36
- if (platform === 'win32' && arch === 'arm64') {
37
- debug(`detected platform ${platform} architecture ${arch} combination`);
38
- arch = 'x64';
39
- debug(`overriding to download ${platform}-${arch} pre-release binary instead`);
40
- }
41
- return `https://cdn.cypress.io/beta/binary/${version}/${platform}-${arch}/${commitBranch}-${commitSha}/cypress.zip`;
42
- }
43
- const alreadyInstalledMsg = () => {
44
- if (!util.isPostInstall()) {
45
- logger.log(stripIndent`
46
- Skipping installation:
47
-
48
- Pass the ${chalk.yellow('--force')} option if you'd like to reinstall anyway.
49
- `);
50
- }
51
- };
52
- const displayCompletionMsg = () => {
53
- // check here to see if we are globally installed
54
- if (util.isInstalledGlobally()) {
55
- // if we are display a warning
56
- logger.log();
57
- logger.warn(stripIndent`
58
- ${logSymbols.warning} Warning: It looks like you\'ve installed Cypress globally.
59
-
60
- The recommended way to install Cypress is as a devDependency per project.
61
-
62
- You should probably run these commands:
63
-
64
- - ${chalk.cyan('npm uninstall -g cypress')}
65
- - ${chalk.cyan('npm install --save-dev cypress')}
66
- `);
67
- return;
68
- }
69
- logger.log();
70
- logger.log('You can now open Cypress by running one of the following, depending on your package manager:');
71
- logger.log();
72
- logger.log(chalk.cyan('- npx cypress open'));
73
- logger.log(chalk.cyan('- yarn cypress open'));
74
- logger.log(chalk.cyan('- pnpm cypress open'));
75
- logger.log();
76
- logger.log(chalk.grey('https://on.cypress.io/opening-the-app'));
77
- logger.log();
78
- };
79
- const downloadAndUnzip = ({
80
- version,
81
- installDir,
82
- downloadDir
83
- }) => {
84
- const progress = {
85
- throttle: 100,
86
- onProgress: null
87
- };
88
- const downloadDestination = path.join(downloadDir, `cypress-${process.pid}.zip`);
89
- const rendererOptions = getRendererOptions();
90
-
91
- // let the user know what version of cypress we're downloading!
92
- logger.log(`Installing Cypress ${chalk.gray(`(version: ${version})`)}`);
93
- logger.log();
94
- const tasks = new Listr([{
95
- options: {
96
- title: util.titleize('Downloading Cypress')
97
- },
98
- task: (ctx, task) => {
99
- // as our download progresses indicate the status
100
- progress.onProgress = progessify(task, 'Downloading Cypress');
101
- return download.start({
102
- version,
103
- downloadDestination,
104
- progress
105
- }).then(redirectVersion => {
106
- if (redirectVersion) version = redirectVersion;
107
- debug(`finished downloading file: ${downloadDestination}`);
108
- }).then(() => {
109
- // save the download destination for unzipping
110
- util.setTaskTitle(task, util.titleize(chalk.green('Downloaded Cypress')), rendererOptions.renderer);
111
- });
112
- }
113
- }, unzipTask({
114
- progress,
115
- zipFilePath: downloadDestination,
116
- installDir,
117
- rendererOptions
118
- }), {
119
- options: {
120
- title: util.titleize('Finishing Installation')
121
- },
122
- task: (ctx, task) => {
123
- const cleanup = () => {
124
- debug('removing zip file %s', downloadDestination);
125
- return fs.removeAsync(downloadDestination);
126
- };
127
- return cleanup().then(() => {
128
- debug('finished installation in', installDir);
129
- util.setTaskTitle(task, util.titleize(chalk.green('Finished Installation'), chalk.gray(installDir)), rendererOptions.renderer);
130
- });
131
- }
132
- }], {
133
- rendererOptions
134
- });
135
-
136
- // start the tasks!
137
- return Promise.resolve(tasks.run());
138
- };
139
- const validateOS = () => {
140
- return util.getPlatformInfo().then(platformInfo => {
141
- return platformInfo.match(/(win32-x64|win32-arm64|linux-x64|linux-arm64|darwin-x64|darwin-arm64)/);
142
- });
143
- };
144
-
145
- /**
146
- * Returns the version to install - either a string like `1.2.3` to be fetched
147
- * from the download server or a file path or HTTP URL.
148
- */
149
- function getVersionOverride({
150
- arch,
151
- envVarVersion,
152
- buildInfo
153
- }) {
154
- // let this environment variable reset the binary version we need
155
- if (envVarVersion) {
156
- return envVarVersion;
157
- }
158
- if (buildInfo && !buildInfo.stable) {
159
- logger.log(chalk.yellow(stripIndent`
160
- ${logSymbols.warning} Warning: You are installing a pre-release build of Cypress.
161
-
162
- Bugs may be present which do not exist in production builds.
163
-
164
- This build was created from:
165
- * Commit SHA: ${buildInfo.commitSha}
166
- * Commit Branch: ${buildInfo.commitBranch}
167
- * Commit Timestamp: ${buildInfo.commitDate}
168
- `));
169
- logger.log();
170
- return _getBinaryUrlFromBuildInfo(arch, buildInfo);
171
- }
172
- }
173
- function getEnvVarVersion() {
174
- if (!util.getEnv('CYPRESS_INSTALL_BINARY')) return;
175
-
176
- // because passed file paths are often double quoted
177
- // and might have extra whitespace around, be robust and trim the string
178
- const trimAndRemoveDoubleQuotes = true;
179
- const envVarVersion = util.getEnv('CYPRESS_INSTALL_BINARY', trimAndRemoveDoubleQuotes);
180
- debug('using environment variable CYPRESS_INSTALL_BINARY "%s"', envVarVersion);
181
- return envVarVersion;
182
- }
183
- const start = async (options = {}) => {
184
- debug('installing with options %j', options);
185
- const envVarVersion = getEnvVarVersion();
186
- if (envVarVersion === '0') {
187
- debug('environment variable CYPRESS_INSTALL_BINARY = 0, skipping install');
188
- logger.log(stripIndent`
189
- ${chalk.yellow('Note:')} Skipping binary installation: Environment variable CYPRESS_INSTALL_BINARY = 0.`);
190
- logger.log();
191
- return;
192
- }
193
- _.defaults(options, {
194
- force: false,
195
- buildInfo
196
- });
197
- if (util.getEnv('CYPRESS_CACHE_FOLDER')) {
198
- const envCache = util.getEnv('CYPRESS_CACHE_FOLDER');
199
- logger.log(stripIndent`
200
- ${chalk.yellow('Note:')} Overriding Cypress cache directory to: ${chalk.cyan(envCache)}
201
-
202
- Previous installs of Cypress may not be found.
203
- `);
204
- logger.log();
205
- }
206
- const pkgVersion = util.pkgVersion();
207
- const arch = await util.getRealArch();
208
- const versionOverride = getVersionOverride({
209
- arch,
210
- envVarVersion,
211
- buildInfo: options.buildInfo
212
- });
213
- const versionToInstall = versionOverride || pkgVersion;
214
- debug('version in package.json is %s, version to install is %s', pkgVersion, versionToInstall);
215
- const installDir = state.getVersionDir(pkgVersion, options.buildInfo);
216
- const cacheDir = state.getCacheDir();
217
- const binaryDir = state.getBinaryDir(pkgVersion);
218
- if (!(await validateOS())) {
219
- return throwFormErrorText(errors.invalidOS)();
220
- }
221
- await fs.ensureDirAsync(cacheDir).catch({
222
- code: 'EACCES'
223
- }, err => {
224
- return throwFormErrorText(errors.invalidCacheDirectory)(stripIndent`
225
- Failed to access ${chalk.cyan(cacheDir)}:
226
-
227
- ${err.message}
228
- `);
229
- });
230
- const binaryPkg = await state.getBinaryPkgAsync(binaryDir);
231
- const binaryVersion = await state.getBinaryPkgVersion(binaryPkg);
232
- const shouldInstall = () => {
233
- if (!binaryVersion) {
234
- debug('no binary installed under cli version');
235
- return true;
236
- }
237
- logger.log();
238
- logger.log(stripIndent`
239
- Cypress ${chalk.green(binaryVersion)} is installed in ${chalk.cyan(installDir)}
240
- `);
241
- logger.log();
242
- if (options.force) {
243
- debug('performing force install over existing binary');
244
- return true;
245
- }
246
- if (binaryVersion === versionToInstall || !util.isSemver(versionToInstall)) {
247
- // our version matches, tell the user this is a noop
248
- alreadyInstalledMsg();
249
- return false;
250
- }
251
- return true;
252
- };
253
-
254
- // noop if we've been told not to download
255
- if (!shouldInstall()) {
256
- return debug('Not downloading or installing binary');
257
- }
258
- if (envVarVersion) {
259
- logger.log(chalk.yellow(stripIndent`
260
- ${logSymbols.warning} Warning: Forcing a binary version different than the default.
261
-
262
- The CLI expected to install version: ${chalk.green(pkgVersion)}
263
-
264
- Instead we will install version: ${chalk.green(versionToInstall)}
265
-
266
- These versions may not work properly together.
267
- `));
268
- logger.log();
269
- }
270
- const getLocalFilePath = async () => {
271
- // see if version supplied is a path to a binary
272
- if (await fs.pathExistsAsync(versionToInstall)) {
273
- return path.extname(versionToInstall) === '.zip' ? versionToInstall : false;
274
- }
275
- const possibleFile = util.formAbsolutePath(versionToInstall);
276
- debug('checking local file', possibleFile, 'cwd', process.cwd());
277
-
278
- // if this exists return the path to it
279
- // else false
280
- if ((await fs.pathExistsAsync(possibleFile)) && path.extname(possibleFile) === '.zip') {
281
- return possibleFile;
282
- }
283
- return false;
284
- };
285
- const pathToLocalFile = await getLocalFilePath();
286
- if (pathToLocalFile) {
287
- const absolutePath = path.resolve(versionToInstall);
288
- debug('found local file at', absolutePath);
289
- debug('skipping download');
290
- const rendererOptions = getRendererOptions();
291
- return new Listr([unzipTask({
292
- progress: {
293
- throttle: 100,
294
- onProgress: null
295
- },
296
- zipFilePath: absolutePath,
297
- installDir,
298
- rendererOptions
299
- })], {
300
- rendererOptions
301
- }).run();
302
- }
303
- if (options.force) {
304
- debug('Cypress already installed at', installDir);
305
- debug('but the installation was forced');
306
- }
307
- debug('preparing to download and unzip version ', versionToInstall, 'to path', installDir);
308
- const downloadDir = os.tmpdir();
309
- await downloadAndUnzip({
310
- version: versionToInstall,
311
- installDir,
312
- downloadDir
313
- });
314
-
315
- // delay 1 sec for UX, unless we are testing
316
- await Promise.delay(1000);
317
- displayCompletionMsg();
318
- };
319
- module.exports = {
320
- start,
321
- _getBinaryUrlFromBuildInfo
322
- };
323
- const unzipTask = ({
324
- zipFilePath,
325
- installDir,
326
- progress,
327
- rendererOptions
328
- }) => {
329
- return {
330
- options: {
331
- title: util.titleize('Unzipping Cypress')
332
- },
333
- task: (ctx, task) => {
334
- // as our unzip progresses indicate the status
335
- progress.onProgress = progessify(task, 'Unzipping Cypress');
336
- return unzip.start({
337
- zipFilePath,
338
- installDir,
339
- progress
340
- }).then(() => {
341
- util.setTaskTitle(task, util.titleize(chalk.green('Unzipped Cypress')), rendererOptions.renderer);
342
- });
343
- }
344
- };
345
- };
346
- const progessify = (task, title) => {
347
- // return higher order function
348
- return (percentComplete, remaining) => {
349
- percentComplete = chalk.white(` ${percentComplete}%`);
350
-
351
- // pluralize seconds remaining
352
- remaining = chalk.gray(`${remaining}s`);
353
- util.setTaskTitle(task, util.titleize(title, percentComplete, remaining), getRendererOptions().renderer);
354
- };
355
- };
356
-
357
- // if we are running in CI then use
358
- // the verbose renderer else use
359
- // the default
360
- const getRendererOptions = () => {
361
- let renderer = util.isCi() ? verbose : 'default';
362
- if (logger.logLevel() === 'silent') {
363
- renderer = 'silent';
364
- }
365
- return {
366
- renderer
367
- };
368
- };
@@ -1,185 +0,0 @@
1
- "use strict";
2
-
3
- const _ = require('lodash');
4
- const os = require('os');
5
- const path = require('path');
6
- const untildify = require('untildify');
7
- const debug = require('debug')('cypress:cli');
8
- const fs = require('../fs');
9
- const util = require('../util');
10
- const getPlatformExecutable = () => {
11
- const platform = os.platform();
12
- switch (platform) {
13
- case 'darwin':
14
- return 'Contents/MacOS/Cypress';
15
- case 'linux':
16
- return 'Cypress';
17
- case 'win32':
18
- return 'Cypress.exe';
19
- // TODO handle this error using our standard
20
- default:
21
- throw new Error(`Platform: "${platform}" is not supported.`);
22
- }
23
- };
24
- const getPlatFormBinaryFolder = () => {
25
- const platform = os.platform();
26
- switch (platform) {
27
- case 'darwin':
28
- return 'Cypress.app';
29
- case 'linux':
30
- return 'Cypress';
31
- case 'win32':
32
- return 'Cypress';
33
- // TODO handle this error using our standard
34
- default:
35
- throw new Error(`Platform: "${platform}" is not supported.`);
36
- }
37
- };
38
- const getBinaryPkgPath = binaryDir => {
39
- const platform = os.platform();
40
- switch (platform) {
41
- case 'darwin':
42
- return path.join(binaryDir, 'Contents', 'Resources', 'app', 'package.json');
43
- case 'linux':
44
- return path.join(binaryDir, 'resources', 'app', 'package.json');
45
- case 'win32':
46
- return path.join(binaryDir, 'resources', 'app', 'package.json');
47
- // TODO handle this error using our standard
48
- default:
49
- throw new Error(`Platform: "${platform}" is not supported.`);
50
- }
51
- };
52
-
53
- /**
54
- * Get path to binary directory
55
- */
56
- const getBinaryDir = (version = util.pkgVersion()) => {
57
- return path.join(getVersionDir(version), getPlatFormBinaryFolder());
58
- };
59
- const getVersionDir = (version = util.pkgVersion(), buildInfo = util.pkgBuildInfo()) => {
60
- if (buildInfo && !buildInfo.stable) {
61
- version = ['beta', version, buildInfo.commitBranch, buildInfo.commitSha.slice(0, 8)].join('-');
62
- }
63
- return path.join(getCacheDir(), version);
64
- };
65
-
66
- /**
67
- * When executing "npm postinstall" hook, the working directory is set to
68
- * "<current folder>/node_modules/cypress", which can be surprising when using relative paths.
69
- */
70
- const isInstallingFromPostinstallHook = () => {
71
- // individual folders
72
- const cwdFolders = process.cwd().split(path.sep);
73
- const length = cwdFolders.length;
74
- return cwdFolders[length - 2] === 'node_modules' && cwdFolders[length - 1] === 'cypress';
75
- };
76
- const getCacheDir = () => {
77
- let cache_directory = util.getCacheDir();
78
- if (util.getEnv('CYPRESS_CACHE_FOLDER')) {
79
- const envVarCacheDir = untildify(util.getEnv('CYPRESS_CACHE_FOLDER'));
80
- debug('using environment variable CYPRESS_CACHE_FOLDER %s', envVarCacheDir);
81
- if (!path.isAbsolute(envVarCacheDir) && isInstallingFromPostinstallHook()) {
82
- const packageRootFolder = path.join('..', '..', envVarCacheDir);
83
- cache_directory = path.resolve(packageRootFolder);
84
- debug('installing from postinstall hook, original root folder is %s', packageRootFolder);
85
- debug('and resolved cache directory is %s', cache_directory);
86
- } else {
87
- cache_directory = path.resolve(envVarCacheDir);
88
- }
89
- }
90
- return cache_directory;
91
- };
92
- const parseRealPlatformBinaryFolderAsync = binaryPath => {
93
- return fs.realpathAsync(binaryPath).then(realPath => {
94
- debug('CYPRESS_RUN_BINARY has realpath:', realPath);
95
- if (!realPath.toString().endsWith(getPlatformExecutable())) {
96
- return false;
97
- }
98
- if (os.platform() === 'darwin') {
99
- return path.resolve(realPath, '..', '..', '..');
100
- }
101
- return path.resolve(realPath, '..');
102
- });
103
- };
104
- const getDistDir = () => {
105
- return path.join(__dirname, '..', '..', 'dist');
106
- };
107
-
108
- /**
109
- * Returns full filename to the file that keeps the Test Runner verification state as JSON text.
110
- * Note: the binary state file will be stored one level up from the given binary folder.
111
- * @param {string} binaryDir - full path to the folder holding the binary.
112
- */
113
- const getBinaryStatePath = binaryDir => {
114
- return path.join(binaryDir, '..', 'binary_state.json');
115
- };
116
- const getBinaryStateContentsAsync = binaryDir => {
117
- const fullPath = getBinaryStatePath(binaryDir);
118
- return fs.readJsonAsync(fullPath).catch({
119
- code: 'ENOENT'
120
- }, SyntaxError, () => {
121
- debug('could not read binary_state.json file at "%s"', fullPath);
122
- return {};
123
- });
124
- };
125
- const getBinaryVerifiedAsync = binaryDir => {
126
- return getBinaryStateContentsAsync(binaryDir).tap(debug).get('verified');
127
- };
128
- const clearBinaryStateAsync = binaryDir => {
129
- return fs.removeAsync(getBinaryStatePath(binaryDir));
130
- };
131
-
132
- /**
133
- * Writes the new binary status.
134
- * @param {boolean} verified The new test runner state after smoke test
135
- * @param {string} binaryDir Folder holding the binary
136
- * @returns {Promise<void>} returns a promise
137
- */
138
- const writeBinaryVerifiedAsync = (verified, binaryDir) => {
139
- return getBinaryStateContentsAsync(binaryDir).then(contents => {
140
- return fs.outputJsonAsync(getBinaryStatePath(binaryDir), _.extend(contents, {
141
- verified
142
- }), {
143
- spaces: 2
144
- });
145
- });
146
- };
147
- const getPathToExecutable = binaryDir => {
148
- return path.join(binaryDir, getPlatformExecutable());
149
- };
150
-
151
- /**
152
- * Resolves with an object read from the binary app package.json file.
153
- * If the file does not exist resolves with null
154
- */
155
- const getBinaryPkgAsync = binaryDir => {
156
- const pathToPackageJson = getBinaryPkgPath(binaryDir);
157
- debug('Reading binary package.json from:', pathToPackageJson);
158
- return fs.pathExistsAsync(pathToPackageJson).then(exists => {
159
- if (!exists) {
160
- return null;
161
- }
162
- return fs.readJsonAsync(pathToPackageJson);
163
- });
164
- };
165
- const getBinaryPkgVersion = o => _.get(o, 'version', null);
166
- const getBinaryElectronVersion = o => _.get(o, 'electronVersion', null);
167
- const getBinaryElectronNodeVersion = o => _.get(o, 'electronNodeVersion', null);
168
- module.exports = {
169
- getPathToExecutable,
170
- getPlatformExecutable,
171
- // those names start to sound like Java
172
- getBinaryElectronNodeVersion,
173
- getBinaryElectronVersion,
174
- getBinaryPkgVersion,
175
- getBinaryVerifiedAsync,
176
- getBinaryPkgAsync,
177
- getBinaryPkgPath,
178
- getBinaryDir,
179
- getCacheDir,
180
- clearBinaryStateAsync,
181
- writeBinaryVerifiedAsync,
182
- parseRealPlatformBinaryFolderAsync,
183
- getDistDir,
184
- getVersionDir
185
- };