cypress 12.1.0 → 12.2.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.
package/lib/errors.js CHANGED
@@ -1,23 +1,19 @@
1
1
  "use strict";
2
2
 
3
3
  const chalk = require('chalk');
4
-
5
4
  const {
6
5
  stripIndent,
7
6
  stripIndents
8
7
  } = require('common-tags');
9
-
10
8
  const la = require('lazy-ass');
11
-
12
9
  const is = require('check-more-types');
13
-
14
10
  const util = require('./util');
15
-
16
11
  const state = require('./tasks/state');
17
-
18
12
  const docsUrl = 'https://on.cypress.io';
19
13
  const requiredDependenciesUrl = `${docsUrl}/required-dependencies`;
20
- const runDocumentationUrl = `${docsUrl}/cypress-run`; // TODO it would be nice if all error objects could be enforced via types
14
+ const runDocumentationUrl = `${docsUrl}/cypress-run`;
15
+
16
+ // TODO it would be nice if all error objects could be enforced via types
21
17
  // to only have description + solution properties
22
18
 
23
19
  const hr = '----------';
@@ -25,8 +21,9 @@ const genericErrorSolution = stripIndent`
25
21
  Search for an existing issue or open a GitHub issue at
26
22
 
27
23
  ${chalk.blue(util.issuesUrl)}
28
- `; // common errors Cypress application can encounter
24
+ `;
29
25
 
26
+ // common errors Cypress application can encounter
30
27
  const unknownError = {
31
28
  description: 'Unknown Cypress CLI error',
32
29
  solution: genericErrorSolution
@@ -64,7 +61,6 @@ const failedUnzipWindowsMaxPathLength = {
64
61
 
65
62
  Read here for solutions to this problem: https://on.cypress.io/win-max-path-length-error`
66
63
  };
