cypress 12.1.0 → 12.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +2 -11
- package/lib/VerboseRenderer.js +2 -16
- package/lib/cli.js +25 -83
- package/lib/cypress.js +1 -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 +6 -6
- 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,
|