cypress 5.1.0 → 5.5.0
Sign up to get free protection for your applications and to get access to all the features.
- package/index.js +6 -6
- package/lib/cli.js +114 -107
- package/lib/cypress.js +21 -21
- package/lib/errors.js +233 -276
- package/lib/exec/info.js +29 -32
- package/lib/exec/open.js +7 -8
- package/lib/exec/run.js +20 -20
- package/lib/exec/spawn.js +53 -49
- package/lib/exec/versions.js +18 -17
- package/lib/exec/xvfb.js +43 -37
- package/lib/fs.js +1 -1
- package/lib/logger.js +24 -50
- package/lib/tasks/cache.js +96 -36
- package/lib/tasks/download.js +113 -133
- package/lib/tasks/get-folder-size.js +41 -0
- package/lib/tasks/install.js +225 -161
- package/lib/tasks/state.js +54 -56
- package/lib/tasks/unzip.js +72 -69
- package/lib/tasks/verify.js +112 -147
- package/lib/util.js +172 -176
- package/package.json +3 -3
- package/types/cypress-npm-api.d.ts +13 -5
- package/types/cypress.d.ts +51 -48
- package/types/mocha/index.d.ts +123 -308
- package/types/net-stubbing.ts +169 -19
package/lib/tasks/state.js
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
"use strict";
|
2
2
|
|
3
|
-
|
3
|
+
const _ = require('lodash');
|
4
4
|
|
5
|
-
|
5
|
+
const os = require('os');
|
6
6
|
|
7
|
-
|
7
|
+
const path = require('path');
|
8
8
|
|
9
|
-
|
9
|
+
const untildify = require('untildify');
|
10
10
|
|
11
|
-
|
11
|
+
const debug = require('debug')('cypress:cli');
|
12
12
|
|
13
|
-
|
13
|
+
const fs = require('../fs');
|
14
14
|
|
15
|
-
|
15
|
+
const util = require('../util');
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
const getPlatformExecutable = () => {
|
18
|
+
const platform = os.platform();
|
19
19
|
|
20
20
|
switch (platform) {
|
21
21
|
case 'darwin':
|
@@ -29,12 +29,12 @@ var getPlatformExecutable = function getPlatformExecutable() {
|
|
29
29
|
// TODO handle this error using our standard
|
30
30
|
|
31
31
|
default:
|
32
|
-
throw new Error(
|
32
|
+
throw new Error(`Platform: "${platform}" is not supported.`);
|
33
33
|
}
|
34
34
|
};
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
const getPlatFormBinaryFolder = () => {
|
37
|
+
const platform = os.platform();
|
38
38
|
|
39
39
|
switch (platform) {
|
40
40
|
case 'darwin':
|
@@ -48,12 +48,12 @@ var getPlatFormBinaryFolder = function getPlatFormBinaryFolder() {
|
|
48
48
|
// TODO handle this error using our standard
|
49
49
|
|
50
50
|
default:
|
51
|
-
throw new Error(
|
51
|
+
throw new Error(`Platform: "${platform}" is not supported.`);
|
52
52
|
}
|
53
53
|
};
|
54
54
|
|
55
|
-
|
56
|
-
|
55
|
+
const getBinaryPkgPath = binaryDir => {
|
56
|
+
const platform = os.platform();
|
57
57
|
|
58
58
|
switch (platform) {
|
59
59
|
case 'darwin':
|
@@ -67,7 +67,7 @@ var getBinaryPkgPath = function getBinaryPkgPath(binaryDir) {
|
|
67
67
|
// TODO handle this error using our standard
|
68
68
|
|
69
69
|
default:
|
70
|
-
throw new Error(
|
70
|
+
throw new Error(`Platform: "${platform}" is not supported.`);
|
71
71
|
}
|
72
72
|
};
|
73
73
|
/**
|
@@ -75,13 +75,11 @@ var getBinaryPkgPath = function getBinaryPkgPath(binaryDir) {
|
|
75
75
|
*/
|
76
76
|
|
77
77
|
|
78
|
-
|
79
|
-
var version = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : util.pkgVersion();
|
78
|
+
const getBinaryDir = (version = util.pkgVersion()) => {
|
80
79
|
return path.join(getVersionDir(version), getPlatFormBinaryFolder());
|
81
80
|
};
|
82
81
|
|
83
|
-
|
84
|
-
var version = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : util.pkgVersion();
|
82
|
+
const getVersionDir = (version = util.pkgVersion()) => {
|
85
83
|
return path.join(getCacheDir(), version);
|
86
84
|
};
|
87
85
|
/**
|
@@ -90,22 +88,22 @@ var getVersionDir = function getVersionDir() {
|
|
90
88
|
*/
|
91
89
|
|
92
90
|
|
93
|
-
|
91
|
+
const isInstallingFromPostinstallHook = () => {
|
94
92
|
// individual folders
|
95
|
-
|
96
|
-
|
93
|
+
const cwdFolders = process.cwd().split(path.sep);
|
94
|
+
const length = cwdFolders.length;
|
97
95
|
return cwdFolders[length - 2] === 'node_modules' && cwdFolders[length - 1] === 'cypress';
|
98
96
|
};
|
99
97
|
|
100
|
-
|
101
|
-
|
98
|
+
const getCacheDir = () => {
|
99
|
+
let cache_directory = util.getCacheDir();
|
102
100
|
|
103
101
|
if (util.getEnv('CYPRESS_CACHE_FOLDER')) {
|
104
|
-
|
102
|
+
const envVarCacheDir = untildify(util.getEnv('CYPRESS_CACHE_FOLDER'));
|
105
103
|
debug('using environment variable CYPRESS_CACHE_FOLDER %s', envVarCacheDir);
|
106
104
|
|
107
105
|
if (!path.isAbsolute(envVarCacheDir) && isInstallingFromPostinstallHook()) {
|
108
|
-
|
106
|
+
const packageRootFolder = path.join('..', '..', envVarCacheDir);
|
109
107
|
cache_directory = path.resolve(packageRootFolder);
|
110
108
|
debug('installing from postinstall hook, original root folder is %s', packageRootFolder);
|
111
109
|
debug('and resolved cache directory is %s', cache_directory);
|
@@ -117,8 +115,8 @@ var getCacheDir = function getCacheDir() {
|
|
117
115
|
return cache_directory;
|
118
116
|
};
|
119
117
|
|
120
|
-
|
121
|
-
return fs.realpathAsync(binaryPath).then(
|
118
|
+
const parseRealPlatformBinaryFolderAsync = binaryPath => {
|
119
|
+
return fs.realpathAsync(binaryPath).then(realPath => {
|
122
120
|
debug('CYPRESS_RUN_BINARY has realpath:', realPath);
|
123
121
|
|
124
122
|
if (!realPath.toString().endsWith(getPlatformExecutable())) {
|
@@ -133,7 +131,7 @@ var parseRealPlatformBinaryFolderAsync = function parseRealPlatformBinaryFolderA
|
|
133
131
|
});
|
134
132
|
};
|
135
133
|
|
136
|
-
|
134
|
+
const getDistDir = () => {
|
137
135
|
return path.join(__dirname, '..', '..', 'dist');
|
138
136
|
};
|
139
137
|
/**
|
@@ -143,25 +141,25 @@ var getDistDir = function getDistDir() {
|
|
143
141
|
*/
|
144
142
|
|
145
143
|
|
146
|
-
|
144
|
+
const getBinaryStatePath = binaryDir => {
|
147
145
|
return path.join(binaryDir, '..', 'binary_state.json');
|
148
146
|
};
|
149
147
|
|
150
|
-
|
151
|
-
|
152
|
-
return fs.readJsonAsync(fullPath)
|
148
|
+
const getBinaryStateContentsAsync = binaryDir => {
|
149
|
+
const fullPath = getBinaryStatePath(binaryDir);
|
150
|
+
return fs.readJsonAsync(fullPath).catch({
|
153
151
|
code: 'ENOENT'
|
154
|
-
}, SyntaxError,
|
152
|
+
}, SyntaxError, () => {
|
155
153
|
debug('could not read binary_state.json file at "%s"', fullPath);
|
156
154
|
return {};
|
157
155
|
});
|
158
156
|
};
|
159
157
|
|
160
|
-
|
158
|
+
const getBinaryVerifiedAsync = binaryDir => {
|
161
159
|
return getBinaryStateContentsAsync(binaryDir).tap(debug).get('verified');
|
162
160
|
};
|
163
161
|
|
164
|
-
|
162
|
+
const clearBinaryStateAsync = binaryDir => {
|
165
163
|
return fs.removeAsync(getBinaryStatePath(binaryDir));
|
166
164
|
};
|
167
165
|
/**
|
@@ -172,24 +170,24 @@ var clearBinaryStateAsync = function clearBinaryStateAsync(binaryDir) {
|
|
172
170
|
*/
|
173
171
|
|
174
172
|
|
175
|
-
|
176
|
-
return getBinaryStateContentsAsync(binaryDir).then(
|
173
|
+
const writeBinaryVerifiedAsync = (verified, binaryDir) => {
|
174
|
+
return getBinaryStateContentsAsync(binaryDir).then(contents => {
|
177
175
|
return fs.outputJsonAsync(getBinaryStatePath(binaryDir), _.extend(contents, {
|
178
|
-
verified
|
176
|
+
verified
|
179
177
|
}), {
|
180
178
|
spaces: 2
|
181
179
|
});
|
182
180
|
});
|
183
181
|
};
|
184
182
|
|
185
|
-
|
183
|
+
const getPathToExecutable = binaryDir => {
|
186
184
|
return path.join(binaryDir, getPlatformExecutable());
|
187
185
|
};
|
188
186
|
|
189
|
-
|
190
|
-
|
187
|
+
const getBinaryPkgVersionAsync = binaryDir => {
|
188
|
+
const pathToPackageJson = getBinaryPkgPath(binaryDir);
|
191
189
|
debug('Reading binary package.json from:', pathToPackageJson);
|
192
|
-
return fs.pathExistsAsync(pathToPackageJson).then(
|
190
|
+
return fs.pathExistsAsync(pathToPackageJson).then(exists => {
|
193
191
|
if (!exists) {
|
194
192
|
return null;
|
195
193
|
}
|
@@ -199,16 +197,16 @@ var getBinaryPkgVersionAsync = function getBinaryPkgVersionAsync(binaryDir) {
|
|
199
197
|
};
|
200
198
|
|
201
199
|
module.exports = {
|
202
|
-
getPathToExecutable
|
203
|
-
getPlatformExecutable
|
204
|
-
getBinaryPkgVersionAsync
|
205
|
-
getBinaryVerifiedAsync
|
206
|
-
getBinaryPkgPath
|
207
|
-
getBinaryDir
|
208
|
-
getCacheDir
|
209
|
-
clearBinaryStateAsync
|
210
|
-
writeBinaryVerifiedAsync
|
211
|
-
parseRealPlatformBinaryFolderAsync
|
212
|
-
getDistDir
|
213
|
-
getVersionDir
|
200
|
+
getPathToExecutable,
|
201
|
+
getPlatformExecutable,
|
202
|
+
getBinaryPkgVersionAsync,
|
203
|
+
getBinaryVerifiedAsync,
|
204
|
+
getBinaryPkgPath,
|
205
|
+
getBinaryDir,
|
206
|
+
getCacheDir,
|
207
|
+
clearBinaryStateAsync,
|
208
|
+
writeBinaryVerifiedAsync,
|
209
|
+
parseRealPlatformBinaryFolderAsync,
|
210
|
+
getDistDir,
|
211
|
+
getVersionDir
|
214
212
|
};
|
package/lib/tasks/unzip.js
CHANGED
@@ -1,41 +1,43 @@
|
|
1
1
|
"use strict";
|
2
2
|
|
3
|
-
|
3
|
+
const _ = require('lodash');
|
4
4
|
|
5
|
-
|
5
|
+
const la = require('lazy-ass');
|
6
6
|
|
7
|
-
|
7
|
+
const is = require('check-more-types');
|
8
8
|
|
9
|
-
|
9
|
+
const cp = require('child_process');
|
10
10
|
|
11
|
-
|
11
|
+
const os = require('os');
|
12
12
|
|
13
|
-
|
13
|
+
const yauzl = require('yauzl');
|
14
14
|
|
15
|
-
|
15
|
+
const debug = require('debug')('cypress:cli:unzip');
|
16
16
|
|
17
|
-
|
17
|
+
const extract = require('extract-zip');
|
18
18
|
|
19
|
-
|
19
|
+
const Promise = require('bluebird');
|
20
20
|
|
21
|
-
|
21
|
+
const readline = require('readline');
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
const {
|
24
|
+
throwFormErrorText,
|
25
|
+
errors
|
26
|
+
} = require('../errors');
|
26
27
|
|
27
|
-
|
28
|
+
const fs = require('../fs');
|
28
29
|
|
29
|
-
|
30
|
+
const util = require('../util');
|
30
31
|
|
31
|
-
|
32
|
-
extract
|
32
|
+
const unzipTools = {
|
33
|
+
extract
|
33
34
|
}; // expose this function for simple testing
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
const unzip = ({
|
37
|
+
zipFilePath,
|
38
|
+
installDir,
|
39
|
+
progress
|
40
|
+
}) => {
|
39
41
|
debug('unzipping from %s', zipFilePath);
|
40
42
|
debug('into', installDir);
|
41
43
|
|
@@ -43,11 +45,11 @@ var unzip = function unzip(_ref) {
|
|
43
45
|
throw new Error('Missing zip filename');
|
44
46
|
}
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
-
return fs.ensureDirAsync(installDir).then(
|
49
|
-
return new Promise(
|
50
|
-
return yauzl.open(zipFilePath,
|
48
|
+
const startTime = Date.now();
|
49
|
+
let yauzlDoneTime = 0;
|
50
|
+
return fs.ensureDirAsync(installDir).then(() => {
|
51
|
+
return new Promise((resolve, reject) => {
|
52
|
+
return yauzl.open(zipFilePath, (err, zipFile) => {
|
51
53
|
yauzlDoneTime = Date.now();
|
52
54
|
|
53
55
|
if (err) {
|
@@ -55,29 +57,29 @@ var unzip = function unzip(_ref) {
|
|
55
57
|
return reject(err);
|
56
58
|
}
|
57
59
|
|
58
|
-
|
60
|
+
const total = zipFile.entryCount;
|
59
61
|
debug('zipFile entries count', total);
|
60
|
-
|
61
|
-
|
62
|
-
|
62
|
+
const started = new Date();
|
63
|
+
let percent = 0;
|
64
|
+
let count = 0;
|
63
65
|
|
64
|
-
|
65
|
-
|
66
|
-
|
66
|
+
const notify = percent => {
|
67
|
+
const elapsed = +new Date() - +started;
|
68
|
+
const eta = util.calculateEta(percent, elapsed);
|
67
69
|
progress.onProgress(percent, util.secsRemaining(eta));
|
68
70
|
};
|
69
71
|
|
70
|
-
|
72
|
+
const tick = () => {
|
71
73
|
count += 1;
|
72
74
|
percent = count / total * 100;
|
73
|
-
|
75
|
+
const displayPercent = percent.toFixed(0);
|
74
76
|
return notify(displayPercent);
|
75
77
|
};
|
76
78
|
|
77
|
-
|
79
|
+
const unzipWithNode = () => {
|
78
80
|
debug('unzipping with node.js (slow)');
|
79
81
|
|
80
|
-
|
82
|
+
const endFn = err => {
|
81
83
|
if (err) {
|
82
84
|
debug('error %s', err.message);
|
83
85
|
return reject(err);
|
@@ -87,7 +89,7 @@ var unzip = function unzip(_ref) {
|
|
87
89
|
return resolve();
|
88
90
|
};
|
89
91
|
|
90
|
-
|
92
|
+
const opts = {
|
91
93
|
dir: installDir,
|
92
94
|
onEntry: tick
|
93
95
|
};
|
@@ -95,17 +97,17 @@ var unzip = function unzip(_ref) {
|
|
95
97
|
return unzipTools.extract(zipFilePath, opts, endFn);
|
96
98
|
};
|
97
99
|
|
98
|
-
|
100
|
+
const unzipFallback = _.once(unzipWithNode);
|
99
101
|
|
100
|
-
|
102
|
+
const unzipWithUnzipTool = () => {
|
101
103
|
debug('unzipping via `unzip`');
|
102
|
-
|
103
|
-
|
104
|
-
sp.on('error',
|
104
|
+
const inflatingRe = /inflating:/;
|
105
|
+
const sp = cp.spawn('unzip', ['-o', zipFilePath, '-d', installDir]);
|
106
|
+
sp.on('error', err => {
|
105
107
|
debug('unzip tool error: %s', err.message);
|
106
108
|
unzipFallback();
|
107
109
|
});
|
108
|
-
sp.on('close',
|
110
|
+
sp.on('close', code => {
|
109
111
|
debug('unzip tool close with code %d', code);
|
110
112
|
|
111
113
|
if (code === 0) {
|
@@ -115,16 +117,16 @@ var unzip = function unzip(_ref) {
|
|
115
117
|
}
|
116
118
|
|
117
119
|
debug('`unzip` failed %o', {
|
118
|
-
code
|
120
|
+
code
|
119
121
|
});
|
120
122
|
return unzipFallback();
|
121
123
|
});
|
122
|
-
sp.stdout.on('data',
|
124
|
+
sp.stdout.on('data', data => {
|
123
125
|
if (inflatingRe.test(data)) {
|
124
126
|
return tick();
|
125
127
|
}
|
126
128
|
});
|
127
|
-
sp.stderr.on('data',
|
129
|
+
sp.stderr.on('data', data => {
|
128
130
|
debug('`unzip` stderr %s', data);
|
129
131
|
});
|
130
132
|
}; // we attempt to first unzip with the native osx
|
@@ -134,16 +136,16 @@ var unzip = function unzip(_ref) {
|
|
134
136
|
// http://automatica.com.au/2011/02/unzip-mac-os-x-zip-in-terminal/
|
135
137
|
|
136
138
|
|
137
|
-
|
139
|
+
const unzipWithOsx = () => {
|
138
140
|
debug('unzipping via `ditto`');
|
139
|
-
|
140
|
-
|
141
|
+
const copyingFileRe = /^copying file/;
|
142
|
+
const sp = cp.spawn('ditto', ['-xkV', zipFilePath, installDir]); // f-it just unzip with node
|
141
143
|
|
142
|
-
sp.on('error',
|
144
|
+
sp.on('error', err => {
|
143
145
|
debug(err.message);
|
144
146
|
unzipFallback();
|
145
147
|
});
|
146
|
-
sp.on('close',
|
148
|
+
sp.on('close', code => {
|
147
149
|
if (code === 0) {
|
148
150
|
// make sure we get to 100% on the progress bar
|
149
151
|
// because reading in lines is not really accurate
|
@@ -153,13 +155,13 @@ var unzip = function unzip(_ref) {
|
|
153
155
|
}
|
154
156
|
|
155
157
|
debug('`ditto` failed %o', {
|
156
|
-
code
|
158
|
+
code
|
157
159
|
});
|
158
160
|
return unzipFallback();
|
159
161
|
});
|
160
162
|
return readline.createInterface({
|
161
163
|
input: sp.stderr
|
162
|
-
}).on('line',
|
164
|
+
}).on('line', line => {
|
163
165
|
if (copyingFileRe.test(line)) {
|
164
166
|
return tick();
|
165
167
|
}
|
@@ -180,7 +182,7 @@ var unzip = function unzip(_ref) {
|
|
180
182
|
return;
|
181
183
|
}
|
182
184
|
});
|
183
|
-
}).tap(
|
185
|
+
}).tap(() => {
|
184
186
|
debug('unzip completed %o', {
|
185
187
|
yauzlMs: yauzlDoneTime - startTime,
|
186
188
|
unzipMs: Date.now() - yauzlDoneTime
|
@@ -189,38 +191,39 @@ var unzip = function unzip(_ref) {
|
|
189
191
|
});
|
190
192
|
};
|
191
193
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
194
|
+
const start = ({
|
195
|
+
zipFilePath,
|
196
|
+
installDir,
|
197
|
+
progress
|
198
|
+
}) => {
|
196
199
|
la(is.unemptyString(installDir), 'missing installDir');
|
197
200
|
|
198
201
|
if (!progress) {
|
199
202
|
progress = {
|
200
|
-
onProgress:
|
203
|
+
onProgress: () => {
|
201
204
|
return {};
|
202
205
|
}
|
203
206
|
};
|
204
207
|
}
|
205
208
|
|
206
|
-
return fs.pathExists(installDir).then(
|
209
|
+
return fs.pathExists(installDir).then(exists => {
|
207
210
|
if (exists) {
|
208
211
|
debug('removing existing unzipped binary', installDir);
|
209
212
|
return fs.removeAsync(installDir);
|
210
213
|
}
|
211
|
-
}).then(
|
214
|
+
}).then(() => {
|
212
215
|
return unzip({
|
213
|
-
zipFilePath
|
214
|
-
installDir
|
215
|
-
progress
|
216
|
+
zipFilePath,
|
217
|
+
installDir,
|
218
|
+
progress
|
216
219
|
});
|
217
|
-
})
|
220
|
+
}).catch(throwFormErrorText(errors.failedUnzip));
|
218
221
|
};
|
219
222
|
|
220
223
|
module.exports = {
|
221
|
-
start
|
224
|
+
start,
|
222
225
|
utils: {
|
223
|
-
unzip
|
224
|
-
unzipTools
|
226
|
+
unzip,
|
227
|
+
unzipTools
|
225
228
|
}
|
226
229
|
};
|