67
-
68
64
  const missingApp = binaryDir => {
69
65
  return {
70
66
  description: `No version of Cypress is installed in: ${chalk.cyan(binaryDir)}`,
@@ -73,7 +69,6 @@ const missingApp = binaryDir => {
73
69
  `
74
70
  };
75
71
  };
76
-
77
72
  const binaryNotExecutable = executable => {
78
73
  return {
79
74
  description: `Cypress cannot run because this binary file does not have executable permissions here:\n\n${executable}`,
@@ -89,7 +84,6 @@ const binaryNotExecutable = executable => {
89
84
  `
90
85
  };
91
86
  };
92
-
93
87
  const notInstalledCI = executable => {
94
88
  return {
95
89
  description: 'The cypress npm package is installed, but the Cypress binary is missing.',
@@ -109,7 +103,6 @@ const notInstalledCI = executable => {
109
103
  `
110
104
  };
111
105
  };
112
-
113
106
  const nonZeroExitCodeXvfb = {
114
107
  description: 'Xvfb exited with a non zero exit code.',
115
108
  solution: stripIndent`
@@ -130,7 +123,6 @@ const missingXvfb = {
130
123
  If you are using Docker, we provide containers with all required dependencies installed.
131
124
  `
132
125
  };
133
-
134
126
  const smokeTestFailure = (smokeTestCommand, timedOut) => {
135
127
  return {
136
128
  description: `Cypress verification ${timedOut ? 'timed out' : 'failed'}.`,
@@ -142,11 +134,9 @@ const smokeTestFailure = (smokeTestCommand, timedOut) => {
142
134
  `
143
135
  };
144
136
  };
145
-
146
137
  const invalidSmokeTestDisplayError = {
147
138
  code: 'INVALID_SMOKE_TEST_DISPLAY_ERROR',
148
139
  description: 'Cypress verification failed.',
149
-
150
140
  solution(msg) {
151
141
  return stripIndent`
152
142
  Cypress failed to start after spawning a new Xvfb server.
@@ -164,7 +154,6 @@ const invalidSmokeTestDisplayError = {
164
154
  Please refer to the error above for more detail.
165
155
  `;
166
156
  }
167
-
168
157
  };
169
158
  const missingDependency = {
170
159
  description: 'Cypress failed to start.',
@@ -226,6 +215,7 @@ const invalidConfigFile = {
226
215
  description: '`--config-file` cannot be false.',
227
216
  solution: 'Either pass a relative path to a valid Cypress config file or remove this option.'
228
217
  };
218
+
229
219
  /**
230
220
  * This error happens when CLI detects that the child Test Runner process
231
221
  * was killed with a signal, like SIGBUS
@@ -233,14 +223,12 @@ const invalidConfigFile = {
233
223
  * @param {'close'|'event'} eventName Child close event name
234
224
  * @param {string} signal Signal that closed the child process, like "SIGBUS"
235
225
  */
236
-
237
226
  const childProcessKilled = (eventName, signal) => {
238
227
  return {
239
228
  description: `The Test Runner unexpectedly exited via a ${chalk.cyan(eventName)} event with signal ${chalk.cyan(signal)}`,
240
229
  solution: solutionUnknown
241
230
  };
242
231
  };
243
-
244
232
  const CYPRESS_RUN_BINARY = {
245
233
  notValid: value => {
246
234
  const properFormat = `**/${state.getPlatformExecutable()}`;
@@ -250,14 +238,15 @@ const CYPRESS_RUN_BINARY = {
250
238
  };
251
239
  }
252
240
  };
253
-
254
241
  function addPlatformInformation(info) {
255
242
  return util.getPlatformInfo().then(platform => {
256
- return { ...info,
243
+ return {
244
+ ...info,
257
245
  platform
258
246
  };
259
247
  });
260
248
  }
249
+
261
250
  /**
262
251
  * Given an error object (see the errors above), forms error message text with details,
263
252
  * then resolves with Error instance you can throw or reject with.
@@ -270,8 +259,6 @@ function addPlatformInformation(info) {
270
259
  return getError(errorObject).then(reject)
271
260
  ```
272
261
  */
273
-
274
-
275
262
  function getError(errorObject) {
276
263
  return formErrorText(errorObject).then(errorMessage => {
277
264
  const err = new Error(errorMessage);
@@ -279,23 +266,21 @@ function getError(errorObject) {
279
266
  return err;
280
267
  });
281
268
  }
269
+
282
270
  /**
283
271
  * Forms nice error message with error and platform information,
284
272
  * and if possible a way to solve it. Resolves with a string.
285
273
  */
286
-
287
-
288
274
  function formErrorText(info, msg, prevMessage) {
289
275
  return addPlatformInformation(info).then(obj => {
290
276
  const formatted = [];
291
-
292
277
  function add(msg) {
293
278
  formatted.push(stripIndents(msg));
294
279
  }
280
+ la(is.unemptyString(obj.description), 'expected error description to be text', obj.description);
295
281
 
296
- la(is.unemptyString(obj.description), 'expected error description to be text', obj.description); // assuming that if there the solution is a function it will handle
282
+ // assuming that if there the solution is a function it will handle
297
283
  // error message and (optional previous error message)
298
-
299
284
  if (is.fn(obj.solution)) {
300
285
  const text = obj.solution(msg, prevMessage);
301
286
  la(is.unemptyString(text), 'expected solution to be text', text);
@@ -313,7 +298,6 @@ function formErrorText(info, msg, prevMessage) {
313
298
  ${obj.solution}
314
299
 
315
300
  `);
316
-
317
301
  if (msg) {
318
302
  add(`
319
303
  ${hr}
@@ -323,13 +307,11 @@ function formErrorText(info, msg, prevMessage) {
323
307
  `);
324
308
  }
325
309
  }
326
-
327
310
  add(`
328
311
  ${hr}
329
312
 
330
313
  ${obj.platform}
331
314
  `);
332
-
333
315
  if (obj.footer) {
334
316
  add(`
335
317
 
@@ -338,37 +320,31 @@ function formErrorText(info, msg, prevMessage) {
338
320
  ${obj.footer}
339
321
  `);
340
322
  }
341
-
342
323
  return formatted.join('\n\n');
343
324
  });
344
325
  }
345
-
346
326
  const raise = info => {
347
327
  return text => {
348
328
  const err = new Error(text);
349
-
350
329
  if (info.code) {
351
330
  err.code = info.code;
352
331
  }
353
-
354
332
  err.known = true;
355
333
  throw err;
356
334
  };
357
335
  };
358
-
359
336
  const throwFormErrorText = info => {
360
337
  return (msg, prevMessage) => {
361
338
  return formErrorText(info, msg, prevMessage).then(raise(info));
362
339
  };
363
340
  };
341
+
364
342
  /**
365
343
  * Forms full error message with error and OS details, prints to the error output
366
344
  * and then exits the process.
367
345
  * @param {ErrorInformation} info Error information {description, solution}
368
346
  * @example return exitWithError(errors.invalidCypressEnv)('foo')
369
347
  */
370
-
371
-
372
348
  const exitWithError = info => {
373
349
  return msg => {
374
350
  return formErrorText(info, msg).then(text => {
@@ -378,7 +354,6 @@ const exitWithError = info => {
378
354
  });
379
355
  };
380
356
  };
381
-
382
357
  module.exports = {
383
358
  raise,
384
359
  exitWithError,
package/lib/exec/info.js CHANGED
@@ -2,55 +2,43 @@
2
2
 
3
3
  /* eslint-disable no-console */
4
4
  const spawn = require('./spawn');
5
-
6
5
  const util = require('../util');
7
-
8
6
  const state = require('../tasks/state');
9
-
10
7
  const os = require('os');
11
-
12
8
  const chalk = require('chalk');
13
-
14
9
  const prettyBytes = require('pretty-bytes');
10
+ const _ = require('lodash');
15
11
 
16
- const _ = require('lodash'); // color for numbers and show values
17
-
18
-
19
- const g = chalk.green; // color for paths
20
-
12
+ // color for numbers and show values
13
+ const g = chalk.green;
14
+ // color for paths
21
15
  const p = chalk.cyan;
22
- const red = chalk.red; // urls
23
-
24
- const link = chalk.blue.underline; // to be exported
16
+ const red = chalk.red;
17
+ // urls
18
+ const link = chalk.blue.underline;
25
19
 
20
+ // to be exported
26
21
  const methods = {};
27
-
28
22
  methods.findProxyEnvironmentVariables = () => {
29
23
  return _.pick(process.env, ['HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY']);
30
24
  };
31
-
32
25
  const maskSensitiveVariables = obj => {
33
- const masked = { ...obj
26
+ const masked = {
27
+ ...obj
34
28
  };
35
-
36
29
  if (masked.CYPRESS_RECORD_KEY) {
37
30
  masked.CYPRESS_RECORD_KEY = '<redacted>';
38
31
  }
39
-
40
32
  return masked;
41
33
  };
42
-
43
34
  methods.findCypressEnvironmentVariables = () => {
44
35
  const isCyVariable = (val, key) => key.startsWith('CYPRESS_');
45
-
46
36
  return _.pickBy(process.env, isCyVariable);
47
37
  };
48
-
49
38
  const formatCypressVariables = () => {
50
39
  const vars = methods.findCypressEnvironmentVariables();
51
40
  return maskSensitiveVariables(vars);
52
41
  };
53
-
54
42
  methods.start = async (options = {}) => {
55
43
  const args = ['--mode=info'];
56
44
  await spawn.start(args, {
@@ -58,33 +46,26 @@ methods.start = async (options = {}) => {
58
46
  });
59
47
  console.log();
60
48
  const proxyVars = methods.findProxyEnvironmentVariables();
61
-
62
49
  if (_.isEmpty(proxyVars)) {
63
50
  console.log('Proxy Settings: none detected');
64
51
  } else {
65
52
  console.log('Proxy Settings:');
66
-
67
53
  _.forEach(proxyVars, (value, key) => {
68
54
  console.log('%s: %s', key, g(value));
69
55
  });
70
-
71
56
  console.log();
72
57
  console.log('Learn More: %s', link('https://on.cypress.io/proxy-configuration'));
73
58
  console.log();
74
59
  }
75
-
76
60
  const cyVars = formatCypressVariables();
77
-
78
61
  if (_.isEmpty(cyVars)) {
79
62
  console.log('Environment Variables: none detected');
80
63
  } else {
81
64
  console.log('Environment Variables:');
82
-
83
65
  _.forEach(cyVars, (value, key) => {
84
66
  console.log('%s: %s', key, g(value));
85
67
  });
86
68
  }
87
-
88
69
  console.log();
89
70
  console.log('Application Data:', p(util.getApplicationDataFolder()));
90
71
  console.log('Browser Profiles:', p(util.getApplicationDataFolder('browsers')));
@@ -96,7 +77,6 @@ methods.start = async (options = {}) => {
96
77
  console.log('Cypress Version: %s', g(util.pkgVersion()), isStable ? g('(stable)') : red('(pre-release)'));
97
78
  console.log('System Platform: %s (%s)', g(os.platform()), g(osVersion));
98
79
  console.log('System Memory: %s free %s', g(prettyBytes(os.totalmem())), g(prettyBytes(os.freemem())));
99
-
100
80
  if (!buildInfo) {
101
81
  console.log();
102
82
  console.log('This is the', red('development'), '(un-built) Cypress CLI.');
@@ -109,5 +89,4 @@ methods.start = async (options = {}) => {
109
89
  console.log(' Commit Date:', g(buildInfo.commitDate));
110
90
  }
111
91
  };
112
-
113
92
  module.exports = methods;
package/lib/exec/open.js CHANGED
@@ -1,21 +1,17 @@
1
1
  "use strict";
2
2
 
3
3
  const debug = require('debug')('cypress:cli');
4
-
5
4
  const util = require('../util');
6
-
7
5
  const spawn = require('./spawn');
8
-
9
6
  const verify = require('../tasks/verify');
10
-
11
7
  const {
12
8
  processTestingType,
13
9
  checkConfigFile
14
10
  } = require('./shared');
15
-
16
11
  const {
17
12
  exitWithError
18
13
  } = require('../errors');
14
+
19
15
  /**
20
16
  * Maps options collected by the CLI
21
17
  * and forms list of CLI arguments to the server.
@@ -25,8 +21,6 @@ const {
25
21
  *
26
22
  * @returns {string[]} list of CLI arguments
27
23
  */
28
-
29
-
30
24
  const processOpenOptions = (options = {}) => {
31
25
  // In addition to setting the project directory, setting the project option
32
26
  // here ultimately decides whether cypress is run in global mode or not.
@@ -37,55 +31,42 @@ const processOpenOptions = (options = {}) => {
37
31
  if (!util.isInstalledGlobally() && !options.global && !options.project) {
38
32
  options.project = process.cwd();
39
33
  }
40
-
41
34
  const args = [];
42
-
43
35
  if (options.config) {
44
36
  args.push('--config', options.config);
45
37
  }
46
-
47
38
  if (options.configFile !== undefined) {
48
39
  checkConfigFile(options);
49
40
  args.push('--config-file', options.configFile);
50
41
  }
51
-
52
42
  if (options.browser) {
53
43
  args.push('--browser', options.browser);
54
44
  }
55
-
56
45
  if (options.env) {
57
46
  args.push('--env', options.env);
58
47
  }
59
-
60
48
  if (options.port) {
61
49
  args.push('--port', options.port);
62
50
  }
63
-
64
51
  if (options.project) {
65
52
  args.push('--project', options.project);
66
53
  }
67
-
68
54
  if (options.global) {
69
55
  args.push('--global', options.global);
70
56
  }
71
-
72
57
  if (options.inspect) {
73
58
  args.push('--inspect');
74
59
  }
75
-
76
60
  if (options.inspectBrk) {
77
61
  args.push('--inspectBrk');
78
62
  }
79
-
80
63
  args.push(...processTestingType(options));
81
64
  debug('opening from options %j', options);
82
65
  debug('command line arguments %j', args);
83
66
  return args;
84
67
  };
85
-
86
68
  module.exports = {
87
69
  processOpenOptions,
88
-
89
70
  start(options = {}) {
90
71
  function open() {
91
72
  try {
@@ -98,16 +79,12 @@ module.exports = {
98
79
  if (err.details) {
99
80
  return exitWithError(err.details)();
100
81
  }
101
-
102
82
  throw err;
103
83
  }
104
84
  }
105
-
106
85
  if (options.dev) {
107
86
  return open();
108
87
  }
109
-
110
88
  return verify.start().then(open);
111
89
  }
112
-
113
90
  };
package/lib/exec/run.js CHANGED
@@ -1,44 +1,36 @@
1
1
  "use strict";
2
2
 
3
3
  const _ = require('lodash');
4
-
5
4
  const debug = require('debug')('cypress:cli:run');
6
-
7
5
  const util = require('../util');
8
-
9
6
  const spawn = require('./spawn');
10
-
11
7
  const verify = require('../tasks/verify');
12
-
13
8
  const {
14
9
  exitWithError,
15
10
  errors
16
11
  } = require('../errors');
17
-
18
12
  const {
19
13
  processTestingType,
20
14
  throwInvalidOptionError,
21
15
  checkConfigFile
22
16
  } = require('./shared');
17
+
23
18
  /**
24
19
  * Typically a user passes a string path to the project.
25
20
  * But "cypress open" allows using `false` to open in global mode,
26
21
  * and the user can accidentally execute `cypress run --project false`
27
22
  * which should be invalid.
28
23
  */
29
-
30
-
31
24
  const isValidProject = v => {
32
25
  if (typeof v === 'boolean') {
33
26
  return false;
34
27
  }
35
-
36
28
  if (v === '' || v === 'false' || v === 'true') {
37
29
  return false;
38
30
  }
39
-
40
31
  return true;
41
32
  };
33
+
42
34
  /**
43
35
  * Maps options collected by the CLI
44
36
  * and forms list of CLI arguments to the server.
@@ -48,129 +40,105 @@ const isValidProject = v => {
48
40
  *
49
41
  * @returns {string[]} list of CLI arguments
50
42
  */
51
-
52
-
53
43
  const processRunOptions = (options = {}) => {
54
44
  debug('processing run options %o', options);
55
-
56
45
  if (!isValidProject(options.project)) {
57
46
  debug('invalid project option %o', {
58
47
  project: options.project
59
48
  });
60
49
  return throwInvalidOptionError(errors.invalidRunProjectPath);
61
50
  }
62
-
63
51
  const args = ['--run-project', options.project];
64
-
65
52
  if (options.browser) {
66
53
  args.push('--browser', options.browser);
67
54
  }
68
-
69
55
  if (options.ciBuildId) {
70
56
  args.push('--ci-build-id', options.ciBuildId);
71
57
  }
72
-
73
58
  if (options.config) {
74
59
  args.push('--config', options.config);
75
60
  }
76
-
77
61
  if (options.configFile !== undefined) {
78
62
  checkConfigFile(options);
79
63
  args.push('--config-file', options.configFile);
80
64
  }
81
-
82
65
  if (options.env) {
83
66
  args.push('--env', options.env);
84
67
  }
85
-
86
68
  if (options.exit === false) {
87
69
  args.push('--no-exit');
88
70
  }
89
-
90
71
  if (options.group) {
91
72
  args.push('--group', options.group);
92
73
  }
93
-
94
74
  if (options.headed) {
95
75
  args.push('--headed', options.headed);
96
76
  }
97
-
98
77
  if (options.headless) {
99
78
  if (options.headed) {
100
79
  return throwInvalidOptionError(errors.incompatibleHeadlessFlags);
101
80
  }
102
-
103
81
  args.push('--headed', !options.headless);
104
- } // if key is set use that - else attempt to find it by environment variable
105
-
82
+ }
106
83
 
84
+ // if key is set use that - else attempt to find it by environment variable
107
85
  if (options.key == null) {
108
86
  debug('--key is not set, looking up environment variable CYPRESS_RECORD_KEY');
109
87
  options.key = util.getEnv('CYPRESS_RECORD_KEY');
110
- } // if we have a key assume we're in record mode
111
-
88
+ }
112
89
 
90
+ // if we have a key assume we're in record mode
113
91
  if (options.key) {
114
92
  args.push('--key', options.key);
115
93
  }
116
-
117
94
  if (options.outputPath) {
118
95
  args.push('--output-path', options.outputPath);
119
96
  }
120
-
121
97
  if (options.parallel) {
122
98
  args.push('--parallel');
123
99
  }
124
-
125
100
  if (options.port) {
126
101
  args.push('--port', options.port);
127
102
  }
128
-
129
103
  if (options.quiet) {
130
104
  args.push('--quiet');
131
- } // if record is defined and we're not
132
- // already in ci mode, then send it up
133
-
105
+ }
134
106
 
107
+ // if record is defined and we're not
108
+ // already in ci mode, then send it up
135
109
  if (options.record != null) {
136
110
  args.push('--record', options.record);
137
- } // if we have a specific reporter push that into the args
138
-
111
+ }
139
112
 
113
+ // if we have a specific reporter push that into the args
140
114
  if (options.reporter) {
141
115
  args.push('--reporter', options.reporter);
142
- } // if we have a specific reporter push that into the args
143
-
116
+ }
144
117
 
118
+ // if we have a specific reporter push that into the args
145
119
  if (options.reporterOptions) {
146
120
  args.push('--reporter-options', options.reporterOptions);
147
- } // if we have specific spec(s) push that into the args
148
-
121
+ }
149
122
 
123
+ // if we have specific spec(s) push that into the args
150
124
  if (options.spec) {
151
125
  args.push('--spec', options.spec);
152
126
  }
153
-
154
127
  if (options.tag) {
155
128
  args.push('--tag', options.tag);
156
129
  }
157
-
158
130
  if (options.inspect) {
159
131
  args.push('--inspect');
160
132
  }
161
-
162
133
  if (options.inspectBrk) {
163
134
  args.push('--inspectBrk');
164
135
  }
165
-
166
136
  args.push(...processTestingType(options));
167
137
  return args;
168
138
  };
169
-
170
139
  module.exports = {
171
140
  processRunOptions,
172
141
  isValidProject,
173
-
174
142
  // resolves with the number of failed tests
175
143
  start(options = {}) {
176
144
  _.defaults(options, {
@@ -180,7 +148,6 @@ module.exports = {
180
148
  reporterOptions: null,
181
149
  project: process.cwd()
182
150
  });
183
-
184
151
  function run() {
185
152
  try {
186
153
  const args = processRunOptions(options);
@@ -192,16 +159,12 @@ module.exports = {
192
159
  if (err.details) {
193
160
  return exitWithError(err.details)();
194
161
  }
195
-
196
162
  throw err;
197
163
  }
198
164
  }
199
-
200
165
  if (options.dev) {
201
166
  return run();
202
167
  }
203
-
204
168
  return verify.start().then(run);
205
169
  }
206
-
207
170
  };