cypress 9.1.0 → 9.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.
- package/README.md +25 -25
- package/bin/cypress +3 -3
- package/lib/cli.js +14 -14
- package/lib/cypress.js +27 -27
- package/lib/errors.js +25 -25
- package/lib/exec/run.js +13 -13
- package/lib/exec/shared.js +8 -8
- package/lib/tasks/cache.js +3 -3
- package/lib/tasks/download.js +76 -48
- package/lib/tasks/get-folder-size.js +8 -8
- package/lib/tasks/state.js +17 -17
- package/lib/tasks/verify.js +12 -12
- package/lib/util.js +45 -45
- package/package.json +6 -5
- package/types/chai/index.d.ts +5 -5
- package/types/cy-blob-util.d.ts +13 -13
- package/types/cy-bluebird.d.ts +12 -12
- package/types/cy-chai.d.ts +10 -10
- package/types/cy-http.d.ts +13 -13
- package/types/cy-minimatch.d.ts +96 -96
- package/types/cypress-eventemitter.d.ts +33 -29
- package/types/cypress-expect.d.ts +3 -3
- package/types/cypress-global-vars.d.ts +22 -22
- package/types/cypress-npm-api.d.ts +404 -404
- package/types/cypress-type-helpers.d.ts +2 -2
- package/types/cypress.d.ts +5860 -5774
- package/types/index.d.ts +33 -33
- package/types/jquery/JQuery.d.ts +12939 -12939
- package/types/jquery/legacy.d.ts +200 -200
- package/types/jquery/misc.d.ts +6661 -6661
- package/types/minimatch/index.d.ts +0 -0
- package/types/mocha/index.d.ts +2801 -2801
- package/types/net-stubbing.ts +553 -553
- package/types/sinon/index.d.ts +227 -217
- package/types/sinon/ts3.1/index.d.ts +0 -1789
package/README.md
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
# Cypress
|
2
|
-
|
3
|
-
Fast, easy and reliable testing for anything that runs in a browser.
|
4
|
-
|
5
|
-
## What is this?
|
6
|
-
|
7
|
-
[Cypress](https://www.cypress.io/) comes packaged as an `npm` module, which is all you need to get started testing.
|
8
|
-
|
9
|
-
After installing you'll be able to:
|
10
|
-
|
11
|
-
- Open Cypress from the CLI
|
12
|
-
- Run Cypress from the CLI
|
13
|
-
- `require` Cypress as a module
|
14
|
-
|
15
|
-
## Install
|
16
|
-
|
17
|
-
Please check our [system requirements](https://on.cypress.io/installing-cypress).
|
18
|
-
|
19
|
-
```sh
|
20
|
-
npm install --save-dev cypress
|
21
|
-
```
|
22
|
-
|
23
|
-
## Documentation
|
24
|
-
|
25
|
-
Please [visit our documentation](https://on.cypress.io/cli) for a full list of commands and examples.
|
1
|
+
# Cypress
|
2
|
+
|
3
|
+
Fast, easy and reliable testing for anything that runs in a browser.
|
4
|
+
|
5
|
+
## What is this?
|
6
|
+
|
7
|
+
[Cypress](https://www.cypress.io/) comes packaged as an `npm` module, which is all you need to get started testing.
|
8
|
+
|
9
|
+
After installing you'll be able to:
|
10
|
+
|
11
|
+
- Open Cypress from the CLI
|
12
|
+
- Run Cypress from the CLI
|
13
|
+
- `require` Cypress as a module
|
14
|
+
|
15
|
+
## Install
|
16
|
+
|
17
|
+
Please check our [system requirements](https://on.cypress.io/installing-cypress).
|
18
|
+
|
19
|
+
```sh
|
20
|
+
npm install --save-dev cypress
|
21
|
+
```
|
22
|
+
|
23
|
+
## Documentation
|
24
|
+
|
25
|
+
Please [visit our documentation](https://on.cypress.io/cli) for a full list of commands and examples.
|
package/bin/cypress
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
|
3
|
-
require('../lib/cli').init()
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
require('../lib/cli').init()
|
package/lib/cli.js
CHANGED
@@ -223,12 +223,12 @@ const createProgram = () => {
|
|
223
223
|
const addCypressRunCommand = program => {
|
224
224
|
return program.command('run').usage('[options]').description('Runs Cypress tests from the CLI without the GUI').option('-b, --browser <browser-name-or-path>', text('browserRunMode')).option('--ci-build-id <id>', text('ciBuildId')).option('-c, --config <config>', text('config')).option('-C, --config-file <config-file>', text('configFile')).option('-e, --env <env>', text('env')).option('--group <name>', text('group')).option('-k, --key <record-key>', text('key')).option('--headed', text('headed')).option('--headless', text('headless')).option('--no-exit', text('exit')).option('--parallel', text('parallel')).option('-p, --port <port>', text('port')).option('-P, --project <project-path>', text('project')).option('-q, --quiet', text('quiet')).option('--record [bool]', text('record'), coerceFalse).option('-r, --reporter <reporter>', text('reporter')).option('-o, --reporter-options <reporter-options>', text('reporterOptions')).option('-s, --spec <spec>', text('spec')).option('-t, --tag <tag>', text('tag')).option('--dev', text('dev'), coerceFalse);
|
225
225
|
};
|
226
|
-
/**
|
227
|
-
* Casts known command line options for "cypress run" to their intended type.
|
228
|
-
* For example if the user passes "--port 5005" the ".port" property should be
|
229
|
-
* a number 5005 and not a string "5005".
|
230
|
-
*
|
231
|
-
* Returns a clone of the original object.
|
226
|
+
/**
|
227
|
+
* Casts known command line options for "cypress run" to their intended type.
|
228
|
+
* For example if the user passes "--port 5005" the ".port" property should be
|
229
|
+
* a number 5005 and not a string "5005".
|
230
|
+
*
|
231
|
+
* Returns a clone of the original object.
|
232
232
|
*/
|
233
233
|
|
234
234
|
|
@@ -251,12 +251,12 @@ const castCypressRunOptions = opts => {
|
|
251
251
|
};
|
252
252
|
|
253
253
|
module.exports = {
|
254
|
-
/**
|
255
|
-
* Parses `cypress run` command line option array into an object
|
256
|
-
* with options that you can feed into a `cypress.run()` module API call.
|
257
|
-
* @example
|
258
|
-
* const options = parseRunCommand(['cypress', 'run', '--browser', 'chrome'])
|
259
|
-
* // options is {browser: 'chrome'}
|
254
|
+
/**
|
255
|
+
* Parses `cypress run` command line option array into an object
|
256
|
+
* with options that you can feed into a `cypress.run()` module API call.
|
257
|
+
* @example
|
258
|
+
* const options = parseRunCommand(['cypress', 'run', '--browser', 'chrome'])
|
259
|
+
* // options is {browser: 'chrome'}
|
260
260
|
*/
|
261
261
|
parseRunCommand(args) {
|
262
262
|
return new Promise((resolve, reject) => {
|
@@ -284,8 +284,8 @@ module.exports = {
|
|
284
284
|
});
|
285
285
|
},
|
286
286
|
|
287
|
-
/**
|
288
|
-
* Parses the command line and kicks off Cypress process.
|
287
|
+
/**
|
288
|
+
* Parses the command line and kicks off Cypress process.
|
289
289
|
*/
|
290
290
|
init(args) {
|
291
291
|
if (!args) {
|
package/lib/cypress.js
CHANGED
@@ -16,18 +16,18 @@ const util = require('./util');
|
|
16
16
|
const cli = require('./cli');
|
17
17
|
|
18
18
|
const cypressModuleApi = {
|
19
|
-
/**
|
20
|
-
* Opens Cypress GUI
|
21
|
-
* @see https://on.cypress.io/module-api#cypress-open
|
19
|
+
/**
|
20
|
+
* Opens Cypress GUI
|
21
|
+
* @see https://on.cypress.io/module-api#cypress-open
|
22
22
|
*/
|
23
23
|
open(options = {}) {
|
24
24
|
options = util.normalizeModuleOptions(options);
|
25
25
|
return open.start(options);
|
26
26
|
},
|
27
27
|
|
28
|
-
/**
|
29
|
-
* Runs Cypress tests in the current project
|
30
|
-
* @see https://on.cypress.io/module-api#cypress-run
|
28
|
+
/**
|
29
|
+
* Runs Cypress tests in the current project
|
30
|
+
* @see https://on.cypress.io/module-api#cypress-run
|
31
31
|
*/
|
32
32
|
run(options = {}) {
|
33
33
|
if (!run.isValidProject(options.project)) {
|
@@ -56,15 +56,15 @@ const cypressModuleApi = {
|
|
56
56
|
},
|
57
57
|
|
58
58
|
cli: {
|
59
|
-
/**
|
60
|
-
* Parses CLI arguments into an object that you can pass to "cypress.run"
|
61
|
-
* @example
|
62
|
-
* const cypress = require('cypress')
|
63
|
-
* const cli = ['cypress', 'run', '--browser', 'firefox']
|
64
|
-
* const options = await cypress.cli.parseRunArguments(cli)
|
65
|
-
* // options is {browser: 'firefox'}
|
66
|
-
* await cypress.run(options)
|
67
|
-
* @see https://on.cypress.io/module-api
|
59
|
+
/**
|
60
|
+
* Parses CLI arguments into an object that you can pass to "cypress.run"
|
61
|
+
* @example
|
62
|
+
* const cypress = require('cypress')
|
63
|
+
* const cli = ['cypress', 'run', '--browser', 'firefox']
|
64
|
+
* const options = await cypress.cli.parseRunArguments(cli)
|
65
|
+
* // options is {browser: 'firefox'}
|
66
|
+
* await cypress.run(options)
|
67
|
+
* @see https://on.cypress.io/module-api
|
68
68
|
*/
|
69
69
|
parseRunArguments(args) {
|
70
70
|
return cli.parseRunCommand(args);
|
@@ -72,18 +72,18 @@ const cypressModuleApi = {
|
|
72
72
|
|
73
73
|
},
|
74
74
|
|
75
|
-
/**
|
76
|
-
* Provides automatic code completion for configuration in many popular code editors.
|
77
|
-
* While it's not strictly necessary for Cypress to parse your configuration, we
|
78
|
-
* recommend wrapping your config object with `defineConfig()`
|
79
|
-
* @example
|
80
|
-
* module.exports = defineConfig({
|
81
|
-
* viewportWith: 400
|
82
|
-
* })
|
83
|
-
*
|
84
|
-
* @see ../types/cypress-npm-api.d.ts
|
85
|
-
* @param {Cypress.ConfigOptions} config
|
86
|
-
* @returns {Cypress.ConfigOptions} the configuration passed in parameter
|
75
|
+
/**
|
76
|
+
* Provides automatic code completion for configuration in many popular code editors.
|
77
|
+
* While it's not strictly necessary for Cypress to parse your configuration, we
|
78
|
+
* recommend wrapping your config object with `defineConfig()`
|
79
|
+
* @example
|
80
|
+
* module.exports = defineConfig({
|
81
|
+
* viewportWith: 400
|
82
|
+
* })
|
83
|
+
*
|
84
|
+
* @see ../types/cypress-npm-api.d.ts
|
85
|
+
* @param {Cypress.ConfigOptions} config
|
86
|
+
* @returns {Cypress.ConfigOptions} the configuration passed in parameter
|
87
87
|
*/
|
88
88
|
defineConfig(config) {
|
89
89
|
return config;
|
package/lib/errors.js
CHANGED
@@ -208,12 +208,12 @@ const invalidTestingType = {
|
|
208
208
|
description: 'Invalid testingType',
|
209
209
|
solution: `Please provide a valid testingType. Valid test types are ${chalk.cyan('\'e2e\'')} and ${chalk.cyan('\'component\'')}.`
|
210
210
|
};
|
211
|
-
/**
|
212
|
-
* This error happens when CLI detects that the child Test Runner process
|
213
|
-
* was killed with a signal, like SIGBUS
|
214
|
-
* @see https://github.com/cypress-io/cypress/issues/5808
|
215
|
-
* @param {'close'|'event'} eventName Child close event name
|
216
|
-
* @param {string} signal Signal that closed the child process, like "SIGBUS"
|
211
|
+
/**
|
212
|
+
* This error happens when CLI detects that the child Test Runner process
|
213
|
+
* was killed with a signal, like SIGBUS
|
214
|
+
* @see https://github.com/cypress-io/cypress/issues/5808
|
215
|
+
* @param {'close'|'event'} eventName Child close event name
|
216
|
+
* @param {string} signal Signal that closed the child process, like "SIGBUS"
|
217
217
|
*/
|
218
218
|
|
219
219
|
const childProcessKilled = (eventName, signal) => {
|
@@ -240,17 +240,17 @@ function addPlatformInformation(info) {
|
|
240
240
|
};
|
241
241
|
});
|
242
242
|
}
|
243
|
-
/**
|
244
|
-
* Given an error object (see the errors above), forms error message text with details,
|
245
|
-
* then resolves with Error instance you can throw or reject with.
|
246
|
-
* @param {object} errorObject
|
247
|
-
* @returns {Promise<Error>} resolves with an Error
|
248
|
-
* @example
|
249
|
-
```js
|
250
|
-
// inside a Promise with "resolve" and "reject"
|
251
|
-
const errorObject = childProcessKilled('exit', 'SIGKILL')
|
252
|
-
return getError(errorObject).then(reject)
|
253
|
-
```
|
243
|
+
/**
|
244
|
+
* Given an error object (see the errors above), forms error message text with details,
|
245
|
+
* then resolves with Error instance you can throw or reject with.
|
246
|
+
* @param {object} errorObject
|
247
|
+
* @returns {Promise<Error>} resolves with an Error
|
248
|
+
* @example
|
249
|
+
```js
|
250
|
+
// inside a Promise with "resolve" and "reject"
|
251
|
+
const errorObject = childProcessKilled('exit', 'SIGKILL')
|
252
|
+
return getError(errorObject).then(reject)
|
253
|
+
```
|
254
254
|
*/
|
255
255
|
|
256
256
|
|
@@ -261,9 +261,9 @@ function getError(errorObject) {
|
|
261
261
|
return err;
|
262
262
|
});
|
263
263
|
}
|
264
|
-
/**
|
265
|
-
* Forms nice error message with error and platform information,
|
266
|
-
* and if possible a way to solve it. Resolves with a string.
|
264
|
+
/**
|
265
|
+
* Forms nice error message with error and platform information,
|
266
|
+
* and if possible a way to solve it. Resolves with a string.
|
267
267
|
*/
|
268
268
|
|
269
269
|
|
@@ -343,11 +343,11 @@ const throwFormErrorText = info => {
|
|
343
343
|
return formErrorText(info, msg, prevMessage).then(raise(info));
|
344
344
|
};
|
345
345
|
};
|
346
|
-
/**
|
347
|
-
* Forms full error message with error and OS details, prints to the error output
|
348
|
-
* and then exits the process.
|
349
|
-
* @param {ErrorInformation} info Error information {description, solution}
|
350
|
-
* @example return exitWithError(errors.invalidCypressEnv)('foo')
|
346
|
+
/**
|
347
|
+
* Forms full error message with error and OS details, prints to the error output
|
348
|
+
* and then exits the process.
|
349
|
+
* @param {ErrorInformation} info Error information {description, solution}
|
350
|
+
* @example return exitWithError(errors.invalidCypressEnv)('foo')
|
351
351
|
*/
|
352
352
|
|
353
353
|
|
package/lib/exec/run.js
CHANGED
@@ -19,11 +19,11 @@ const {
|
|
19
19
|
processTestingType,
|
20
20
|
throwInvalidOptionError
|
21
21
|
} = require('./shared');
|
22
|
-
/**
|
23
|
-
* Typically a user passes a string path to the project.
|
24
|
-
* But "cypress open" allows using `false` to open in global mode,
|
25
|
-
* and the user can accidentally execute `cypress run --project false`
|
26
|
-
* which should be invalid.
|
22
|
+
/**
|
23
|
+
* Typically a user passes a string path to the project.
|
24
|
+
* But "cypress open" allows using `false` to open in global mode,
|
25
|
+
* and the user can accidentally execute `cypress run --project false`
|
26
|
+
* which should be invalid.
|
27
27
|
*/
|
28
28
|
|
29
29
|
|
@@ -38,14 +38,14 @@ const isValidProject = v => {
|
|
38
38
|
|
39
39
|
return true;
|
40
40
|
};
|
41
|
-
/**
|
42
|
-
* Maps options collected by the CLI
|
43
|
-
* and forms list of CLI arguments to the server.
|
44
|
-
*
|
45
|
-
* Note: there is lightweight validation, with errors
|
46
|
-
* thrown synchronously.
|
47
|
-
*
|
48
|
-
* @returns {string[]} list of CLI arguments
|
41
|
+
/**
|
42
|
+
* Maps options collected by the CLI
|
43
|
+
* and forms list of CLI arguments to the server.
|
44
|
+
*
|
45
|
+
* Note: there is lightweight validation, with errors
|
46
|
+
* thrown synchronously.
|
47
|
+
*
|
48
|
+
* @returns {string[]} list of CLI arguments
|
49
49
|
*/
|
50
50
|
|
51
51
|
|
package/lib/exec/shared.js
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
const {
|
4
4
|
errors
|
5
5
|
} = require('../errors');
|
6
|
-
/**
|
7
|
-
* Throws an error with "details" property from
|
8
|
-
* "errors" object.
|
9
|
-
* @param {Object} details - Error details
|
6
|
+
/**
|
7
|
+
* Throws an error with "details" property from
|
8
|
+
* "errors" object.
|
9
|
+
* @param {Object} details - Error details
|
10
10
|
*/
|
11
11
|
|
12
12
|
|
@@ -21,10 +21,10 @@ const throwInvalidOptionError = details => {
|
|
21
21
|
err.details = details;
|
22
22
|
throw err;
|
23
23
|
};
|
24
|
-
/**
|
25
|
-
* Selects exec args based on the configured `testingType`
|
26
|
-
* @param {string} testingType The type of tests being executed
|
27
|
-
* @returns {string[]} The array of new exec arguments
|
24
|
+
/**
|
25
|
+
* Selects exec args based on the configured `testingType`
|
26
|
+
* @param {string} testingType The type of tests being executed
|
27
|
+
* @returns {string[]} The array of new exec arguments
|
28
28
|
*/
|
29
29
|
|
30
30
|
|
package/lib/tasks/cache.js
CHANGED
@@ -72,9 +72,9 @@ const prune = () => {
|
|
72
72
|
const fileSizeInMB = size => {
|
73
73
|
return `${(size / 1024 / 1024).toFixed(1)}MB`;
|
74
74
|
};
|
75
|
-
/**
|
76
|
-
* Collects all cached versions, finds when each was used
|
77
|
-
* and prints a table with results to the terminal
|
75
|
+
/**
|
76
|
+
* Collects all cached versions, finds when each was used
|
77
|
+
* and prints a table with results to the terminal
|
78
78
|
*/
|
79
79
|
|
80
80
|
|
package/lib/tasks/download.js
CHANGED
@@ -8,7 +8,7 @@ const is = require('check-more-types');
|
|
8
8
|
|
9
9
|
const os = require('os');
|
10
10
|
|
11
|
-
const
|
11
|
+
const Url = require('url');
|
12
12
|
|
13
13
|
const path = require('path');
|
14
14
|
|
@@ -36,6 +36,7 @@ const fs = require('../fs');
|
|
36
36
|
const util = require('../util');
|
37
37
|
|
38
38
|
const defaultBaseUrl = 'https://download.cypress.io/';
|
39
|
+
const defaultMaxRedirects = 10;
|
39
40
|
|
40
41
|
const getProxyForUrlWithNpmConfig = url => {
|
41
42
|
return getProxyForUrl(url) || process.env.npm_config_https_proxy || process.env.npm_config_proxy || null;
|
@@ -76,9 +77,10 @@ const getCA = () => {
|
|
76
77
|
};
|
77
78
|
|
78
79
|
const prepend = urlPath => {
|
79
|
-
const endpoint =
|
80
|
+
const endpoint = Url.resolve(getBaseUrl(), urlPath);
|
80
81
|
const platform = os.platform();
|
81
|
-
|
82
|
+
const pathTemplate = util.getEnv('CYPRESS_DOWNLOAD_PATH_TEMPLATE');
|
83
|
+
return pathTemplate ? pathTemplate.replace('${endpoint}', endpoint).replace('${platform}', platform).replace('${arch}', arch()) : `${endpoint}?platform=${platform}&arch=${arch()}`;
|
82
84
|
};
|
83
85
|
|
84
86
|
const getUrl = version => {
|
@@ -102,9 +104,9 @@ const prettyDownloadErr = (err, version) => {
|
|
102
104
|
debug(msg);
|
103
105
|
return throwFormErrorText(errors.failedDownload)(msg);
|
104
106
|
};
|
105
|
-
/**
|
106
|
-
* Checks checksum and file size for the given file. Allows both
|
107
|
-
* values or just one of them to be checked.
|
107
|
+
/**
|
108
|
+
* Checks checksum and file size for the given file. Allows both
|
109
|
+
* values or just one of them to be checked.
|
108
110
|
*/
|
109
111
|
|
110
112
|
|
@@ -183,8 +185,18 @@ const downloadFromUrl = ({
|
|
183
185
|
url,
|
184
186
|
downloadDestination,
|
185
187
|
progress,
|
186
|
-
ca
|
188
|
+
ca,
|
189
|
+
version,
|
190
|
+
redirectTTL = defaultMaxRedirects
|
187
191
|
}) => {
|
192
|
+
if (redirectTTL <= 0) {
|
193
|
+
return Promise.reject(new Error(stripIndent`
|
194
|
+
Failed downloading the Cypress binary.
|
195
|
+
There were too many redirects. The default allowance is ${defaultMaxRedirects}.
|
196
|
+
Maybe you got stuck in a redirect loop?
|
197
|
+
`));
|
198
|
+
}
|
199
|
+
|
188
200
|
return new Promise((resolve, reject) => {
|
189
201
|
const proxy = getProxyForUrlWithNpmConfig(url);
|
190
202
|
debug('Downloading package', {
|
@@ -192,35 +204,24 @@ const downloadFromUrl = ({
|
|
192
204
|
proxy,
|
193
205
|
downloadDestination
|
194
206
|
});
|
195
|
-
let redirectVersion;
|
196
|
-
const reqOptions = {
|
197
|
-
url,
|
198
|
-
proxy,
|
199
|
-
|
200
|
-
followRedirect(response) {
|
201
|
-
const version = response.headers['x-version'];
|
202
|
-
debug('redirect version:', version);
|
203
|
-
|
204
|
-
if (version) {
|
205
|
-
// set the version in options if we have one.
|
206
|
-
// this insulates us from potential redirect
|
207
|
-
// problems where version would be set to undefined.
|
208
|
-
redirectVersion = version;
|
209
|
-
} // yes redirect
|
210
|
-
|
211
|
-
|
212
|
-
return true;
|
213
|
-
}
|
214
|
-
|
215
|
-
};
|
216
207
|
|
217
208
|
if (ca) {
|
218
209
|
debug('using custom CA details from npm config');
|
219
|
-
reqOptions.agentOptions = {
|
220
|
-
ca
|
221
|
-
};
|
222
210
|
}
|
223
211
|
|
212
|
+
const reqOptions = {
|
213
|
+
uri: url,
|
214
|
+
...(proxy ? {
|
215
|
+
proxy
|
216
|
+
} : {}),
|
217
|
+
...(ca ? {
|
218
|
+
agentOptions: {
|
219
|
+
ca
|
220
|
+
}
|
221
|
+
} : {}),
|
222
|
+
method: 'GET',
|
223
|
+
followRedirect: false
|
224
|
+
};
|
224
225
|
const req = request(reqOptions); // closure
|
225
226
|
|
226
227
|
let started = null;
|
@@ -248,18 +249,46 @@ const downloadFromUrl = ({
|
|
248
249
|
// response headers
|
249
250
|
|
250
251
|
|
251
|
-
started = new Date();
|
252
|
-
|
253
|
-
if (
|
252
|
+
started = new Date();
|
253
|
+
|
254
|
+
if (/^3/.test(response.statusCode)) {
|
255
|
+
const redirectVersion = response.headers['x-version'];
|
256
|
+
const redirectUrl = response.headers.location;
|
257
|
+
debug('redirect version:', redirectVersion);
|
258
|
+
debug('redirect url:', redirectUrl);
|
259
|
+
downloadFromUrl({
|
260
|
+
url: redirectUrl,
|
261
|
+
progress,
|
262
|
+
ca,
|
263
|
+
downloadDestination,
|
264
|
+
version: redirectVersion,
|
265
|
+
redirectTTL: redirectTTL - 1
|
266
|
+
}).then(resolve).catch(reject); // if our status code does not start with 200
|
267
|
+
} else if (!/^2/.test(response.statusCode)) {
|
254
268
|
debug('response code %d', response.statusCode);
|
255
269
|
const err = new Error(stripIndent`
|
256
270
|
Failed downloading the Cypress binary.
|
257
271
|
Response code: ${response.statusCode}
|
258
272
|
Response message: ${response.statusMessage}
|
259
273
|
`);
|
260
|
-
reject(err);
|
274
|
+
reject(err); // status codes here are all 2xx
|
275
|
+
} else {
|
276
|
+
// We only enable this pipe connection when we know we've got a successful return
|
277
|
+
// and handle the completion with verify and resolve
|
278
|
+
// there was a possible race condition between end of request and close of writeStream
|
279
|
+
// that is made ordered with this Promise.all
|
280
|
+
Promise.all([new Promise(r => {
|
281
|
+
return response.pipe(fs.createWriteStream(downloadDestination).on('close', r));
|
282
|
+
}), new Promise(r => response.on('end', r))]).then(() => {
|
283
|
+
debug('downloading finished');
|
284
|
+
verifyDownloadedFile(downloadDestination, expectedSize, expectedChecksum).then(() => debug('verified')).then(() => resolve(version)).catch(reject);
|
285
|
+
});
|
261
286
|
}
|
262
|
-
}).on('error',
|
287
|
+
}).on('error', e => {
|
288
|
+
if (e.code === 'ECONNRESET') return; // sometimes proxies give ECONNRESET but we don't care
|
289
|
+
|
290
|
+
reject(e);
|
291
|
+
}).on('progress', state => {
|
263
292
|
// total time we've elapsed
|
264
293
|
// starting on our first progress notification
|
265
294
|
const elapsed = new Date() - started; // request-progress sends a value between 0 and 1
|
@@ -268,19 +297,13 @@ const downloadFromUrl = ({
|
|
268
297
|
const eta = util.calculateEta(percentage, elapsed); // send up our percent and seconds remaining
|
269
298
|
|
270
299
|
progress.onProgress(percentage, util.secsRemaining(eta));
|
271
|
-
}) // save this download here
|
272
|
-
.pipe(fs.createWriteStream(downloadDestination)).on('finish', () => {
|
273
|
-
debug('downloading finished');
|
274
|
-
verifyDownloadedFile(downloadDestination, expectedSize, expectedChecksum).then(() => {
|
275
|
-
return resolve(redirectVersion);
|
276
|
-
}, reject);
|
277
300
|
});
|
278
301
|
});
|
279
302
|
};
|
280
|
-
/**
|
281
|
-
* Download Cypress.zip from external url to local file.
|
282
|
-
* @param [string] version Could be "3.3.0" or full URL
|
283
|
-
* @param [string] downloadDestination Local filename to save as
|
303
|
+
/**
|
304
|
+
* Download Cypress.zip from external url to local file.
|
305
|
+
* @param [string] version Could be "3.3.0" or full URL
|
306
|
+
* @param [string] downloadDestination Local filename to save as
|
284
307
|
*/
|
285
308
|
|
286
309
|
|
@@ -288,7 +311,8 @@ const start = opts => {
|
|
288
311
|
let {
|
289
312
|
version,
|
290
313
|
downloadDestination,
|
291
|
-
progress
|
314
|
+
progress,
|
315
|
+
redirectTTL
|
292
316
|
} = opts;
|
293
317
|
|
294
318
|
if (!downloadDestination) {
|
@@ -316,7 +340,11 @@ const start = opts => {
|
|
316
340
|
url,
|
317
341
|
downloadDestination,
|
318
342
|
progress,
|
319
|
-
ca
|
343
|
+
ca,
|
344
|
+
version,
|
345
|
+
...(redirectTTL ? {
|
346
|
+
redirectTTL
|
347
|
+
} : {})
|
320
348
|
});
|
321
349
|
}).catch(err => {
|
322
350
|
return prettyDownloadErr(err, version);
|
@@ -7,14 +7,14 @@ const {
|
|
7
7
|
} = require('path');
|
8
8
|
|
9
9
|
const Bluebird = require('bluebird');
|
10
|
-
/**
|
11
|
-
* Get the size of a folder or a file.
|
12
|
-
*
|
13
|
-
* This function returns the actual file size of the folder (size), not the allocated space on disk (size on disk).
|
14
|
-
* For more details between the difference, check this link:
|
15
|
-
* https://www.howtogeek.com/180369/why-is-there-a-big-difference-between-size-and-size-on-disk/
|
16
|
-
*
|
17
|
-
* @param {string} path path to the file or the folder.
|
10
|
+
/**
|
11
|
+
* Get the size of a folder or a file.
|
12
|
+
*
|
13
|
+
* This function returns the actual file size of the folder (size), not the allocated space on disk (size on disk).
|
14
|
+
* For more details between the difference, check this link:
|
15
|
+
* https://www.howtogeek.com/180369/why-is-there-a-big-difference-between-size-and-size-on-disk/
|
16
|
+
*
|
17
|
+
* @param {string} path path to the file or the folder.
|
18
18
|
*/
|
19
19
|
|
20
20
|
|
package/lib/tasks/state.js
CHANGED
@@ -70,8 +70,8 @@ const getBinaryPkgPath = binaryDir => {
|
|
70
70
|
throw new Error(`Platform: "${platform}" is not supported.`);
|
71
71
|
}
|
72
72
|
};
|
73
|
-
/**
|
74
|
-
* Get path to binary directory
|
73
|
+
/**
|
74
|
+
* Get path to binary directory
|
75
75
|
*/
|
76
76
|
|
77
77
|
|
@@ -82,9 +82,9 @@ const getBinaryDir = (version = util.pkgVersion()) => {
|
|
82
82
|
const getVersionDir = (version = util.pkgVersion()) => {
|
83
83
|
return path.join(getCacheDir(), version);
|
84
84
|
};
|
85
|
-
/**
|
86
|
-
* When executing "npm postinstall" hook, the working directory is set to
|
87
|
-
* "<current folder>/node_modules/cypress", which can be surprising when using relative paths.
|
85
|
+
/**
|
86
|
+
* When executing "npm postinstall" hook, the working directory is set to
|
87
|
+
* "<current folder>/node_modules/cypress", which can be surprising when using relative paths.
|
88
88
|
*/
|
89
89
|
|
90
90
|
|
@@ -134,10 +134,10 @@ const parseRealPlatformBinaryFolderAsync = binaryPath => {
|
|
134
134
|
const getDistDir = () => {
|
135
135
|
return path.join(__dirname, '..', '..', 'dist');
|
136
136
|
};
|
137
|
-
/**
|
138
|
-
* Returns full filename to the file that keeps the Test Runner verification state as JSON text.
|
139
|
-
* Note: the binary state file will be stored one level up from the given binary folder.
|
140
|
-
* @param {string} binaryDir - full path to the folder holding the binary.
|
137
|
+
/**
|
138
|
+
* Returns full filename to the file that keeps the Test Runner verification state as JSON text.
|
139
|
+
* Note: the binary state file will be stored one level up from the given binary folder.
|
140
|
+
* @param {string} binaryDir - full path to the folder holding the binary.
|
141
141
|
*/
|
142
142
|
|
143
143
|
|
@@ -162,11 +162,11 @@ const getBinaryVerifiedAsync = binaryDir => {
|
|
162
162
|
const clearBinaryStateAsync = binaryDir => {
|
163
163
|
return fs.removeAsync(getBinaryStatePath(binaryDir));
|
164
164
|
};
|
165
|
-
/**
|
166
|
-
* Writes the new binary status.
|
167
|
-
* @param {boolean} verified The new test runner state after smoke test
|
168
|
-
* @param {string} binaryDir Folder holding the binary
|
169
|
-
* @returns {Promise<void>} returns a promise
|
165
|
+
/**
|
166
|
+
* Writes the new binary status.
|
167
|
+
* @param {boolean} verified The new test runner state after smoke test
|
168
|
+
* @param {string} binaryDir Folder holding the binary
|
169
|
+
* @returns {Promise<void>} returns a promise
|
170
170
|
*/
|
171
171
|
|
172
172
|
|
@@ -183,9 +183,9 @@ const writeBinaryVerifiedAsync = (verified, binaryDir) => {
|
|
183
183
|
const getPathToExecutable = binaryDir => {
|
184
184
|
return path.join(binaryDir, getPlatformExecutable());
|
185
185
|
};
|
186
|
-
/**
|
187
|
-
* Resolves with an object read from the binary app package.json file.
|
188
|
-
* If the file does not exist resolves with null
|
186
|
+
/**
|
187
|
+
* Resolves with an object read from the binary app package.json file.
|
188
|
+
* If the file does not exist resolves with null
|
189
189
|
*/
|
190
190
|
|
191
191
|
|