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/cache.js
CHANGED
@@ -1,49 +1,35 @@
|
|
1
1
|
"use strict";
|
2
2
|
|
3
3
|
const state = require('./state');
|
4
|
-
|
5
4
|
const logger = require('../logger');
|
6
|
-
|
7
5
|
const fs = require('../fs');
|
8
|
-
|
9
6
|
const util = require('../util');
|
10
|
-
|
11
7
|
const {
|
12
8
|
join
|
13
9
|
} = require('path');
|
14
|
-
|
15
10
|
const Table = require('cli-table3');
|
16
|
-
|
17
11
|
const dayjs = require('dayjs');
|
18
|
-
|
19
12
|
const relativeTime = require('dayjs/plugin/relativeTime');
|
20
|
-
|
21
13
|
const chalk = require('chalk');
|
22
|
-
|
23
14
|
const _ = require('lodash');
|
24
|
-
|
25
15
|
const getFolderSize = require('./get-folder-size');
|
26
|
-
|
27
16
|
const Bluebird = require('bluebird');
|
17
|
+
dayjs.extend(relativeTime);
|
28
18
|
|
29
|
-
|
30
|
-
|
19
|
+
// output colors for the table
|
31
20
|
const colors = {
|
32
21
|
titles: chalk.white,
|
33
22
|
dates: chalk.cyan,
|
34
23
|
values: chalk.green,
|
35
24
|
size: chalk.gray
|
36
25
|
};
|
37
|
-
|
38
26
|
const logCachePath = () => {
|
39
27
|
logger.always(state.getCacheDir());
|
40
28
|
return undefined;
|
41
29
|
};
|
42
|
-
|
43
30
|
const clear = () => {
|
44
31
|
return fs.removeAsync(state.getCacheDir());
|
45
32
|
};
|
46
|
-
|
47
33
|
const prune = () => {
|
48
34
|
const cacheDir = state.getCacheDir();
|
49
35
|
const currentVersion = util.pkgVersion();
|
@@ -68,24 +54,20 @@ const prune = () => {
|
|
68
54
|
logger.always(`No Cypress cache was found at ${cacheDir}. Nothing to prune.`);
|
69
55
|
});
|
70
56
|
};
|
71
|
-
|
72
57
|
const fileSizeInMB = size => {
|
73
58
|
return `${(size / 1024 / 1024).toFixed(1)}MB`;
|
74
59
|
};
|
60
|
+
|
75
61
|
/**
|
76
62
|
* Collects all cached versions, finds when each was used
|
77
63
|
* and prints a table with results to the terminal
|
78
64
|
*/
|
79
|
-
|
80
|
-
|
81
65
|
const list = showSize => {
|
82
66
|
return getCachedVersions(showSize).then(binaries => {
|
83
67
|
const head = [colors.titles('version'), colors.titles('last used')];
|
84
|
-
|
85
68
|
if (showSize) {
|
86
69
|
head.push(colors.titles('size'));
|
87
70
|
}
|
88
|
-
|
89
71
|
const table = new Table({
|
90
72
|
head
|
91
73
|
});
|
@@ -93,18 +75,15 @@ const list = showSize => {
|
|
93
75
|
const versionString = colors.values(binary.version);
|
94
76
|
const lastUsed = binary.accessed ? colors.dates(binary.accessed) : 'unknown';
|
95
77
|
const row = [versionString, lastUsed];
|
96
|
-
|
97
78
|
if (showSize) {
|
98
79
|
const size = colors.size(fileSizeInMB(binary.size));
|
99
80
|
row.push(size);
|
100
81
|
}
|
101
|
-
|
102
82
|
return table.push(row);
|
103
83
|
});
|
104
84
|
logger.always(table.toString());
|
105
85
|
});
|
106
86
|
};
|
107
|
-
|
108
87
|
const getCachedVersions = showSize => {
|
109
88
|
const cacheDir = state.getCacheDir();
|
110
89
|
return fs.readdirAsync(cacheDir).filter(util.isSemver).map(version => {
|
@@ -119,13 +98,11 @@ const getCachedVersions = showSize => {
|
|
119
98
|
const executable = state.getPathToExecutable(binaryDir);
|
120
99
|
return fs.statAsync(executable).then(stat => {
|
121
100
|
const lastAccessedTime = _.get(stat, 'atime');
|
122
|
-
|
123
101
|
if (!lastAccessedTime) {
|
124
102
|
// the test runner has never been opened
|
125
103
|
// or could be a test simulating missing timestamp
|
126
104
|
return binary;
|
127
105
|
}
|
128
|
-
|
129
106
|
const accessed = dayjs(lastAccessedTime).fromNow();
|
130
107
|
binary.accessed = accessed;
|
131
108
|
return binary;
|
@@ -137,16 +114,15 @@ const getCachedVersions = showSize => {
|
|
137
114
|
if (showSize) {
|
138
115
|
const binaryDir = state.getBinaryDir(binary.version);
|
139
116
|
return getFolderSize(binaryDir).then(size => {
|
140
|
-
return {
|
117
|
+
return {
|
118
|
+
...binary,
|
141
119
|
size
|
142
120
|
};
|
143
121
|
});
|
144
122
|
}
|
145
|
-
|
146
123
|
return binary;
|
147
124
|
});
|
148
125
|
};
|
149
|
-
|
150
126
|
module.exports = {
|
151
127
|
path: logCachePath,
|
152
128
|
clear,
|
package/lib/tasks/download.js
CHANGED
@@ -1,59 +1,39 @@
|
|
1
1
|
"use strict";
|
2
2
|
|
3
3
|
const la = require('lazy-ass');
|
4
|
-
|
5
4
|
const is = require('check-more-types');
|
6
|
-
|
7
5
|
const os = require('os');
|
8
|
-
|
9
6
|
const url = require('url');
|
10
|
-
|
11
7
|
const path = require('path');
|
12
|
-
|
13
8
|
const debug = require('debug')('cypress:cli');
|
14
|
-
|
15
9
|
const request = require('@cypress/request');
|
16
|
-
|
17
10
|
const Promise = require('bluebird');
|
18
|
-
|
19
11
|
const requestProgress = require('request-progress');
|
20
|
-
|
21
12
|
const {
|
22
13
|
stripIndent
|
23
14
|
} = require('common-tags');
|
24
|
-
|
25
15
|
const getProxyForUrl = require('proxy-from-env').getProxyForUrl;
|
26
|
-
|
27
16
|
const {
|
28
17
|
throwFormErrorText,
|
29
18
|
errors
|
30
19
|
} = require('../errors');
|
31
|
-
|
32
20
|
const fs = require('../fs');
|
33
|
-
|
34
21
|
const util = require('../util');
|
35
|
-
|
36
22
|
const defaultBaseUrl = 'https://download.cypress.io/';
|
37
23
|
const defaultMaxRedirects = 10;
|
38
|
-
|
39
24
|
const getProxyForUrlWithNpmConfig = url => {
|
40
25
|
return getProxyForUrl(url) || process.env.npm_config_https_proxy || process.env.npm_config_proxy || null;
|
41
26
|
};
|
42
|
-
|
43
27
|
const getBaseUrl = () => {
|
44
28
|
if (util.getEnv('CYPRESS_DOWNLOAD_MIRROR')) {
|
45
29
|
let baseUrl = util.getEnv('CYPRESS_DOWNLOAD_MIRROR');
|
46
|
-
|
47
30
|
if (!baseUrl.endsWith('/')) {
|
48
31
|
baseUrl += '/';
|
49
32
|
}
|
50
|
-
|
51
33
|
return baseUrl;
|
52
34
|
}
|
53
|
-
|
54
35
|
return defaultBaseUrl;
|
55
36
|
};
|
56
|
-
|
57
37
|
const getCA = () => {
|
58
38
|
return new Promise(resolve => {
|
59
39
|
if (process.env.npm_config_cafile) {
|
@@ -69,28 +49,23 @@ const getCA = () => {
|
|
69
49
|
}
|
70
50
|
});
|
71
51
|
};
|
72
|
-
|
73
52
|
const prepend = (arch, urlPath, version) => {
|
74
53
|
const endpoint = url.resolve(getBaseUrl(), urlPath);
|
75
54
|
const platform = os.platform();
|
76
55
|
const pathTemplate = util.getEnv('CYPRESS_DOWNLOAD_PATH_TEMPLATE', true);
|
77
56
|
return pathTemplate ? pathTemplate.replace(/\\?\$\{endpoint\}/, endpoint).replace(/\\?\$\{platform\}/, platform).replace(/\\?\$\{arch\}/, arch).replace(/\\?\$\{version\}/, version) : `${endpoint}?platform=${platform}&arch=${arch}`;
|
78
57
|
};
|
79
|
-
|
80
58
|
const getUrl = (arch, version) => {
|
81
59
|
if (is.url(version)) {
|
82
60
|
debug('version is already an url', version);
|
83
61
|
return version;
|
84
62
|
}
|
85
|
-
|
86
63
|
const urlPath = version ? `desktop/${version}` : 'desktop';
|
87
64
|
return prepend(arch, urlPath, version);
|
88
65
|
};
|
89
|
-
|
90
66
|
const statusMessage = err => {
|
91
67
|
return err.statusCode ? [err.statusCode, err.statusMessage].join(' - ') : err.toString();
|
92
68
|
};
|
93
|
-
|
94
69
|
const prettyDownloadErr = (err, url) => {
|
95
70
|
const msg = stripIndent`
|
96
71
|
URL: ${url}
|
@@ -99,12 +74,11 @@ const prettyDownloadErr = (err, url) => {
|
|
99
74
|
debug(msg);
|
100
75
|
return throwFormErrorText(errors.failedDownload)(msg);
|
101
76
|
};
|
77
|
+
|
102
78
|
/**
|
103
79
|
* Checks checksum and file size for the given file. Allows both
|
104
80
|
* values or just one of them to be checked.
|
105
81
|
*/
|
106
|
-
|
107
|
-
|
108
82
|
const verifyDownloadedFile = (filename, expectedSize, expectedChecksum) => {
|
109
83
|
if (expectedSize && expectedChecksum) {
|
110
84
|
debug('verifying checksum and file size');
|
@@ -113,7 +87,6 @@ const verifyDownloadedFile = (filename, expectedSize, expectedChecksum) => {
|
|
113
87
|
debug('downloaded file has the expected checksum and size ✅');
|
114
88
|
return;
|
115
89
|
}
|
116
|
-
|
117
90
|
debug('raising error: checksum or file size mismatch');
|
118
91
|
const text = stripIndent`
|
119
92
|
Corrupted download
|
@@ -128,7 +101,6 @@ const verifyDownloadedFile = (filename, expectedSize, expectedChecksum) => {
|
|
128
101
|
throw new Error(text);
|
129
102
|
});
|
130
103
|
}
|
131
|
-
|
132
104
|
if (expectedChecksum) {
|
133
105
|
debug('only checking expected file checksum %d', expectedChecksum);
|
134
106
|
return util.getFileChecksum(filename).then(checksum => {
|
@@ -136,7 +108,6 @@ const verifyDownloadedFile = (filename, expectedSize, expectedChecksum) => {
|
|
136
108
|
debug('downloaded file has the expected checksum ✅');
|
137
109
|
return;
|
138
110
|
}
|
139
|
-
|
140
111
|
debug('raising error: file checksum mismatch');
|
141
112
|
const text = stripIndent`
|
142
113
|
Corrupted download
|
@@ -147,7 +118,6 @@ const verifyDownloadedFile = (filename, expectedSize, expectedChecksum) => {
|
|
147
118
|
throw new Error(text);
|
148
119
|
});
|
149
120
|
}
|
150
|
-
|
151
121
|
if (expectedSize) {
|
152
122
|
// maybe we don't have a checksum, but at least CDN returns content length
|
153
123
|
// which we can check against the file size
|
@@ -157,7 +127,6 @@ const verifyDownloadedFile = (filename, expectedSize, expectedChecksum) => {
|
|
157
127
|
debug('downloaded file has the expected size ✅');
|
158
128
|
return;
|
159
129
|
}
|
160
|
-
|
161
130
|
debug('raising error: file size mismatch');
|
162
131
|
const text = stripIndent`
|
163
132
|
Corrupted download
|
@@ -168,14 +137,13 @@ const verifyDownloadedFile = (filename, expectedSize, expectedChecksum) => {
|
|
168
137
|
throw new Error(text);
|
169
138
|
});
|
170
139
|
}
|
171
|
-
|
172
140
|
debug('downloaded file lacks checksum or size to verify');
|
173
141
|
return Promise.resolve();
|
174
|
-
};
|
142
|
+
};
|
143
|
+
|
144
|
+
// downloads from given url
|
175
145
|
// return an object with
|
176
146
|
// {filename: ..., downloaded: true}
|
177
|
-
|
178
|
-
|
179
147
|
const downloadFromUrl = ({
|
180
148
|
url,
|
181
149
|
downloadDestination,
|
@@ -191,7 +159,6 @@ const downloadFromUrl = ({
|
|
191
159
|
Maybe you got stuck in a redirect loop?
|
192
160
|
`));
|
193
161
|
}
|
194
|
-
|
195
162
|
return new Promise((resolve, reject) => {
|
196
163
|
const proxy = getProxyForUrlWithNpmConfig(url);
|
197
164
|
debug('Downloading package', {
|
@@ -199,11 +166,9 @@ const downloadFromUrl = ({
|
|
199
166
|
proxy,
|
200
167
|
downloadDestination
|
201
168
|
});
|
202
|
-
|
203
169
|
if (ca) {
|
204
170
|
debug('using custom CA details from npm config');
|
205
171
|
}
|
206
|
-
|
207
172
|
const reqOptions = {
|
208
173
|
uri: url,
|
209
174
|
...(proxy ? {
|
@@ -217,8 +182,9 @@ const downloadFromUrl = ({
|
|
217
182
|
method: 'GET',
|
218
183
|
followRedirect: false
|
219
184
|
};
|
220
|
-
const req = request(reqOptions);
|
185
|
+
const req = request(reqOptions);
|
221
186
|
|
187
|
+
// closure
|
222
188
|
let started = null;
|
223
189
|
let expectedSize;
|
224
190
|
let expectedChecksum;
|
@@ -231,21 +197,18 @@ const downloadFromUrl = ({
|
|
231
197
|
// see https://github.com/cypress-io/cypress/pull/4092
|
232
198
|
expectedSize = response.headers['x-amz-meta-size'] || response.headers['content-length'];
|
233
199
|
expectedChecksum = response.headers['x-amz-meta-checksum'];
|
234
|
-
|
235
200
|
if (expectedChecksum) {
|
236
201
|
debug('expected checksum %s', expectedChecksum);
|
237
202
|
}
|
238
|
-
|
239
203
|
if (expectedSize) {
|
240
204
|
// convert from string (all Amazon custom headers are strings)
|
241
205
|
expectedSize = Number(expectedSize);
|
242
206
|
debug('expected file size %d', expectedSize);
|
243
|
-
}
|
244
|
-
// response headers
|
245
|
-
|
207
|
+
}
|
246
208
|
|
209
|
+
// start counting now once we've gotten
|
210
|
+
// response headers
|
247
211
|
started = new Date();
|
248
|
-
|
249
212
|
if (/^3/.test(response.statusCode)) {
|
250
213
|
const redirectVersion = response.headers['x-version'];
|
251
214
|
const redirectUrl = response.headers.location;
|
@@ -258,7 +221,9 @@ const downloadFromUrl = ({
|
|
258
221
|
downloadDestination,
|
259
222
|
version: redirectVersion,
|
260
223
|
redirectTTL: redirectTTL - 1
|
261
|
-
}).then(resolve).catch(reject);
|
224
|
+
}).then(resolve).catch(reject);
|
225
|
+
|
226
|
+
// if our status code does not start with 200
|
262
227
|
} else if (!/^2/.test(response.statusCode)) {
|
263
228
|
debug('response code %d', response.statusCode);
|
264
229
|
const err = new Error(stripIndent`
|
@@ -266,7 +231,8 @@ const downloadFromUrl = ({
|
|
266
231
|
Response code: ${response.statusCode}
|
267
232
|
Response message: ${response.statusMessage}
|
268
233
|
`);
|
269
|
-
reject(err);
|
234
|
+
reject(err);
|
235
|
+
// status codes here are all 2xx
|
270
236
|
} else {
|
271
237
|
// We only enable this pipe connection when we know we've got a successful return
|
272
238
|
// and handle the completion with verify and resolve
|
@@ -286,22 +252,23 @@ const downloadFromUrl = ({
|
|
286
252
|
}).on('progress', state => {
|
287
253
|
// total time we've elapsed
|
288
254
|
// starting on our first progress notification
|
289
|
-
const elapsed = new Date() - started;
|
255
|
+
const elapsed = new Date() - started;
|
290
256
|
|
257
|
+
// request-progress sends a value between 0 and 1
|
291
258
|
const percentage = util.convertPercentToPercentage(state.percent);
|
292
|
-
const eta = util.calculateEta(percentage, elapsed);
|
259
|
+
const eta = util.calculateEta(percentage, elapsed);
|
293
260
|
|
261
|
+
// send up our percent and seconds remaining
|
294
262
|
progress.onProgress(percentage, util.secsRemaining(eta));
|
295
263
|
});
|
296
264
|
});
|
297
265
|
};
|
266
|
+
|
298
267
|
/**
|
299
268
|
* Download Cypress.zip from external versionUrl to local file.
|
300
269
|
* @param [string] version Could be "3.3.0" or full URL
|
301
270
|
* @param [string] downloadDestination Local filename to save as
|
302
271
|
*/
|
303
|
-
|
304
|
-
|
305
272
|
const start = async opts => {
|
306
273
|
let {
|
307
274
|
version,
|
@@ -309,11 +276,9 @@ const start = async opts => {
|
|
309
276
|
progress,
|
310
277
|
redirectTTL
|
311
278
|
} = opts;
|
312
|
-
|
313
279
|
if (!downloadDestination) {
|
314
280
|
la(is.unemptyString(downloadDestination), 'missing download dir', opts);
|
315
281
|
}
|
316
|
-
|
317
282
|
if (!progress) {
|
318
283
|
progress = {
|
319
284
|
onProgress: () => {
|
@@ -321,14 +286,14 @@ const start = async opts => {
|
|
321
286
|
}
|
322
287
|
};
|
323
288
|
}
|
324
|
-
|
325
289
|
const arch = await util.getRealArch();
|
326
290
|
const versionUrl = getUrl(arch, version);
|
327
291
|
progress.throttle = 100;
|
328
292
|
debug('needed Cypress version: %s', version);
|
329
293
|
debug('source url %s', versionUrl);
|
330
|
-
debug(`downloading cypress.zip to "${downloadDestination}"`);
|
294
|
+
debug(`downloading cypress.zip to "${downloadDestination}"`);
|
331
295
|
|
296
|
+
// ensure download dir exists
|
332
297
|
return fs.ensureDirAsync(path.dirname(downloadDestination)).then(() => {
|
333
298
|
return getCA();
|
334
299
|
}).then(ca => {
|
@@ -346,7 +311,6 @@ const start = async opts => {
|
|
346
311
|
return prettyDownloadErr(err, versionUrl);
|
347
312
|
});
|
348
313
|
};
|
349
|
-
|
350
314
|
module.exports = {
|
351
315
|
start,
|
352
316
|
getUrl,
|
@@ -1,12 +1,11 @@
|
|
1
1
|
"use strict";
|
2
2
|
|
3
3
|
const fs = require('../fs');
|
4
|
-
|
5
4
|
const {
|
6
5
|
join
|
7
6
|
} = require('path');
|
8
|
-
|
9
7
|
const Bluebird = require('bluebird');
|
8
|
+
|
10
9
|
/**
|
11
10
|
* Get the size of a folder or a file.
|
12
11
|
*
|
@@ -16,26 +15,19 @@ const Bluebird = require('bluebird');
|
|
16
15
|
*
|
17
16
|
* @param {string} path path to the file or the folder.
|
18
17
|
*/
|
19
|
-
|
20
|
-
|
21
18
|
async function getSize(path) {
|
22
19
|
const stat = await fs.lstat(path);
|
23
|
-
|
24
20
|
if (stat.isDirectory()) {
|
25
21
|
const list = await fs.readdir(path);
|
26
22
|
return Bluebird.resolve(list).reduce(async (prev, curr) => {
|
27
23
|
const currPath = join(path, curr);
|
28
24
|
const s = await fs.lstat(currPath);
|
29
|
-
|
30
25
|
if (s.isDirectory()) {
|
31
26
|
return prev + (await getSize(currPath));
|
32
27
|
}
|
33
|
-
|
34
28
|
return prev + s.size;
|
35
29
|
}, 0);
|
36
30
|
}
|
37
|
-
|
38
31
|
return stat.size;
|
39
32
|
}
|
40
|
-
|
41
33
|
module.exports = getSize;
|