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