cypress 3.0.3 → 3.1.3

Sign up to get free protection for your applications and to get access to all the features.
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
+ }