cypress 12.0.2 → 12.2.0
Sign up to get free protection for your applications and to get access to all the features.
- package/index.js +2 -11
- package/lib/VerboseRenderer.js +2 -16
- package/lib/cli.js +25 -83
- package/lib/cypress.js +2 -14
- package/lib/errors.js +13 -38
- package/lib/exec/info.js +10 -31
- package/lib/exec/open.js +1 -24
- package/lib/exec/run.js +15 -52
- package/lib/exec/shared.js +6 -15
- package/lib/exec/spawn.js +45 -88
- package/lib/exec/versions.js +0 -9
- package/lib/exec/xvfb.js +5 -18
- package/lib/fs.js +0 -1
- package/lib/logger.js +3 -10
- package/lib/tasks/cache.js +5 -29
- package/lib/tasks/download.js +21 -57
- package/lib/tasks/get-folder-size.js +1 -9
- package/lib/tasks/install.js +20 -66
- package/lib/tasks/state.js +5 -51
- package/lib/tasks/unzip.js +7 -41
- package/lib/tasks/verify.js +11 -65
- package/lib/util.js +41 -128
- package/mount-utils/package.json +2 -2
- package/package.json +3 -3
- package/react/dist/cypress-react.cjs.js +7 -14
- package/react/package.json +1 -1
- package/react18/dist/cypress-react.cjs.js +6 -12
- package/react18/package.json +1 -1
- package/svelte/dist/cypress-svelte.cjs.js +0 -2
- package/types/cypress.d.ts +51 -17
- package/types/net-stubbing.d.ts +11 -0
- package/vue/dist/cypress-vue.cjs.js +3 -6
- package/vue/package.json +1 -1
- package/vue2/dist/cypress-vue2.cjs.js +18 -27
- package/vue2/dist/cypress-vue2.esm-bundler.js +0 -3
package/lib/tasks/unzip.js
CHANGED
@@ -1,38 +1,26 @@
|
|
1
1
|
"use strict";
|
2
2
|
|
3
3
|
const _ = require('lodash');
|
4
|
-
|
5
4
|
const la = require('lazy-ass');
|
6
|
-
|
7
5
|
const is = require('check-more-types');
|
8
|
-
|
9
6
|
const cp = require('child_process');
|
10
|
-
|
11
7
|
const os = require('os');
|
12
|
-
|
13
8
|
const yauzl = require('yauzl');
|
14
|
-
|
15
9
|
const debug = require('debug')('cypress:cli:unzip');
|
16
|
-
|
17
10
|
const extract = require('extract-zip');
|
18
|
-
|
19
11
|
const Promise = require('bluebird');
|
20
|
-
|
21
12
|
const readline = require('readline');
|
22
|
-
|
23
13
|
const {
|
24
14
|
throwFormErrorText,
|
25
15
|
errors
|
26
16
|
} = require('../errors');
|
27
|
-
|
28
17
|
const fs = require('../fs');
|
29
|
-
|
30
18
|
const util = require('../util');
|
31
|
-
|
32
19
|
const unzipTools = {
|
33
20
|
extract
|
34
|
-
};
|
21
|
+
};
|
35
22
|
|
23
|
+
// expose this function for simple testing
|
36
24
|
const unzip = ({
|
37
25
|
zipFilePath,
|
38
26
|
installDir,
|
@@ -40,42 +28,35 @@ const unzip = ({
|
|
40
28
|
}) => {
|
41
29
|
debug('unzipping from %s', zipFilePath);
|
42
30
|
debug('into', installDir);
|
43
|
-
|
44
31
|
if (!zipFilePath) {
|
45
32
|
throw new Error('Missing zip filename');
|
46
33
|
}
|
47
|
-
|
48
34
|
const startTime = Date.now();
|
49
35
|
let yauzlDoneTime = 0;
|
50
36
|
return fs.ensureDirAsync(installDir).then(() => {
|
51
37
|
return new Promise((resolve, reject) => {
|
52
38
|
return yauzl.open(zipFilePath, (err, zipFile) => {
|
53
39
|
yauzlDoneTime = Date.now();
|
54
|
-
|
55
40
|
if (err) {
|
56
41
|
debug('error using yauzl %s', err.message);
|
57
42
|
return reject(err);
|
58
43
|
}
|
59
|
-
|
60
44
|
const total = zipFile.entryCount;
|
61
45
|
debug('zipFile entries count', total);
|
62
46
|
const started = new Date();
|
63
47
|
let percent = 0;
|
64
48
|
let count = 0;
|
65
|
-
|
66
49
|
const notify = percent => {
|
67
50
|
const elapsed = +new Date() - +started;
|
68
51
|
const eta = util.calculateEta(percent, elapsed);
|
69
52
|
progress.onProgress(percent, util.secsRemaining(eta));
|
70
53
|
};
|
71
|
-
|
72
54
|
const tick = () => {
|
73
55
|
count += 1;
|
74
56
|
percent = count / total * 100;
|
75
57
|
const displayPercent = percent.toFixed(0);
|
76
58
|
return notify(displayPercent);
|
77
59
|
};
|
78
|
-
|
79
60
|
const unzipWithNode = () => {
|
80
61
|
debug('unzipping with node.js (slow)');
|
81
62
|
const opts = {
|
@@ -93,9 +74,7 @@ const unzip = ({
|
|
93
74
|
}
|
94
75
|
});
|
95
76
|
};
|
96
|
-
|
97
77
|
const unzipFallback = _.once(unzipWithNode);
|
98
|
-
|
99
78
|
const unzipWithUnzipTool = () => {
|
100
79
|
debug('unzipping via `unzip`');
|
101
80
|
const inflatingRe = /inflating:/;
|
@@ -106,13 +85,11 @@ const unzip = ({
|
|
106
85
|
});
|
107
86
|
sp.on('close', code => {
|
108
87
|
debug('unzip tool close with code %d', code);
|
109
|
-
|
110
88
|
if (code === 0) {
|
111
89
|
percent = 100;
|
112
90
|
notify(percent);
|
113
91
|
return resolve();
|
114
92
|
}
|
115
|
-
|
116
93
|
debug('`unzip` failed %o', {
|
117
94
|
code
|
118
95
|
});
|
@@ -126,18 +103,19 @@ const unzip = ({
|
|
126
103
|
sp.stderr.on('data', data => {
|
127
104
|
debug('`unzip` stderr %s', data);
|
128
105
|
});
|
129
|
-
};
|
106
|
+
};
|
107
|
+
|
108
|
+
// we attempt to first unzip with the native osx
|
130
109
|
// ditto because its less likely to have problems
|
131
110
|
// with corruption, symlinks, or icons causing failures
|
132
111
|
// and can handle resource forks
|
133
112
|
// http://automatica.com.au/2011/02/unzip-mac-os-x-zip-in-terminal/
|
134
|
-
|
135
|
-
|
136
113
|
const unzipWithOsx = () => {
|
137
114
|
debug('unzipping via `ditto`');
|
138
115
|
const copyingFileRe = /^copying file/;
|
139
|
-
const sp = cp.spawn('ditto', ['-xkV', zipFilePath, installDir]);
|
116
|
+
const sp = cp.spawn('ditto', ['-xkV', zipFilePath, installDir]);
|
140
117
|
|
118
|
+
// f-it just unzip with node
|
141
119
|
sp.on('error', err => {
|
142
120
|
debug(err.message);
|
143
121
|
unzipFallback();
|
@@ -150,7 +128,6 @@ const unzip = ({
|
|
150
128
|
notify(percent);
|
151
129
|
return resolve();
|
152
130
|
}
|
153
|
-
|
154
131
|
debug('`ditto` failed %o', {
|
155
132
|
code
|
156
133
|
});
|
@@ -164,17 +141,13 @@ const unzip = ({
|
|
164
141
|
}
|
165
142
|
});
|
166
143
|
};
|
167
|
-
|
168
144
|
switch (os.platform()) {
|
169
145
|
case 'darwin':
|
170
146
|
return unzipWithOsx();
|
171
|
-
|
172
147
|
case 'linux':
|
173
148
|
return unzipWithUnzipTool();
|
174
|
-
|
175
149
|
case 'win32':
|
176
150
|
return unzipWithNode();
|
177
|
-
|
178
151
|
default:
|
179
152
|
return;
|
180
153
|
}
|
@@ -187,18 +160,15 @@ const unzip = ({
|
|
187
160
|
});
|
188
161
|
});
|
189
162
|
};
|
190
|
-
|
191
163
|
function isMaybeWindowsMaxPathLengthError(err) {
|
192
164
|
return os.platform() === 'win32' && err.code === 'ENOENT' && err.syscall === 'realpath';
|
193
165
|
}
|
194
|
-
|
195
166
|
const start = async ({
|
196
167
|
zipFilePath,
|
197
168
|
installDir,
|
198
169
|
progress
|
199
170
|
}) => {
|
200
171
|
la(is.unemptyString(installDir), 'missing installDir');
|
201
|
-
|
202
172
|
if (!progress) {
|
203
173
|
progress = {
|
204
174
|
onProgress: () => {
|
@@ -206,15 +176,12 @@ const start = async ({
|
|
206
176
|
}
|
207
177
|
};
|
208
178
|
}
|
209
|
-
|
210
179
|
try {
|
211
180
|
const installDirExists = await fs.pathExists(installDir);
|
212
|
-
|
213
181
|
if (installDirExists) {
|
214
182
|
debug('removing existing unzipped binary', installDir);
|
215
183
|
await fs.removeAsync(installDir);
|
216
184
|
}
|
217
|
-
|
218
185
|
await unzip({
|
219
186
|
zipFilePath,
|
220
187
|
installDir,
|
@@ -225,7 +192,6 @@ const start = async ({
|
|
225
192
|
await throwFormErrorText(errorTemplate)(err);
|
226
193
|
}
|
227
194
|
};
|
228
|
-
|
229
195
|
module.exports = {
|
230
196
|
start,
|
231
197
|
utils: {
|
package/lib/tasks/verify.js
CHANGED
@@ -1,50 +1,33 @@
|
|
1
1
|
"use strict";
|
2
2
|
|
3
3
|
const _ = require('lodash');
|
4
|
-
|
5
4
|
const chalk = require('chalk');
|
6
|
-
|
7
5
|
const {
|
8
6
|
Listr
|
9
7
|
} = require('listr2');
|
10
|
-
|
11
8
|
const debug = require('debug')('cypress:cli');
|
12
|
-
|
13
9
|
const {
|
14
10
|
stripIndent
|
15
11
|
} = require('common-tags');
|
16
|
-
|
17
12
|
const Promise = require('bluebird');
|
18
|
-
|
19
13
|
const logSymbols = require('log-symbols');
|
20
|
-
|
21
14
|
const path = require('path');
|
22
|
-
|
23
15
|
const os = require('os');
|
24
|
-
|
25
16
|
const verbose = require('../VerboseRenderer');
|
26
|
-
|
27
17
|
const {
|
28
18
|
throwFormErrorText,
|
29
19
|
errors
|
30
20
|
} = require('../errors');
|
31
|
-
|
32
21
|
const util = require('../util');
|
33
|
-
|
34
22
|
const logger = require('../logger');
|
35
|
-
|
36
23
|
const xvfb = require('../exec/xvfb');
|
37
|
-
|
38
24
|
const state = require('./state');
|
39
|
-
|
40
25
|
const VERIFY_TEST_RUNNER_TIMEOUT_MS = +util.getEnv('CYPRESS_VERIFY_TIMEOUT') || 30000;
|
41
|
-
|
42
26
|
const checkExecutable = binaryDir => {
|
43
27
|
const executable = state.getPathToExecutable(binaryDir);
|
44
28
|
debug('checking if executable exists', executable);
|
45
29
|
return util.isExecutableAsync(executable).then(isExecutable => {
|
46
30
|
debug('Binary is executable? :', isExecutable);
|
47
|
-
|
48
31
|
if (!isExecutable) {
|
49
32
|
return throwFormErrorText(errors.binaryNotExecutable(executable))();
|
50
33
|
}
|
@@ -54,99 +37,79 @@ const checkExecutable = binaryDir => {
|
|
54
37
|
if (util.isCi()) {
|
55
38
|
return throwFormErrorText(errors.notInstalledCI(executable))();
|
56
39
|
}
|
57
|
-
|
58
40
|
return throwFormErrorText(errors.missingApp(binaryDir))(stripIndent`
|
59
41
|
Cypress executable not found at: ${chalk.cyan(executable)}
|
60
42
|
`);
|
61
43
|
});
|
62
44
|
};
|
63
|
-
|
64
45
|
const runSmokeTest = (binaryDir, options) => {
|
65
46
|
let executable = state.getPathToExecutable(binaryDir);
|
66
|
-
|
67
47
|
const onSmokeTestError = (smokeTestCommand, linuxWithDisplayEnv) => {
|
68
48
|
return err => {
|
69
49
|
debug('Smoke test failed:', err);
|
70
50
|
let errMessage = err.stderr || err.message;
|
71
51
|
debug('error message:', errMessage);
|
72
|
-
|
73
52
|
if (err.timedOut) {
|
74
53
|
debug('error timedOut is true');
|
75
54
|
return throwFormErrorText(errors.smokeTestFailure(smokeTestCommand, true))(errMessage);
|
76
55
|
}
|
77
|
-
|
78
56
|
if (linuxWithDisplayEnv && util.isBrokenGtkDisplay(errMessage)) {
|
79
57
|
util.logBrokenGtkDisplayWarning();
|
80
58
|
return throwFormErrorText(errors.invalidSmokeTestDisplayError)(errMessage);
|
81
59
|
}
|
82
|
-
|
83
60
|
return throwFormErrorText(errors.missingDependency)(errMessage);
|
84
61
|
};
|
85
62
|
};
|
86
|
-
|
87
63
|
const needsXvfb = xvfb.isNeeded();
|
88
64
|
debug('needs Xvfb?', needsXvfb);
|
65
|
+
|
89
66
|
/**
|
90
67
|
* Spawn Cypress running smoke test to check if all operating system
|
91
68
|
* dependencies are good.
|
92
69
|
*/
|
93
|
-
|
94
70
|
const spawn = linuxWithDisplayEnv => {
|
95
71
|
const random = _.random(0, 1000);
|
96
|
-
|
97
72
|
const args = ['--smoke-test', `--ping=${random}`];
|
98
|
-
|
99
73
|
if (needsSandbox()) {
|
100
74
|
// electron requires --no-sandbox to run as root
|
101
75
|
debug('disabling Electron sandbox');
|
102
76
|
args.unshift('--no-sandbox');
|
103
77
|
}
|
104
|
-
|
105
78
|
if (options.dev) {
|
106
79
|
executable = 'node';
|
107
80
|
args.unshift(path.resolve(__dirname, '..', '..', '..', 'scripts', 'start.js'));
|
108
81
|
}
|
109
|
-
|
110
82
|
const smokeTestCommand = `${executable} ${args.join(' ')}`;
|
111
83
|
debug('running smoke test');
|
112
84
|
debug('using Cypress executable %s', executable);
|
113
85
|
debug('smoke test command:', smokeTestCommand);
|
114
86
|
debug('smoke test timeout %d ms', options.smokeTestTimeout);
|
115
|
-
|
116
87
|
const env = _.extend({}, process.env, {
|
117
88
|
ELECTRON_ENABLE_LOGGING: true
|
118
89
|
});
|
119
|
-
|
120
90
|
const stdioOptions = _.extend({}, {
|
121
91
|
env,
|
122
92
|
timeout: options.smokeTestTimeout
|
123
93
|
});
|
124
|
-
|
125
94
|
return Promise.resolve(util.exec(executable, args, stdioOptions)).catch(onSmokeTestError(smokeTestCommand, linuxWithDisplayEnv)).then(result => {
|
126
95
|
// TODO: when execa > 1.1 is released
|
127
96
|
// change this to `result.all` for both stderr and stdout
|
128
97
|
// use lodash to be robust during tests against null result or missing stdout
|
129
98
|
const smokeTestStdout = _.get(result, 'stdout', '');
|
130
|
-
|
131
99
|
debug('smoke test stdout "%s"', smokeTestStdout);
|
132
|
-
|
133
100
|
if (!util.stdoutLineMatches(String(random), smokeTestStdout)) {
|
134
101
|
debug('Smoke test failed because could not find %d in:', random, result);
|
135
|
-
|
136
102
|
const smokeTestStderr = _.get(result, 'stderr', '');
|
137
|
-
|
138
103
|
const errorText = smokeTestStderr || smokeTestStdout;
|
139
104
|
return throwFormErrorText(errors.smokeTestFailure(smokeTestCommand, false))(errorText);
|
140
105
|
}
|
141
106
|
});
|
142
107
|
};
|
143
|
-
|
144
108
|
const spawnInXvfb = linuxWithDisplayEnv => {
|
145
109
|
return xvfb.start().then(() => {
|
146
110
|
return spawn(linuxWithDisplayEnv);
|
147
111
|
}).finally(xvfb.stop);
|
148
112
|
};
|
149
|
-
|
150
113
|
const userFriendlySpawn = linuxWithDisplayEnv => {
|
151
114
|
debug('spawning, should retry on display problem?', Boolean(linuxWithDisplayEnv));
|
152
115
|
return spawn(linuxWithDisplayEnv).catch({
|
@@ -155,31 +118,30 @@ const runSmokeTest = (binaryDir, options) => {
|
|
155
118
|
return spawnInXvfb(linuxWithDisplayEnv);
|
156
119
|
});
|
157
120
|
};
|
158
|
-
|
159
121
|
if (needsXvfb) {
|
160
122
|
return spawnInXvfb();
|
161
|
-
}
|
123
|
+
}
|
124
|
+
|
125
|
+
// if we are on linux and there's already a DISPLAY
|
162
126
|
// set, then we may need to rerun cypress after
|
163
127
|
// spawning our own Xvfb server
|
164
|
-
|
165
|
-
|
166
128
|
const linuxWithDisplayEnv = util.isPossibleLinuxWithIncorrectDisplay();
|
167
129
|
return userFriendlySpawn(linuxWithDisplayEnv);
|
168
130
|
};
|
169
|
-
|
170
131
|
function testBinary(version, binaryDir, options) {
|
171
|
-
debug('running binary verification check', version);
|
132
|
+
debug('running binary verification check', version);
|
172
133
|
|
134
|
+
// if running from 'cypress verify', don't print this message
|
173
135
|
if (!options.force) {
|
174
136
|
logger.log(stripIndent`
|
175
137
|
It looks like this is your first time using Cypress: ${chalk.cyan(version)}
|
176
138
|
`);
|
177
139
|
}
|
140
|
+
logger.log();
|
178
141
|
|
179
|
-
|
142
|
+
// if we are running in CI then use
|
180
143
|
// the verbose renderer else use
|
181
144
|
// the default
|
182
|
-
|
183
145
|
let renderer = util.isCi() ? verbose : 'default';
|
184
146
|
if (logger.logLevel() === 'silent') renderer = 'silent';
|
185
147
|
const rendererOptions = {
|
@@ -206,17 +168,16 @@ function testBinary(version, binaryDir, options) {
|
|
206
168
|
});
|
207
169
|
return tasks.run();
|
208
170
|
}
|
209
|
-
|
210
171
|
const maybeVerify = (installedVersion, binaryDir, options) => {
|
211
172
|
return state.getBinaryVerifiedAsync(binaryDir).then(isVerified => {
|
212
173
|
debug('is Verified ?', isVerified);
|
213
|
-
let shouldVerify = !isVerified;
|
174
|
+
let shouldVerify = !isVerified;
|
214
175
|
|
176
|
+
// force verify if options.force
|
215
177
|
if (options.force) {
|
216
178
|
debug('force verify');
|
217
179
|
shouldVerify = true;
|
218
180
|
}
|
219
|
-
|
220
181
|
if (shouldVerify) {
|
221
182
|
return testBinary(installedVersion, binaryDir, options).then(() => {
|
222
183
|
if (options.welcomeMessage) {
|
@@ -227,23 +188,19 @@ const maybeVerify = (installedVersion, binaryDir, options) => {
|
|
227
188
|
}
|
228
189
|
});
|
229
190
|
};
|
230
|
-
|
231
191
|
const start = (options = {}) => {
|
232
192
|
debug('verifying Cypress app');
|
233
193
|
const packageVersion = util.pkgVersion();
|
234
194
|
let binaryDir = state.getBinaryDir(packageVersion);
|
235
|
-
|
236
195
|
_.defaults(options, {
|
237
196
|
dev: false,
|
238
197
|
force: false,
|
239
198
|
welcomeMessage: true,
|
240
199
|
smokeTestTimeout: VERIFY_TEST_RUNNER_TIMEOUT_MS
|
241
200
|
});
|
242
|
-
|
243
201
|
if (options.dev) {
|
244
202
|
return runSmokeTest('', options);
|
245
203
|
}
|
246
|
-
|
247
204
|
const parseBinaryEnvVar = () => {
|
248
205
|
const envBinaryPath = util.getEnv('CYPRESS_RUN_BINARY');
|
249
206
|
debug('CYPRESS_RUN_BINARY exists, =', envBinaryPath);
|
@@ -257,7 +214,6 @@ const start = (options = {}) => {
|
|
257
214
|
logger.log();
|
258
215
|
return util.isExecutableAsync(envBinaryPath).then(isExecutable => {
|
259
216
|
debug('CYPRESS_RUN_BINARY is executable? :', isExecutable);
|
260
|
-
|
261
217
|
if (!isExecutable) {
|
262
218
|
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))(stripIndent`
|
263
219
|
The supplied binary path is not executable
|
@@ -269,7 +225,6 @@ const start = (options = {}) => {
|
|
269
225
|
if (!envBinaryDir) {
|
270
226
|
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))();
|
271
227
|
}
|
272
|
-
|
273
228
|
debug('CYPRESS_RUN_BINARY has binaryDir:', envBinaryDir);
|
274
229
|
binaryDir = envBinaryDir;
|
275
230
|
}).catch({
|
@@ -278,10 +233,8 @@ const start = (options = {}) => {
|
|
278
233
|
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))(err.message);
|
279
234
|
});
|
280
235
|
};
|
281
|
-
|
282
236
|
return Promise.try(() => {
|
283
237
|
debug('checking environment variables');
|
284
|
-
|
285
238
|
if (util.getEnv('CYPRESS_RUN_BINARY')) {
|
286
239
|
return parseBinaryEnvVar();
|
287
240
|
}
|
@@ -300,9 +253,7 @@ const start = (options = {}) => {
|
|
300
253
|
Cannot read binary version from: ${chalk.cyan(state.getBinaryPkgPath(binaryDir))}
|
301
254
|
`);
|
302
255
|
}
|
303
|
-
|
304
256
|
debug(`Found binary version ${chalk.green(binaryVersion)} installed in: ${chalk.cyan(binaryDir)}`);
|
305
|
-
|
306
257
|
if (binaryVersion !== packageVersion) {
|
307
258
|
// warn if we installed with CYPRESS_INSTALL_BINARY or changed version
|
308
259
|
// in the package.json
|
@@ -317,18 +268,16 @@ const start = (options = {}) => {
|
|
317
268
|
`);
|
318
269
|
logger.log();
|
319
270
|
}
|
320
|
-
|
321
271
|
return maybeVerify(binaryVersion, binaryDir, options);
|
322
272
|
}).catch(err => {
|
323
273
|
if (err.known) {
|
324
274
|
throw err;
|
325
275
|
}
|
326
|
-
|
327
276
|
return throwFormErrorText(errors.unexpected)(err.stack);
|
328
277
|
});
|
329
278
|
};
|
330
|
-
|
331
279
|
const isLinuxLike = () => os.platform() !== 'win32';
|
280
|
+
|
332
281
|
/**
|
333
282
|
* Returns true if running on a system where Electron needs "--no-sandbox" flag.
|
334
283
|
* @see https://crbug.com/638180
|
@@ -338,10 +287,7 @@ const isLinuxLike = () => os.platform() !== 'win32';
|
|
338
287
|
* Seems there is a lot of discussion around this issue among Electron users
|
339
288
|
* @see https://github.com/electron/electron/issues/17972
|
340
289
|
*/
|
341
|
-
|
342
|
-
|
343
290
|
const needsSandbox = () => isLinuxLike();
|
344
|
-
|
345
291
|
module.exports = {
|
346
292
|
start,
|
347
293
|
VERIFY_TEST_RUNNER_TIMEOUT_MS,
|