cypress 3.0.3 → 3.1.3

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/cli.js CHANGED
@@ -21,6 +21,7 @@ function unknownOption(flag) {
21
21
  var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'option';
22
22
 
23
23
  if (this._allowUnknownOption) return;
24
+
24
25
  logger.error();
25
26
  logger.error(' error: unknown ' + type + ':', flag);
26
27
  logger.error();
@@ -35,7 +36,7 @@ var coerceFalse = function coerceFalse(arg) {
35
36
  };
36
37
 
37
38
  var parseOpts = function parseOpts(opts) {
38
- opts = _.pick(opts, 'project', 'spec', 'reporter', 'reporterOptions', 'path', 'destination', 'port', 'env', 'cypressVersion', 'config', 'record', 'key', 'browser', 'detached', 'headed', 'global', 'dev', 'force', 'exit', 'cachePath', 'cacheList', 'cacheClear');
39
+ opts = _.pick(opts, 'project', 'spec', 'reporter', 'reporterOptions', 'path', 'destination', 'port', 'env', 'cypressVersion', 'config', 'record', 'key', 'browser', 'detached', 'headed', 'global', 'dev', 'force', 'exit', 'cachePath', 'cacheList', 'cacheClear', 'parallel', 'group', 'ciBuildId');
39
40
 
40
41
  if (opts.exit) {
41
42
  opts = _.omit(opts, 'exit');
@@ -59,14 +60,17 @@ var descriptions = {
59
60
  detached: 'runs Cypress application in detached mode',
60
61
  project: 'path to the project',
61
62
  global: 'force Cypress into global mode as if its globally installed',
62
- version: 'Prints Cypress version',
63
+ version: 'prints Cypress version',
63
64
  headed: 'displays the Electron browser instead of running headlessly',
64
65
  dev: 'runs cypress in development and bypasses binary check',
65
66
  forceInstall: 'force install the Cypress binary',
66
67
  exit: 'keep the browser open after tests finish',
67
68
  cachePath: 'print the cypress binary cache path',
68
69
  cacheList: 'list the currently cached versions',
69
- cacheClear: 'delete the Cypress binary cache'
70
+ cacheClear: 'delete the Cypress binary cache',
71
+ group: 'a named group for recorded runs in the Cypress dashboard',
72
+ parallel: 'enables concurrent runs and automatic load balancing of specs across multiple machines or processes',
73
+ ciBuildId: 'the unique identifier for a run on your CI provider. typically a "BUILD_ID" env var. this value is automatically detected for most CI providers'
70
74
  };
71
75
 
72
76
  var knownCommands = ['version', 'run', 'open', 'install', 'verify', '-v', '--version', 'help', '-h', '--help', 'cache'];
@@ -85,6 +89,7 @@ function includesVersion(args) {
85
89
 
86
90
  function showVersions() {
87
91
  debug('printing Cypress version');
92
+
88
93
  return require('./exec/versions').getVersions().then(function () {
89
94
  var versions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
90
95
 
@@ -112,7 +117,7 @@ module.exports = {
112
117
 
113
118
  program.option('-v, --version', text('version')).command('version').description(text('version')).action(showVersions);
114
119
 
115
- program.command('run').usage('[options]').description('Runs Cypress tests from the CLI without the GUI').option('--record [bool]', text('record'), coerceFalse).option('--headed', text('headed')).option('-k, --key <record-key>', text('key')).option('-s, --spec <spec>', text('spec')).option('-r, --reporter <reporter>', text('reporter')).option('-o, --reporter-options <reporter-options>', text('reporterOptions')).option('-p, --port <port>', text('port')).option('-e, --env <env>', text('env')).option('-c, --config <config>', text('config')).option('-b, --browser <browser-name>', text('browser')).option('-P, --project <project-path>', text('project')).option('--no-exit', text('exit')).option('--dev', text('dev'), coerceFalse).action(function (opts) {
120
+ program.command('run').usage('[options]').description('Runs Cypress tests from the CLI without the GUI').option('--record [bool]', text('record'), coerceFalse).option('--headed', text('headed')).option('-k, --key <record-key>', text('key')).option('-s, --spec <spec>', text('spec')).option('-r, --reporter <reporter>', text('reporter')).option('-o, --reporter-options <reporter-options>', text('reporterOptions')).option('-p, --port <port>', text('port')).option('-e, --env <env>', text('env')).option('-c, --config <config>', text('config')).option('-b, --browser <browser-name>', text('browser')).option('-P, --project <project-path>', text('project')).option('--parallel', text('parallel')).option('--group <name>', text('group')).option('--ci-build-id <id>', text('ciBuildId')).option('--no-exit', text('exit')).option('--dev', text('dev'), coerceFalse).action(function (opts) {
116
121
  debug('running Cypress');
117
122
  require('./exec/run').start(parseOpts(opts)).then(util.exit).catch(util.logErrorExit1);
118
123
  });
@@ -130,6 +135,7 @@ module.exports = {
130
135
  var defaultOpts = { force: true, welcomeMessage: false };
131
136
  var parsedOpts = parseOpts(opts);
132
137
  var options = _.extend(parsedOpts, defaultOpts);
138
+
133
139
  require('./tasks/verify').start(options).catch(util.logErrorExit1);
134
140
  });
135
141
 
@@ -137,6 +143,7 @@ module.exports = {
137
143
  if (opts.command || !_.includes(['list', 'path', 'clear'], opts)) {
138
144
  unknownOption.call(this, 'cache ' + opts, 'sub-command');
139
145
  }
146
+
140
147
  cache[opts]();
141
148
  });
142
149
 
@@ -153,10 +160,12 @@ module.exports = {
153
160
  // Deprecated Catches
154
161
 
155
162
  var firstCommand = args[2];
163
+
156
164
  if (!_.includes(knownCommands, firstCommand)) {
157
165
  debug('unknown command %s', firstCommand);
158
166
  logger.error('Unknown command', '"' + firstCommand + '"');
159
167
  program.outputHelp();
168
+
160
169
  return util.exit(1);
161
170
  }
162
171
 
@@ -167,7 +176,9 @@ module.exports = {
167
176
  // so we have to manually catch '-v, --version'
168
177
  return showVersions();
169
178
  }
179
+
170
180
  debug('program parsing arguments');
181
+
171
182
  return program.parse(args);
172
183
  }
173
184
  };
package/lib/cypress.js CHANGED
@@ -15,6 +15,7 @@ var cypressModuleApi = {
15
15
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16
16
 
17
17
  options = util.normalizeModuleOptions(options);
18
+
18
19
  return _open.start(options);
19
20
  },
20
21
  run: function run() {
@@ -33,6 +34,7 @@ var cypressModuleApi = {
33
34
  message: 'Could not find Cypress test run results'
34
35
  };
35
36
  }
37
+
36
38
  return output;
37
39
  });
38
40
  });
package/lib/errors.js CHANGED
@@ -3,7 +3,7 @@
3
3
  var _templateObject = _taggedTemplateLiteral(['\n Search for an existing issue or open a GitHub issue at\n\n ', '\n '], ['\n Search for an existing issue or open a GitHub issue at\n\n ', '\n ']),
4
4
  _templateObject2 = _taggedTemplateLiteral(['\n \nPlease reinstall Cypress by running: ', '\n '], ['\n \\nPlease reinstall Cypress by running: ', '\n ']),
5
5
  _templateObject3 = _taggedTemplateLiteral(['\n\n Reasons this may happen:\n \n - node was installed as \'root\' or with \'sudo\'\n - the cypress npm package as \'root\' or with \'sudo\'\n \n Please check that you have the appropriate user permissions.\n '], ['\\n\n Reasons this may happen:\n \n - node was installed as \'root\' or with \'sudo\'\n - the cypress npm package as \'root\' or with \'sudo\'\n \n Please check that you have the appropriate user permissions.\n ']),
6
- _templateObject4 = _taggedTemplateLiteral(['\n\n We expected the binary to be installed here: ', '\n \n Reasons it may be missing:\n\n - You\'re caching \'node_modules\' but are not caching this path: ', '\n - You ran \'npm install\' at an earlier build step but did not persist: ', '\n\n Properly caching the binary will fix this error and avoid downloading and unzipping Cypress.\n\n Alternatively, you can run \'cypress install\' to download the binary again.\n\n https://on.cypress.io/not-installed-ci-error\n '], ['\\n\n We expected the binary to be installed here: ', '\n \n Reasons it may be missing:\n\n - You\'re caching \'node_modules\' but are not caching this path: ', '\n - You ran \'npm install\' at an earlier build step but did not persist: ', '\n\n Properly caching the binary will fix this error and avoid downloading and unzipping Cypress.\n\n Alternatively, you can run \'cypress install\' to download the binary again.\n\n https://on.cypress.io/not-installed-ci-error\n ']),
6
+ _templateObject4 = _taggedTemplateLiteral(['\n\n We expected the binary to be installed here: ', '\n \n Reasons it may be missing:\n\n - You\'re caching \'node_modules\' but are not caching this path: ', '\n - You ran \'npm install\' at an earlier build step but did not persist: ', '\n\n Properly caching the binary will fix this error and avoid downloading and unzipping Cypress.\n\n Alternatively, you can run \'cypress install\' to download the binary again.\n\n ', '\n '], ['\\n\n We expected the binary to be installed here: ', '\n \n Reasons it may be missing:\n\n - You\'re caching \'node_modules\' but are not caching this path: ', '\n - You ran \'npm install\' at an earlier build step but did not persist: ', '\n\n Properly caching the binary will fix this error and avoid downloading and unzipping Cypress.\n\n Alternatively, you can run \'cypress install\' to download the binary again.\n\n ', '\n ']),
7
7
  _templateObject5 = _taggedTemplateLiteral(['\n There was a problem spawning Xvfb.\n\n This is likely a problem with your system, permissions, or installation of Xvfb.\n '], ['\n There was a problem spawning Xvfb.\n\n This is likely a problem with your system, permissions, or installation of Xvfb.\n ']),
8
8
  _templateObject6 = _taggedTemplateLiteral(['\n Install XVFB and run Cypress again.\n\n Read our documentation on dependencies for more information:\n\n ', '\n\n If you are using Docker, we provide containers with all required dependencies installed.\n '], ['\n Install XVFB and run Cypress again.\n\n Read our documentation on dependencies for more information:\n\n ', '\n\n If you are using Docker, we provide containers with all required dependencies installed.\n ']),
9
9
  _templateObject7 = _taggedTemplateLiteral(['\n This is usually caused by a missing library or dependency.\n\n The error below should indicate which dependency is missing.\n\n ', '\n\n If you are using Docker, we provide containers with all required dependencies installed.\n '], ['\n This is usually caused by a missing library or dependency.\n\n The error below should indicate which dependency is missing.\n\n ', '\n\n If you are using Docker, we provide containers with all required dependencies installed.\n ']),
@@ -42,7 +42,7 @@ var failedDownload = {
42
42
 
43
43
  var failedUnzip = {
44
44
  description: 'The Cypress App could not be unzipped.',
45
- solution: stripIndent(_templateObject, issuesUrl)
45
+ solution: stripIndent(_templateObject, chalk.blue(issuesUrl))
46
46
  };
47
47
 
48
48
  var missingApp = function missingApp(binaryDir) {
@@ -62,7 +62,7 @@ var binaryNotExecutable = function binaryNotExecutable(executable) {
62
62
  var notInstalledCI = function notInstalledCI(executable) {
63
63
  return {
64
64
  description: 'The cypress npm package is installed, but the Cypress binary is missing.',
65
- solution: stripIndent(_templateObject4, chalk.cyan(executable), util.getCacheDir(), util.getCacheDir())
65
+ solution: stripIndent(_templateObject4, chalk.cyan(executable), util.getCacheDir(), util.getCacheDir(), chalk.blue('https://on.cypress.io/not-installed-ci-error'))
66
66
  };
67
67
  };
68
68
 
@@ -73,13 +73,13 @@ var nonZeroExitCodeXvfb = {
73
73
 
74
74
  var missingXvfb = {
75
75
  description: 'Your system is missing the dependency: XVFB',
76
- solution: stripIndent(_templateObject6, requiredDependenciesUrl)
76
+ solution: stripIndent(_templateObject6, chalk.blue(requiredDependenciesUrl))
77
77
  };
78
78
 
79
79
  var missingDependency = {
80
80
  description: 'Cypress failed to start.',
81
81
  // this message is too Linux specific
82
- solution: stripIndent(_templateObject7, requiredDependenciesUrl)
82
+ solution: stripIndent(_templateObject7, chalk.blue(requiredDependenciesUrl))
83
83
  };
84
84
 
85
85
  var invalidCacheDirectory = {
@@ -94,7 +94,7 @@ var versionMismatch = {
94
94
 
95
95
  var unexpected = {
96
96
  description: 'An unexpected error occurred while verifying the Cypress executable.',
97
- solution: stripIndent(_templateObject8, docsUrl, issuesUrl)
97
+ solution: stripIndent(_templateObject8, chalk.blue(docsUrl), chalk.blue(issuesUrl))
98
98
  };
99
99
 
100
100
  var removed = {
@@ -111,6 +111,7 @@ var removed = {
111
111
  var CYPRESS_RUN_BINARY = {
112
112
  notValid: function notValid(value) {
113
113
  var properFormat = '**/' + state.getPlatformExecutable();
114
+
114
115
  return {
115
116
  description: 'Could not run binary set by environment variable CYPRESS_RUN_BINARY=' + value,
116
117
  solution: 'Ensure the environment variable is a path to the Cypress binary, matching ' + properFormat
@@ -158,6 +159,7 @@ function formErrorText(info, msg) {
158
159
 
159
160
  var raise = function raise(text) {
160
161
  var err = new Error(text);
162
+
161
163
  err.known = true;
162
164
  throw err;
163
165
  };
package/lib/exec/run.js CHANGED
@@ -68,6 +68,18 @@ var processRunOptions = function processRunOptions() {
68
68
  args.push('--record', options.record);
69
69
  }
70
70
 
71
+ if (options.parallel) {
72
+ args.push('--parallel');
73
+ }
74
+
75
+ if (options.group) {
76
+ args.push('--group', options.group);
77
+ }
78
+
79
+ if (options.ciBuildId) {
80
+ args.push('--ci-build-id', options.ciBuildId);
81
+ }
82
+
71
83
  if (options.outputPath) {
72
84
  args.push('--output-path', options.outputPath);
73
85
  }
package/lib/exec/spawn.js CHANGED
@@ -80,6 +80,7 @@ module.exports = {
80
80
  }
81
81
 
82
82
  var overrides = util.getEnvOverrides();
83
+ var node11WindowsFix = isPlatform('win32');
83
84
 
84
85
  debug('spawning Cypress with executable: %s', executable);
85
86
  debug('spawn forcing env overrides %o', overrides);
@@ -93,8 +94,12 @@ module.exports = {
93
94
  // also figure out whether we should force stdout and stderr into thinking
94
95
  // it is a tty as opposed to a pipe.
95
96
  options.env = _.extend({}, options.env, overrides);
97
+ if (node11WindowsFix) {
98
+ options = _.extend({}, options, { windowsHide: false });
99
+ }
96
100
 
97
101
  var child = cp.spawn(executable, args, options);
102
+
98
103
  child.on('close', resolve);
99
104
  child.on('error', reject);
100
105
 
@@ -141,8 +146,8 @@ module.exports = {
141
146
 
142
147
  if (needsXvfb) {
143
148
  return xvfb.start().then(userFriendlySpawn).finally(xvfb.stop);
144
- } else {
145
- return userFriendlySpawn();
146
149
  }
150
+
151
+ return userFriendlySpawn();
147
152
  }
148
153
  };
@@ -16,10 +16,12 @@ var getVersions = function getVersions() {
16
16
 
17
17
  if (util.getEnv('CYPRESS_RUN_BINARY')) {
18
18
  var envBinaryPath = path.resolve(util.getEnv('CYPRESS_RUN_BINARY'));
19
+
19
20
  return state.parseRealPlatformBinaryFolderAsync(envBinaryPath).then(function (envBinaryDir) {
20
21
  if (!envBinaryDir) {
21
22
  return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))();
22
23
  }
24
+
23
25
  debug('CYPRESS_RUN_BINARY has binaryDir:', envBinaryDir);
24
26
 
25
27
  return envBinaryDir;
@@ -27,6 +29,7 @@ var getVersions = function getVersions() {
27
29
  return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))(err.message);
28
30
  });
29
31
  }
32
+
30
33
  return state.getBinaryDir();
31
34
  }).then(state.getBinaryPkgVersionAsync).then(function (binaryVersion) {
32
35
  return {
package/lib/exec/xvfb.js CHANGED
@@ -27,6 +27,7 @@ module.exports = {
27
27
 
28
28
  start: function start() {
29
29
  debug('Starting XVFB');
30
+
30
31
  return xvfb.startAsync().catch({ nonZeroExitCode: true }, throwFormErrorText(errors.nonZeroExitCodeXvfb)).catch(function (err) {
31
32
  if (err.known) {
32
33
  throw err;
@@ -37,6 +38,7 @@ module.exports = {
37
38
  },
38
39
  stop: function stop() {
39
40
  debug('Stopping XVFB');
41
+
40
42
  return xvfb.stopAsync();
41
43
  },
42
44
  isNeeded: function isNeeded() {
@@ -48,6 +50,7 @@ module.exports = {
48
50
  verify: function verify() {
49
51
  return xvfb.startAsync().then(R.T).catch(function (err) {
50
52
  debug('Could not verify xvfb: %s', err.message);
53
+
51
54
  return false;
52
55
  }).finally(xvfb.stopAsync);
53
56
  }
package/lib/logger.js CHANGED
@@ -24,6 +24,7 @@ var warn = function warn() {
24
24
  }
25
25
 
26
26
  if (logLevel() === 'silent') return;
27
+
27
28
  logs.push(messages.join(' '));
28
29
  console.log(chalk.yellow.apply(chalk, messages)); // eslint-disable-line no-console
29
30
  };
@@ -36,6 +37,7 @@ var log = function log() {
36
37
  }
37
38
 
38
39
  if (logLevel() === 'silent' || logLevel() === 'warn') return;
40
+
39
41
  logs.push(messages.join(' '));
40
42
  (_console = console).log.apply(_console, messages); // eslint-disable-line no-console
41
43
  };
@@ -44,6 +46,7 @@ var log = function log() {
44
46
  // on each one to allow easy unit testing for specific message
45
47
  var logLines = function logLines(text) {
46
48
  var lines = text.split('\n');
49
+
47
50
  R.forEach(log, lines);
48
51
  };
49
52
 
@@ -7,6 +7,7 @@ var util = require('../util');
7
7
 
8
8
  var path = function path() {
9
9
  logger.log(state.getCacheDir());
10
+
10
11
  return undefined;
11
12
  };
12
13
 
@@ -27,20 +27,37 @@ var _require2 = require('../errors'),
27
27
  var fs = require('../fs');
28
28
  var util = require('../util');
29
29
 
30
- var baseUrl = 'https://download.cypress.io/';
30
+ var defaultBaseUrl = 'https://download.cypress.io/';
31
+
32
+ var getBaseUrl = function getBaseUrl() {
33
+ if (util.getEnv('CYPRESS_DOWNLOAD_MIRROR')) {
34
+ var baseUrl = util.getEnv('CYPRESS_DOWNLOAD_MIRROR');
35
+
36
+ if (!baseUrl.endsWith('/')) {
37
+ baseUrl += '/';
38
+ }
39
+
40
+ return baseUrl;
41
+ }
42
+
43
+ return defaultBaseUrl;
44
+ };
31
45
 
32
46
  var prepend = function prepend(urlPath) {
33
- var endpoint = url.resolve(baseUrl, urlPath);
47
+ var endpoint = url.resolve(getBaseUrl(), urlPath);
34
48
  var platform = os.platform();
35
49
  var arch = os.arch();
50
+
36
51
  return endpoint + '?platform=' + platform + '&arch=' + arch;
37
52
  };
38
53
 
39
54
  var getUrl = function getUrl(version) {
40
55
  if (is.url(version)) {
41
56
  debug('version is already an url', version);
57
+
42
58
  return version;
43
59
  }
60
+
44
61
  return version ? prepend('desktop/' + version) : prepend('desktop');
45
62
  };
46
63
 
@@ -50,6 +67,7 @@ var statusMessage = function statusMessage(err) {
50
67
 
51
68
  var prettyDownloadErr = function prettyDownloadErr(err, version) {
52
69
  var msg = stripIndent(_templateObject, getUrl(version), statusMessage(err));
70
+
53
71
  debug(msg);
54
72
 
55
73
  return throwFormErrorText(errors.failedDownload)(msg);
@@ -73,6 +91,7 @@ var downloadFromUrl = function downloadFromUrl(_ref) {
73
91
  url: url,
74
92
  followRedirect: function followRedirect(response) {
75
93
  var version = response.headers['x-version'];
94
+
76
95
  debug('redirect version:', version);
77
96
  if (version) {
78
97
  // set the version in options if we have one.
@@ -131,6 +150,7 @@ var start = function start(_ref2) {
131
150
  if (!downloadDestination) {
132
151
  la(is.unemptyString(downloadDestination), 'missing download dir', _arguments);
133
152
  }
153
+
134
154
  if (!progress) {
135
155
  progress = { onProgress: function onProgress() {
136
156
  return {};
@@ -138,6 +158,7 @@ var start = function start(_ref2) {
138
158
  }
139
159
 
140
160
  var url = getUrl(version);
161
+
141
162
  progress.throttle = 100;
142
163
 
143
164
  debug('needed Cypress version: %s', version);
@@ -83,6 +83,7 @@ var downloadAndUnzip = function downloadAndUnzip(_ref) {
83
83
 
84
84
  return download.start({ version: version, downloadDestination: downloadDestination, progress: progress }).then(function (redirectVersion) {
85
85
  if (redirectVersion) version = redirectVersion;
86
+
86
87
  debug('finished downloading file: ' + downloadDestination);
87
88
  }).then(function () {
88
89
  // save the download destination for unzipping
@@ -100,6 +101,7 @@ var downloadAndUnzip = function downloadAndUnzip(_ref) {
100
101
 
101
102
  var cleanup = function cleanup() {
102
103
  debug('removing zip file %s', downloadDestination);
104
+
103
105
  return fs.removeAsync(downloadDestination);
104
106
  };
105
107
 
@@ -136,18 +138,21 @@ var start = function start() {
136
138
 
137
139
  var pkgVersion = util.pkgVersion();
138
140
  var needVersion = pkgVersion;
141
+
139
142
  debug('version in package.json is', needVersion);
140
143
 
141
144
  // let this environment variable reset the binary version we need
142
145
  if (util.getEnv('CYPRESS_INSTALL_BINARY')) {
143
146
 
144
147
  var envVarVersion = util.getEnv('CYPRESS_INSTALL_BINARY');
148
+
145
149
  debug('using environment variable CYPRESS_INSTALL_BINARY %s', envVarVersion);
146
150
 
147
151
  if (envVarVersion === '0') {
148
152
  debug('environment variable CYPRESS_INSTALL_BINARY = 0, skipping install');
149
153
  logger.log(stripIndent(_templateObject3, chalk.yellow('Note:')));
150
154
  logger.log();
155
+
151
156
  return Promise.resolve();
152
157
  }
153
158
 
@@ -162,6 +167,7 @@ var start = function start() {
162
167
 
163
168
  if (util.getEnv('CYPRESS_CACHE_FOLDER')) {
164
169
  var envCache = util.getEnv('CYPRESS_CACHE_FOLDER');
170
+
165
171
  logger.log(stripIndent(_templateObject4, chalk.yellow('Note:'), chalk.cyan(envCache)));
166
172
  logger.log();
167
173
  }
@@ -178,6 +184,7 @@ var start = function start() {
178
184
 
179
185
  if (!binaryVersion) {
180
186
  debug('no binary installed under cli version');
187
+
181
188
  return true;
182
189
  }
183
190
 
@@ -189,12 +196,14 @@ var start = function start() {
189
196
 
190
197
  if (options.force) {
191
198
  debug('performing force install over existing binary');
199
+
192
200
  return true;
193
201
  }
194
202
 
195
203
  if (binaryVersion === needVersion || !util.isSemver(needVersion)) {
196
204
  // our version matches, tell the user this is a noop
197
205
  alreadyInstalledMsg();
206
+
198
207
  return false;
199
208
  }
200
209
 
@@ -203,6 +212,7 @@ var start = function start() {
203
212
  // noop if we've been told not to download
204
213
  if (!shouldInstall) {
205
214
  debug('Not downloading or installing binary');
215
+
206
216
  return;
207
217
  }
208
218
 
@@ -218,6 +228,7 @@ var start = function start() {
218
228
  }
219
229
 
220
230
  var possibleFile = util.formAbsolutePath(needVersion);
231
+
221
232
  debug('checking local file', possibleFile, 'cwd', process.cwd());
222
233
 
223
234
  return fs.pathExistsAsync(possibleFile).then(function (exists) {
@@ -226,15 +237,18 @@ var start = function start() {
226
237
  if (exists && path.extname(possibleFile) === '.zip') {
227
238
  return possibleFile;
228
239
  }
240
+
229
241
  return false;
230
242
  });
231
243
  }).then(function (pathToLocalFile) {
232
244
  if (pathToLocalFile) {
233
245
  var absolutePath = path.resolve(needVersion);
246
+
234
247
  debug('found local file at', absolutePath);
235
248
  debug('skipping download');
236
249
 
237
250
  var rendererOptions = getRendererOptions();
251
+
238
252
  return new Listr([unzipTask({
239
253
  progress: {
240
254
  throttle: 100,
@@ -254,6 +268,7 @@ var start = function start() {
254
268
  debug('preparing to download and unzip version ', needVersion, 'to path', installDir);
255
269
 
256
270
  var downloadDir = os.tmpdir();
271
+
257
272
  return downloadAndUnzip({ version: needVersion, installDir: installDir, downloadDir: downloadDir });
258
273
  })
259
274
  // delay 1 sec for UX, unless we are testing
@@ -272,6 +287,7 @@ var unzipTask = function unzipTask(_ref2) {
272
287
  installDir = _ref2.installDir,
273
288
  progress = _ref2.progress,
274
289
  rendererOptions = _ref2.rendererOptions;
290
+
275
291
  return {
276
292
  title: util.titleize('Unzipping Cypress'),
277
293
  task: function task(ctx, _task3) {
@@ -302,9 +318,11 @@ var progessify = function progessify(task, title) {
302
318
  // the default
303
319
  var getRendererOptions = function getRendererOptions() {
304
320
  var renderer = util.isCi() ? verbose : 'default';
321
+
305
322
  if (logger.logLevel() === 'silent') {
306
323
  renderer = 'silent';
307
324
  }
325
+
308
326
  return {
309
327
  renderer: renderer
310
328
  };
@@ -10,6 +10,7 @@ var util = require('../util');
10
10
 
11
11
  var getPlatformExecutable = function getPlatformExecutable() {
12
12
  var platform = os.platform();
13
+
13
14
  switch (platform) {
14
15
  case 'darwin':
15
16
  return 'Contents/MacOS/Cypress';
@@ -25,6 +26,7 @@ var getPlatformExecutable = function getPlatformExecutable() {
25
26
 
26
27
  var getPlatFormBinaryFolder = function getPlatFormBinaryFolder() {
27
28
  var platform = os.platform();
29
+
28
30
  switch (platform) {
29
31
  case 'darwin':
30
32
  return 'Cypress.app';
@@ -40,6 +42,7 @@ var getPlatFormBinaryFolder = function getPlatFormBinaryFolder() {
40
42
 
41
43
  var getBinaryPkgPath = function getBinaryPkgPath(binaryDir) {
42
44
  var platform = os.platform();
45
+
43
46
  switch (platform) {
44
47
  case 'darwin':
45
48
  return path.join(binaryDir, 'Contents', 'Resources', 'app', 'package.json');
@@ -70,11 +73,14 @@ var getVersionDir = function getVersionDir() {
70
73
 
71
74
  var getCacheDir = function getCacheDir() {
72
75
  var cache_directory = util.getCacheDir();
76
+
73
77
  if (util.getEnv('CYPRESS_CACHE_FOLDER')) {
74
78
  var envVarCacheDir = util.getEnv('CYPRESS_CACHE_FOLDER');
79
+
75
80
  debug('using environment variable CYPRESS_CACHE_FOLDER %s', envVarCacheDir);
76
81
  cache_directory = path.resolve(envVarCacheDir);
77
82
  }
83
+
78
84
  return cache_directory;
79
85
  };
80
86
 
@@ -84,9 +90,11 @@ var parseRealPlatformBinaryFolderAsync = function parseRealPlatformBinaryFolderA
84
90
  if (!realPath.toString().endsWith(getPlatformExecutable())) {
85
91
  return false;
86
92
  }
93
+
87
94
  if (os.platform() === 'darwin') {
88
95
  return path.resolve(realPath, '..', '..', '..');
89
96
  }
97
+
90
98
  return path.resolve(realPath, '..');
91
99
  });
92
100
  };
@@ -102,6 +110,7 @@ var getBinaryStatePath = function getBinaryStatePath(binaryDir) {
102
110
  var getBinaryStateContentsAsync = function getBinaryStateContentsAsync(binaryDir) {
103
111
  return fs.readJsonAsync(getBinaryStatePath(binaryDir)).catch({ code: 'ENOENT' }, SyntaxError, function () {
104
112
  debug('could not read binary_state.json file');
113
+
105
114
  return {};
106
115
  });
107
116
  };
@@ -129,11 +138,14 @@ var getPathToExecutable = function getPathToExecutable(binaryDir) {
129
138
 
130
139
  var getBinaryPkgVersionAsync = function getBinaryPkgVersionAsync(binaryDir) {
131
140
  var pathToPackageJson = getBinaryPkgPath(binaryDir);
141
+
132
142
  debug('Reading binary package.json from:', pathToPackageJson);
143
+
133
144
  return fs.pathExistsAsync(pathToPackageJson).then(function (exists) {
134
145
  if (!exists) {
135
146
  return null;
136
147
  }
148
+
137
149
  return fs.readJsonAsync(pathToPackageJson).get('version');
138
150
  });
139
151
  };
@@ -35,6 +35,7 @@ var unzip = function unzip(_ref) {
35
35
  return new Promise(function (resolve, reject) {
36
36
  return yauzl.open(zipFilePath, function (err, zipFile) {
37
37
  if (err) return reject(err);
38
+
38
39
  // debug('zipfile.paths:', zipFile)
39
40
  // zipFile.on('entry', debug)
40
41
  // debug(zipFile.readEntry())
@@ -90,12 +91,9 @@ var unzip = function unzip(_ref) {
90
91
  var copyingFileRe = /^copying file/;
91
92
 
92
93
  var sp = cp.spawn('ditto', ['-xkV', zipFilePath, installDir]);
93
- sp.on('error', function () {
94
- return (
95
- // f-it just unzip with node
96
- unzipWithNode()
97
- );
98
- });
94
+
95
+ // f-it just unzip with node
96
+ sp.on('error', unzipWithNode);
99
97
 
100
98
  sp.on('close', function (code) {
101
99
  if (code === 0) {
@@ -139,13 +137,16 @@ var start = function start(_ref2) {
139
137
  progress = _ref2.progress;
140
138
 
141
139
  la(is.unemptyString(installDir), 'missing installDir');
142
- if (!progress) progress = { onProgress: function onProgress() {
143
- return {};
144
- } };
140
+ if (!progress) {
141
+ progress = { onProgress: function onProgress() {
142
+ return {};
143
+ } };
144
+ }
145
145
 
146
146
  return fs.pathExists(installDir).then(function (exists) {
147
147
  if (exists) {
148
148
  debug('removing existing unzipped binary', installDir);
149
+
149
150
  return fs.removeAsync(installDir);
150
151
  }
151
152
  }).then(function () {
@@ -32,7 +32,9 @@ var state = require('./state');
32
32
 
33
33
  var checkExecutable = function checkExecutable(binaryDir) {
34
34
  var executable = state.getPathToExecutable(binaryDir);
35
+
35
36
  debug('checking if executable exists', executable);
37
+
36
38
  return util.isExecutableAsync(executable).then(function (isExecutable) {
37
39
  debug('Binary is executable? :', isExecutable);
38
40
  if (!isExecutable) {
@@ -42,6 +44,7 @@ var checkExecutable = function checkExecutable(binaryDir) {
42
44
  if (util.isCi()) {
43
45
  return throwFormErrorText(errors.notInstalledCI(executable))();
44
46
  }
47
+
45
48
  return throwFormErrorText(errors.missingApp(binaryDir))(stripIndent(_templateObject, chalk.cyan(executable)));
46
49
  });
47
50
  };
@@ -49,29 +52,35 @@ var checkExecutable = function checkExecutable(binaryDir) {
49
52
  var runSmokeTest = function runSmokeTest(binaryDir) {
50
53
  debug('running smoke test');
51
54
  var cypressExecPath = state.getPathToExecutable(binaryDir);
55
+
52
56
  debug('using Cypress executable %s', cypressExecPath);
53
57
 
54
58
  var onXvfbError = function onXvfbError(err) {
55
59
  debug('caught xvfb error %s', err.message);
60
+
56
61
  return throwFormErrorText(errors.missingXvfb)('Caught error trying to run XVFB: "' + err.message + '"');
57
62
  };
58
63
 
59
64
  var onSmokeTestError = function onSmokeTestError(err) {
60
65
  debug('Smoke test failed:', err);
66
+
61
67
  return throwFormErrorText(errors.missingDependency)(err.stderr || err.message);
62
68
  };
63
69
 
64
70
  var needsXvfb = xvfb.isNeeded();
71
+
65
72
  debug('needs XVFB?', needsXvfb);
66
73
 
67
74
  var spawn = function spawn() {
68
75
  var random = _.random(0, 1000);
69
76
  var args = ['--smoke-test', '--ping=' + random];
70
77
  var smokeTestCommand = cypressExecPath + ' ' + args.join(' ');
78
+
71
79
  debug('smoke test command:', smokeTestCommand);
72
80
 
73
81
  return Promise.resolve(util.exec(cypressExecPath, args)).catch(onSmokeTestError).then(function (result) {
74
82
  var smokeTestReturned = result.stdout;
83
+
75
84
  debug('smoke test stdout "%s"', smokeTestReturned);
76
85
 
77
86
  if (!util.stdoutLineMatches(String(random), smokeTestReturned)) {
@@ -85,9 +94,9 @@ var runSmokeTest = function runSmokeTest(binaryDir) {
85
94
  return xvfb.start().catch(onXvfbError).then(spawn).finally(function () {
86
95
  return xvfb.stop().catch(onXvfbError);
87
96
  });
88
- } else {
89
- return spawn();
90
97
  }
98
+
99
+ return spawn();
91
100
  };
92
101
 
93
102
  function testBinary(version, binaryDir) {
@@ -101,6 +110,7 @@ function testBinary(version, binaryDir) {
101
110
  // the verbose renderer else use
102
111
  // the default
103
112
  var renderer = util.isCi() ? verbose : 'default';
113
+
104
114
  if (logger.logLevel() === 'silent') renderer = 'silent';
105
115
 
106
116
  var rendererOptions = {
@@ -111,11 +121,13 @@ function testBinary(version, binaryDir) {
111
121
  title: util.titleize('Verifying Cypress can run', chalk.gray(binaryDir)),
112
122
  task: function task(ctx, _task) {
113
123
  debug('clearing out the verified version');
124
+
114
125
  return state.clearBinaryStateAsync(binaryDir).then(function () {
115
126
  return Promise.all([runSmokeTest(binaryDir), Promise.resolve().delay(1500)] // good user experience
116
127
  );
117
128
  }).then(function () {
118
129
  debug('write verified: true');
130
+
119
131
  return state.writeBinaryVerifiedAsync(true, binaryDir);
120
132
  }).then(function () {
121
133
  util.setTaskTitle(_task, util.titleize(chalk.green('Verified Cypress!'), chalk.gray(binaryDir)), rendererOptions.renderer);
@@ -134,6 +146,7 @@ var maybeVerify = function maybeVerify(installedVersion, binaryDir) {
134
146
  debug('is Verified ?', isVerified);
135
147
 
136
148
  var shouldVerify = !isVerified;
149
+
137
150
  // force verify if options.force
138
151
  if (options.force) {
139
152
  debug('force verify');
@@ -166,6 +179,7 @@ var start = function start() {
166
179
 
167
180
  var parseBinaryEnvVar = function parseBinaryEnvVar() {
168
181
  var envBinaryPath = util.getEnv('CYPRESS_RUN_BINARY');
182
+
169
183
  debug('CYPRESS_RUN_BINARY exists, =', envBinaryPath);
170
184
  logger.log(stripIndent(_templateObject4, chalk.yellow('Note:'), chalk.white('CYPRESS_RUN_BINARY='), chalk.cyan(envBinaryPath)));
171
185
  logger.log();
@@ -181,6 +195,7 @@ var start = function start() {
181
195
  if (!envBinaryDir) {
182
196
  return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))();
183
197
  }
198
+
184
199
  debug('CYPRESS_RUN_BINARY has binaryDir:', envBinaryDir);
185
200
 
186
201
  binaryDir = envBinaryDir;
@@ -204,6 +219,7 @@ var start = function start() {
204
219
 
205
220
  if (!binaryVersion) {
206
221
  debug('no Cypress binary found for cli version ', packageVersion);
222
+
207
223
  return throwFormErrorText(errors.missingApp(binaryDir))('\n Cannot read binary version from: ' + chalk.cyan(state.getBinaryPkgPath(binaryDir)) + '\n ');
208
224
  }
209
225
 
package/lib/util.js CHANGED
@@ -35,6 +35,7 @@ function normalizeModuleOptions() {
35
35
  function stdoutLineMatches(expectedLine, stdout) {
36
36
  var lines = stdout.split('\n').map(R.trim);
37
37
  var lineMatches = R.equals(expectedLine);
38
+
38
39
  return lines.some(lineMatches);
39
40
  }
40
41
 
@@ -175,9 +176,9 @@ var util = {
175
176
  }).catch(function () {
176
177
  return os.release();
177
178
  });
178
- } else {
179
- return os.release();
180
179
  }
180
+
181
+ return os.release();
181
182
  });
182
183
  },
183
184
 
@@ -190,24 +191,32 @@ var util = {
190
191
  if (path.isAbsolute(filename)) {
191
192
  return filename;
192
193
  }
194
+
193
195
  return path.join(process.cwd(), '..', '..', filename);
194
196
  },
195
197
  getEnv: function getEnv(varName) {
196
198
  var envVar = process.env[varName];
197
199
  var configVar = process.env['npm_config_' + varName];
198
200
  var packageConfigVar = process.env['npm_package_config_' + varName];
201
+
199
202
  if (envVar) {
200
203
  debug('Using ' + varName + ' from environment variable');
204
+
201
205
  return envVar;
202
206
  }
207
+
203
208
  if (configVar) {
204
209
  debug('Using ' + varName + ' from npm config');
210
+
205
211
  return configVar;
206
212
  }
213
+
207
214
  if (packageConfigVar) {
208
215
  debug('Using ' + varName + ' from package.json config');
216
+
209
217
  return packageConfigVar;
210
218
  }
219
+
211
220
  return undefined;
212
221
  },
213
222
  getCacheDir: function getCacheDir() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress",
3
- "version": "3.0.3",
3
+ "version": "3.1.3",
4
4
  "main": "index.js",
5
5
  "bin": {
6
6
  "cypress": "bin/cypress"
@@ -26,7 +26,7 @@
26
26
  "@types/bluebird": "3.5.18",
27
27
  "@types/chai": "4.0.8",
28
28
  "@types/chai-jquery": "1.1.35",
29
- "@types/jquery": "3.2.16",
29
+ "@types/jquery": "3.3.6",
30
30
  "@types/lodash": "4.14.87",
31
31
  "@types/minimatch": "3.0.3",
32
32
  "@types/mocha": "2.2.44",
@@ -52,7 +52,7 @@
52
52
  "lodash": "4.17.10",
53
53
  "log-symbols": "2.2.0",
54
54
  "minimist": "1.2.0",
55
- "progress": "1.1.8",
55
+ "moment": "2.22.2",
56
56
  "ramda": "0.24.1",
57
57
  "request": "2.87.0",
58
58
  "request-progress": "0.3.1",
package/types/index.d.ts CHANGED
@@ -10,12 +10,14 @@
10
10
  /// <reference path="./blob-util.d.ts" />
11
11
  /// <reference path="./bluebird.d.ts" />
12
12
  /// <reference path="./minimatch.d.ts" />
13
+ /// <reference path="./moment.d.ts" />
13
14
 
14
15
  /// <reference types="chai" />
15
16
  /// <reference types="chai-jquery" />
16
17
  /// <reference types="jquery" />
17
18
  /// <reference types="lodash" />
18
19
  /// <reference types="mocha" />
20
+ /// <reference types="moment" />
19
21
  /// <reference types="sinon" />
20
22
  /// <reference types="sinon-chai" />
21
23
 
@@ -100,7 +102,7 @@ declare namespace Cypress {
100
102
  * @example
101
103
  * const todaysDate = Cypress.moment().format("MMM DD, YYYY")
102
104
  */
103
- moment: (...args: any[]) => any // perhaps we want to add moment as a dependency for types?
105
+ moment: Moment.MomentStatic
104
106
  /**
105
107
  * Cypress automatically includes Bluebird and exposes it as Cypress.Promise.
106
108
  *
@@ -1104,7 +1106,7 @@ declare namespace Cypress {
1104
1106
  * cy.screenshot()
1105
1107
  * cy.get(".post").screenshot()
1106
1108
  */
1107
- screenshot(options?: Partial<Loggable & Timeoutable>): Chainable<null>
1109
+ screenshot(options?: Partial<Loggable & Timeoutable & ScreenshotOptions>): Chainable<null>
1108
1110
  /**
1109
1111
  * Take a screenshot of the application under test and the Cypress Command Log and save under given filename.
1110
1112
  *
@@ -1512,13 +1514,13 @@ declare namespace Cypress {
1512
1514
  *
1513
1515
  * @see https://on.cypress.io/wait
1514
1516
  */
1515
- wait(alias: string, options?: Partial<Loggable & Timeoutable>): Chainable<WaitXHR>
1517
+ wait(alias: string, options?: Partial<Loggable & Timeoutable & TimeoutableXHR>): Chainable<WaitXHR>
1516
1518
  /**
1517
1519
  * Wait for list of XHR requests to complete.
1518
1520
  *
1519
1521
  * @see https://on.cypress.io/wait
1520
1522
  */
1521
- wait(alias: string[], options?: Partial<Loggable & Timeoutable>): Chainable<WaitXHR[]>
1523
+ wait(alias: string[], options?: Partial<Loggable & Timeoutable & TimeoutableXHR>): Chainable<WaitXHR[]>
1522
1524
 
1523
1525
  /**
1524
1526
  * Get the window object of the page that is currently active.
@@ -1566,6 +1568,16 @@ declare namespace Cypress {
1566
1568
  * })
1567
1569
  */
1568
1570
  wrap<E extends Node = HTMLElement>(element: E | JQuery<E>, options?: Partial<Loggable & Timeoutable>): Chainable<JQuery<E>>
1571
+ /**
1572
+ * Yield the element passed into `.wrap()` to the next command in the Cypress chain.
1573
+ *
1574
+ * @see https://on.cypress.io/wrap
1575
+ * @example
1576
+ * cy.wrap(new Promise((resolve, reject) => {
1577
+ * setTimeout(resolve, 1000);
1578
+ * }).then(result => {})
1579
+ */
1580
+ wrap<F extends Promise<S>, S>(promise: F, options?: Partial<Loggable & Timeoutable>): Chainable<S>
1569
1581
  /**
1570
1582
  * Yields whatever is passed into `.wrap()` to the next command in the Cypress chain.
1571
1583
  *
@@ -1645,6 +1657,26 @@ declare namespace Cypress {
1645
1657
  timeout: number
1646
1658
  }
1647
1659
 
1660
+ /**
1661
+ * Options that control how long the Test Runner waits for an XHR request and response to succeed
1662
+ */
1663
+ interface TimeoutableXHR {
1664
+ /**
1665
+ * Time to wait for the request (ms)
1666
+ *
1667
+ * @default {@link Timeoutable#timeout}
1668
+ * @see https://docs.cypress.io/guides/references/configuration.html#Timeouts
1669
+ */
1670
+ requestTimeout: number,
1671
+ /**
1672
+ * Time to wait for the response (ms)
1673
+ *
1674
+ * @default {@link Timeoutable#timeout}
1675
+ * @see https://docs.cypress.io/guides/references/configuration.html#Timeouts
1676
+ */
1677
+ responseTimeout: number
1678
+ }
1679
+
1648
1680
  /**
1649
1681
  * Options to force an event, skipping Actionability check
1650
1682
  * @see https://docs.cypress.io/guides/core-concepts/interacting-with-elements.html#Actionability
@@ -0,0 +1,11 @@
1
+ // Shim definition to export a namespace. Cypress is actually a global module
2
+ // so import/export isn't allowed there. We import here and define a global module
3
+ // so that Cypress can get and use the Moment type
4
+ // tslint:disable-next-line:no-implicit-dependencies
5
+ import * as moment from 'moment'
6
+ export = Moment
7
+ export as namespace Moment
8
+
9
+ declare namespace Moment {
10
+ type MomentStatic = typeof moment
11
+ }