@testim/testim-cli 3.289.0 → 3.290.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/cli.js +22390 -122
- package/cli.js.map +1 -0
- package/npm-shrinkwrap.json +1951 -203
- package/package.json +9 -5
- package/OverrideTestDataBuilder.js +0 -117
- package/agent/routers/cliJsCode/index.js +0 -13
- package/agent/routers/cliJsCode/router.js +0 -63
- package/agent/routers/cliJsCode/service.js +0 -705
- package/agent/routers/codim/router.js +0 -69
- package/agent/routers/codim/router.test.js +0 -60
- package/agent/routers/codim/service.js +0 -193
- package/agent/routers/general/index.js +0 -36
- package/agent/routers/hybrid/registerRoutes.js +0 -81
- package/agent/routers/index.js +0 -56
- package/agent/routers/playground/router.js +0 -77
- package/agent/routers/playground/service.js +0 -96
- package/agent/routers/standalone-browser/registerRoutes.js +0 -47
- package/agent/server.js +0 -150
- package/cdpTestRunner.js +0 -86
- package/chromiumInstaller.js +0 -91
- package/cli/isCiRun.js +0 -10
- package/cli/onExit.js +0 -65
- package/cli/writeStackTrace.js +0 -27
- package/cliAgentMode.js +0 -384
- package/codim/codim-cli.js +0 -91
- package/codim/codim-npm-package/index.ts +0 -427
- package/codim/codim-npm-package/package-lock.json +0 -14
- package/codim/codim-npm-package/package.json +0 -14
- package/codim/hybrid-utils.js +0 -28
- package/codim/measure-perf.js +0 -41
- package/codim/template.js/.idea/workspace.xml +0 -57
- package/codim/template.js/.vscode/launch.json +0 -53
- package/codim/template.ts/.idea/workspace.xml +0 -57
- package/codim/template.ts/.vscode/launch.json +0 -55
- package/commons/AbortError.js +0 -12
- package/commons/SeleniumPerfStats.js +0 -58
- package/commons/chrome-launcher.js +0 -15
- package/commons/chromedriverWrapper.js +0 -70
- package/commons/config.js +0 -39
- package/commons/constants.js +0 -67
- package/commons/detectDebugger.js +0 -19
- package/commons/featureAvailabilityService.js +0 -26
- package/commons/featureFlags.js +0 -132
- package/commons/getSessionPlayerRequire.js +0 -28
- package/commons/httpRequest.js +0 -261
- package/commons/httpRequestCounters.js +0 -98
- package/commons/httpRequestCounters.test.js +0 -38
- package/commons/initializeUserWithAuth.js +0 -55
- package/commons/lazyRequire.js +0 -105
- package/commons/logUtils.js +0 -15
- package/commons/logUtils.test.js +0 -21
- package/commons/logger.js +0 -178
- package/commons/mockNetworkRuleFileSchema.json +0 -140
- package/commons/npmWrapper.js +0 -174
- package/commons/npmWrapper.test.js +0 -374
- package/commons/performance-logger.js +0 -71
- package/commons/preloadTests.js +0 -29
- package/commons/prepareRunner.js +0 -85
- package/commons/prepareRunner.test.js +0 -144
- package/commons/prepareRunnerAndTestimStartUtils.js +0 -198
- package/commons/prepareRunnerAndTestimStartUtils.test.js +0 -73
- package/commons/requireWithFallback.js +0 -25
- package/commons/runnerFileCache.js +0 -204
- package/commons/socket/baseSocketServiceSocketIO.js +0 -197
- package/commons/socket/realDataService.js +0 -59
- package/commons/socket/realDataServiceSocketIO.js +0 -33
- package/commons/socket/remoteStepService.js +0 -55
- package/commons/socket/remoteStepServiceSocketIO.js +0 -61
- package/commons/socket/socketService.js +0 -175
- package/commons/socket/testResultService.js +0 -62
- package/commons/socket/testResultServiceSocketIO.js +0 -64
- package/commons/testimAnalytics.js +0 -40
- package/commons/testimCloudflare.js +0 -83
- package/commons/testimCloudflare.test.js +0 -185
- package/commons/testimCustomToken.js +0 -124
- package/commons/testimDesiredCapabilitiesBuilder.js +0 -647
- package/commons/testimNgrok.js +0 -90
- package/commons/testimNgrok.test.js +0 -140
- package/commons/testimServicesApi.js +0 -631
- package/commons/testimTunnel.js +0 -73
- package/commons/testimTunnel.test.js +0 -172
- package/commons/xhr2.js +0 -897
- package/coverage/SummaryToObjectReport.js +0 -19
- package/coverage/jsCoverage.js +0 -252
- package/credentialsManager.js +0 -142
- package/errors.js +0 -161
- package/executionQueue.js +0 -37
- package/fixLocalBuild.js +0 -24
- package/inputFileUtils.js +0 -103
- package/lib/coralogix-winston.transport.js +0 -99
- package/player/SeleniumProtocolError.js +0 -100
- package/player/WebDriverHttpRequest.js +0 -177
- package/player/WebdriverioWebDriverApi.js +0 -671
- package/player/appiumTestPlayer.js +0 -90
- package/player/chromeLauncherTestPlayer.js +0 -67
- package/player/constants.js +0 -332
- package/player/extensionTestPlayer.js +0 -32
- package/player/findElementStrategy.js +0 -154
- package/player/scripts/isElementDisplayed.js +0 -252
- package/player/seleniumTestPlayer.js +0 -140
- package/player/services/frameLocator.js +0 -170
- package/player/services/mobileFrameLocatorMock.js +0 -32
- package/player/services/playbackTimeoutCalculator.js +0 -175
- package/player/services/portSelector.js +0 -19
- package/player/services/tabService.js +0 -551
- package/player/services/tabServiceMock.js +0 -167
- package/player/services/windowCreationListener.js +0 -8
- package/player/stepActions/RefreshStepAction.js +0 -16
- package/player/stepActions/apiStepAction.js +0 -89
- package/player/stepActions/baseCliJsStepAction.js +0 -51
- package/player/stepActions/baseJsStepAction.js +0 -277
- package/player/stepActions/cliConditionStepAction.js +0 -11
- package/player/stepActions/cliJsStepAction.js +0 -11
- package/player/stepActions/dropFileStepAction.js +0 -34
- package/player/stepActions/evaluateExpressionStepAction.js +0 -52
- package/player/stepActions/extensionOnlyStepAction.js +0 -12
- package/player/stepActions/extractTextStepAction.js +0 -19
- package/player/stepActions/hoverStepAction.js +0 -55
- package/player/stepActions/inputFileStepAction.js +0 -199
- package/player/stepActions/jsCodeStepAction.js +0 -11
- package/player/stepActions/jsConditionStepAction.js +0 -11
- package/player/stepActions/locateStepAction.js +0 -159
- package/player/stepActions/mouseStepAction.js +0 -370
- package/player/stepActions/navigationStepAction.js +0 -29
- package/player/stepActions/nodePackageStepAction.js +0 -47
- package/player/stepActions/pixelValidationStepAction.js +0 -39
- package/player/stepActions/scripts/dispatchEvents.js +0 -282
- package/player/stepActions/scripts/doClick.js +0 -221
- package/player/stepActions/scripts/doDragPath.js +0 -225
- package/player/stepActions/scripts/doubleClick.js +0 -119
- package/player/stepActions/scripts/dropEvent.js +0 -63
- package/player/stepActions/scripts/focusElement.js +0 -46
- package/player/stepActions/scripts/html5dragAction.js +0 -56
- package/player/stepActions/scripts/html5dragActionV2.js +0 -312
- package/player/stepActions/scripts/runCode.js +0 -147
- package/player/stepActions/scripts/scroll.js +0 -90
- package/player/stepActions/scripts/selectOption.js +0 -51
- package/player/stepActions/scripts/setText.js +0 -415
- package/player/stepActions/scripts/wheel.js +0 -61
- package/player/stepActions/scrollStepAction.js +0 -96
- package/player/stepActions/selectOptionStepAction.js +0 -49
- package/player/stepActions/sfdcRecordedStepAction.js +0 -24
- package/player/stepActions/sfdcStepAction.js +0 -28
- package/player/stepActions/sleepStepAction.js +0 -12
- package/player/stepActions/specialKeyStepAction.js +0 -52
- package/player/stepActions/stepAction.js +0 -73
- package/player/stepActions/stepActionRegistrar.js +0 -111
- package/player/stepActions/submitStepAction.js +0 -12
- package/player/stepActions/tdkHybridStepAction.js +0 -18
- package/player/stepActions/textStepAction.js +0 -110
- package/player/stepActions/textValidationStepAction.js +0 -64
- package/player/stepActions/wheelStepAction.js +0 -41
- package/player/utils/cookieUtils.js +0 -39
- package/player/utils/eyeSdkService.js +0 -250
- package/player/utils/imageCaptureUtils.js +0 -267
- package/player/utils/screenshotUtils.js +0 -68
- package/player/utils/stepActionUtils.js +0 -90
- package/player/utils/windowUtils.js +0 -195
- package/player/webDriverUtils.js +0 -40
- package/player/webDriverUtils.test.js +0 -116
- package/player/webdriver.js +0 -976
- package/polyfills/Array.prototype.at.js +0 -13
- package/polyfills/index.js +0 -13
- package/processHandler.js +0 -79
- package/processHandler.test.js +0 -55
- package/reports/chromeReporter.js +0 -17
- package/reports/consoleReporter.js +0 -190
- package/reports/debugReporter.js +0 -82
- package/reports/jsonReporter.js +0 -55
- package/reports/junitReporter.js +0 -183
- package/reports/reporter.js +0 -166
- package/reports/reporterUtils.js +0 -54
- package/reports/teamCityReporter.js +0 -73
- package/runOptions.d.ts +0 -305
- package/runOptions.js +0 -1288
- package/runOptionsAgentFlow.js +0 -87
- package/runOptionsUtils.js +0 -60
- package/runner.js +0 -355
- package/runners/ParallelWorkerManager.js +0 -284
- package/runners/TestPlanRunner.js +0 -419
- package/runners/buildCodeTests.js +0 -159
- package/runners/runnerUtils.js +0 -81
- package/services/analyticsService.js +0 -96
- package/services/branchService.js +0 -29
- package/services/gridService.js +0 -357
- package/services/gridService.test.js +0 -357
- package/services/labFeaturesService.js +0 -64
- package/services/lambdatestService.js +0 -227
- package/services/lambdatestService.test.js +0 -353
- package/services/localRCASaver.js +0 -124
- package/stepPlayers/cliJsStepPlayback.js +0 -40
- package/stepPlayers/hybridStepPlayback.js +0 -140
- package/stepPlayers/nodePackageStepPlayback.js +0 -28
- package/stepPlayers/playwrightHybridStepPlayback.js +0 -61
- package/stepPlayers/puppeteerHybridStepPlayback.js +0 -76
- package/stepPlayers/remoteStepPlayback.js +0 -80
- package/stepPlayers/seleniumHybridStepPlayback.js +0 -84
- package/stepPlayers/tdkHybridStepPlayback.js +0 -112
- package/testRunHandler.js +0 -603
- package/testRunStatus.js +0 -567
- package/testimNpmDriver.js +0 -52
- package/utils/argsUtils.js +0 -91
- package/utils/argsUtils.test.js +0 -32
- package/utils/fsUtils.js +0 -174
- package/utils/index.js +0 -197
- package/utils/promiseUtils.js +0 -85
- package/utils/stringUtils.js +0 -98
- package/utils/stringUtils.test.js +0 -22
- package/utils/timeUtils.js +0 -25
- package/utils/utils.test.js +0 -27
- package/workers/BaseWorker.js +0 -498
- package/workers/BaseWorker.test.js +0 -186
- package/workers/WorkerAppium.js +0 -180
- package/workers/WorkerExtension.js +0 -192
- package/workers/WorkerExtensionSingleBrowser.js +0 -77
- package/workers/WorkerSelenium.js +0 -253
- package/workers/workerUtils.js +0 -20
package/commons/httpRequest.js
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const logger = require('./logger').getLogger('http-request');
|
|
4
|
-
const superagent = require('superagent');
|
|
5
|
-
const { makeCounters } = require('./httpRequestCounters');
|
|
6
|
-
const { promiseFromCallback } = require('../utils/promiseUtils');
|
|
7
|
-
|
|
8
|
-
const wrapWithMonitoring = makeCounters();
|
|
9
|
-
|
|
10
|
-
const DEFAULT_REQUEST_TIMEOUT = process.env.DEFAULT_REQUEST_TIMEOUT || 30000; //30sec timeout
|
|
11
|
-
const DOWNLOAD_REQUEST_TIMEOUT = 60000; //1min timeout
|
|
12
|
-
|
|
13
|
-
function getCaFile() {
|
|
14
|
-
return global.caFileContent;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function binaryParser(res, fn) {
|
|
18
|
-
const data = [];
|
|
19
|
-
|
|
20
|
-
res.on('data', (chunk) => {
|
|
21
|
-
data.push(chunk); // Append Buffer object
|
|
22
|
-
});
|
|
23
|
-
res.on('end', () => {
|
|
24
|
-
fn(null, Buffer.concat(data)); // Merge the chunks and return
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function getProxy() {
|
|
29
|
-
if (!superagent.Request.prototype.proxy && global.SuperagentProxy) {
|
|
30
|
-
global.SuperagentProxy(superagent);
|
|
31
|
-
}
|
|
32
|
-
return global.proxyUri;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const logErrorAndRethrow = (logMsg, data) => err => {
|
|
36
|
-
logger.error(logMsg, { ...data, error: err });
|
|
37
|
-
throw err;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
function deleteMethod(url, body, headers, timeout) {
|
|
41
|
-
return deleteFullRes(url, body, headers, timeout)
|
|
42
|
-
.then(res => {
|
|
43
|
-
if (res.type === 'text/plain') {
|
|
44
|
-
return res.text;
|
|
45
|
-
}
|
|
46
|
-
return res.body;
|
|
47
|
-
})
|
|
48
|
-
.catch(logErrorAndRethrow('failed to delete request', { url }));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function deleteFullRes(url, body = {}, headers = {}, timeout = DEFAULT_REQUEST_TIMEOUT) {
|
|
52
|
-
const request = superagent
|
|
53
|
-
.delete(url)
|
|
54
|
-
.send(body)
|
|
55
|
-
.timeout(timeout)
|
|
56
|
-
.set(headers);
|
|
57
|
-
|
|
58
|
-
if (getCaFile()) {
|
|
59
|
-
request.ca(getCaFile());
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (getProxy()) {
|
|
63
|
-
request.proxy(getProxy());
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return promiseFromCallback((callback) => request.end(callback));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function post({
|
|
70
|
-
url, body, headers, timeout, retry,
|
|
71
|
-
}) {
|
|
72
|
-
return postFullRes(url, body, headers, timeout, retry)
|
|
73
|
-
.then(res => {
|
|
74
|
-
if (res.type === 'text/plain') {
|
|
75
|
-
return res.text;
|
|
76
|
-
}
|
|
77
|
-
return res.body;
|
|
78
|
-
})
|
|
79
|
-
.catch(logErrorAndRethrow('failed to post request', { url }));
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function postFullRes(url, body, headers = {}, timeout = DEFAULT_REQUEST_TIMEOUT, retry = 0) {
|
|
83
|
-
const request = superagent
|
|
84
|
-
.post(url)
|
|
85
|
-
.send(body)
|
|
86
|
-
.timeout(timeout)
|
|
87
|
-
.set(headers);
|
|
88
|
-
|
|
89
|
-
if (getCaFile()) {
|
|
90
|
-
request.ca(getCaFile());
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (getProxy()) {
|
|
94
|
-
request.proxy(getProxy());
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (retry) {
|
|
98
|
-
request.retry(retry);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return promiseFromCallback((callback) => request.end(callback)).catch(e => {
|
|
102
|
-
e.url = url;
|
|
103
|
-
e.originalRequestTimeout = timeout;
|
|
104
|
-
e.additionalSetHeaders = headers;
|
|
105
|
-
throw e;
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function postForm(url, fields, files, headers = {}, timeout = DEFAULT_REQUEST_TIMEOUT) {
|
|
110
|
-
const request = superagent
|
|
111
|
-
.post(url)
|
|
112
|
-
.type('form')
|
|
113
|
-
.timeout(timeout)
|
|
114
|
-
.set(headers);
|
|
115
|
-
|
|
116
|
-
request.field(fields);
|
|
117
|
-
|
|
118
|
-
Object.keys(files).forEach(file => {
|
|
119
|
-
request.attach(file, files[file].buffer, files[file].fileName);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
if (getCaFile()) {
|
|
123
|
-
request.ca(getCaFile());
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (getProxy()) {
|
|
127
|
-
request.proxy(getProxy());
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return promiseFromCallback((callback) => request.end(callback))
|
|
131
|
-
.then((res) => {
|
|
132
|
-
if (res.type === 'text/plain') {
|
|
133
|
-
return res.text;
|
|
134
|
-
}
|
|
135
|
-
return res.body;
|
|
136
|
-
})
|
|
137
|
-
.catch(logErrorAndRethrow('failed to post request', { url }));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function _get(url, query, headers = {}, timeout = DEFAULT_REQUEST_TIMEOUT, { isBinary = false, skipProxy = false } = {}) {
|
|
141
|
-
const request = superagent
|
|
142
|
-
.get(url)
|
|
143
|
-
.query(query)
|
|
144
|
-
.timeout(timeout)
|
|
145
|
-
.set(headers);
|
|
146
|
-
|
|
147
|
-
if (isBinary) {
|
|
148
|
-
request.buffer(true);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (getCaFile()) {
|
|
152
|
-
request.ca(getCaFile());
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (!skipProxy && getProxy()) {
|
|
156
|
-
request.proxy(getProxy());
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return promiseFromCallback((callback) => request.end(callback));
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function getText(url, query, headers) {
|
|
163
|
-
return _get(url, query, headers)
|
|
164
|
-
.then((res) => res.text)
|
|
165
|
-
.catch(logErrorAndRethrow('failed to getText request', { url, query }));
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function get(url, query, headers, timeout, options) {
|
|
169
|
-
return _get(url, query, headers, timeout, options)
|
|
170
|
-
.then((res) => res.body)
|
|
171
|
-
.catch(err => {
|
|
172
|
-
logger.warn('failed to get request', { url, query, error: err });
|
|
173
|
-
throw err;
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function getFullRes(url, query, headers, timeout) {
|
|
178
|
-
return _get(url, query, headers, timeout);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function head(url) {
|
|
182
|
-
const request = superagent
|
|
183
|
-
.head(url)
|
|
184
|
-
.timeout(DEFAULT_REQUEST_TIMEOUT);
|
|
185
|
-
|
|
186
|
-
if (getCaFile()) {
|
|
187
|
-
request.ca(getCaFile());
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
if (getProxy()) {
|
|
191
|
-
request.proxy(getProxy());
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return promiseFromCallback((callback) => request.end(callback))
|
|
195
|
-
.catch(logErrorAndRethrow('failed to head request', { url }));
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function put(url, body, headers = {}, timeout = DEFAULT_REQUEST_TIMEOUT) {
|
|
199
|
-
const request = superagent
|
|
200
|
-
.put(url)
|
|
201
|
-
.send(body)
|
|
202
|
-
.timeout(timeout)
|
|
203
|
-
.set(headers);
|
|
204
|
-
|
|
205
|
-
if (getCaFile()) {
|
|
206
|
-
request.ca(getCaFile());
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (getProxy()) {
|
|
210
|
-
request.proxy(getProxy());
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return promiseFromCallback((callback) => request.end(callback))
|
|
214
|
-
.then((res) => res.body)
|
|
215
|
-
.catch(logErrorAndRethrow('failed to put request', { url }));
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* @param {string} url
|
|
220
|
-
* @returns {Promise<Omit<superagent.Response, 'body'> & { body: Buffer }>}
|
|
221
|
-
*/
|
|
222
|
-
function download(url) {
|
|
223
|
-
logger.info('start to download', { url });
|
|
224
|
-
|
|
225
|
-
const request = superagent
|
|
226
|
-
.get(url)
|
|
227
|
-
.timeout(DOWNLOAD_REQUEST_TIMEOUT)
|
|
228
|
-
.buffer(true)
|
|
229
|
-
.parse(binaryParser);
|
|
230
|
-
|
|
231
|
-
if (getCaFile()) {
|
|
232
|
-
request.ca(getCaFile());
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (getProxy()) {
|
|
236
|
-
request.proxy(getProxy());
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return promiseFromCallback((callback) => request.end(callback))
|
|
240
|
-
.then(response => {
|
|
241
|
-
logger.info('finished to download', { url });
|
|
242
|
-
return response;
|
|
243
|
-
})
|
|
244
|
-
.catch(logErrorAndRethrow('failed to download', { url }));
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
module.exports = {
|
|
248
|
-
delete: wrapWithMonitoring(deleteMethod),
|
|
249
|
-
deleteFullRes: wrapWithMonitoring(deleteFullRes),
|
|
250
|
-
put: wrapWithMonitoring(put),
|
|
251
|
-
get: wrapWithMonitoring(get),
|
|
252
|
-
getText: wrapWithMonitoring(getText),
|
|
253
|
-
post: wrapWithMonitoring(post),
|
|
254
|
-
postFullRes: wrapWithMonitoring(postFullRes),
|
|
255
|
-
getFullRes: wrapWithMonitoring(getFullRes),
|
|
256
|
-
postForm: wrapWithMonitoring(postForm),
|
|
257
|
-
head: wrapWithMonitoring(head),
|
|
258
|
-
download: wrapWithMonitoring(download),
|
|
259
|
-
isNetworkHealthy: wrapWithMonitoring.isNetworkHealthy,
|
|
260
|
-
didNetworkConnectivityTestFail: wrapWithMonitoring.didNetworkConnectivityTestFail,
|
|
261
|
-
};
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
const _ = require('lodash');
|
|
6
|
-
const config = require('./config');
|
|
7
|
-
const dns = require('dns').promises;
|
|
8
|
-
const { sum } = require('lodash');
|
|
9
|
-
const { promiseMap } = require('../utils/promiseUtils');
|
|
10
|
-
|
|
11
|
-
const logger = require('./logger').getLogger('http-request-counters');
|
|
12
|
-
|
|
13
|
-
let networkConnectivityTestFailed = false;
|
|
14
|
-
|
|
15
|
-
/** Tests network connectivity with DNS resolution (a basic test for a 7 later stack parallel but essential to most HTTP requests) */
|
|
16
|
-
const testNetworkConnectivity = async () => {
|
|
17
|
-
if (config.IS_ON_PREM) {
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
|
-
const hostnames = ['www.google.com', 'www.facebook.com', 'www.microsoft.com', 'testim.io'];
|
|
21
|
-
try {
|
|
22
|
-
// If any of these domains resolve we consider the connectivity to be ok
|
|
23
|
-
const result = Boolean(await promiseMap(hostnames, host => dns.lookup(host)));
|
|
24
|
-
if (!result) {
|
|
25
|
-
networkConnectivityTestFailed = true;
|
|
26
|
-
}
|
|
27
|
-
return result;
|
|
28
|
-
} catch (e) {
|
|
29
|
-
logger.error('network connectivity test failed');
|
|
30
|
-
networkConnectivityTestFailed = true;
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
const throttledTestNetworkConnectivity = _.throttle(testNetworkConnectivity, 10 * 1000);
|
|
35
|
-
|
|
36
|
-
// we remove entries after 15 minutes, note that this isn't accurate because
|
|
37
|
-
// we remove the "fail"/"success" 10 minutes after we add them (and not the "call")
|
|
38
|
-
// this is fine since these values are an estimation and not an accurate representation
|
|
39
|
-
// we poll them when a test fails - so values older than 15 minutes (10 minutes is
|
|
40
|
-
// the default timeout) are hardly relevant.
|
|
41
|
-
const ttl = 60 * 1000 * 15;
|
|
42
|
-
|
|
43
|
-
module.exports.makeCounters = () => {
|
|
44
|
-
const counters = {
|
|
45
|
-
/** @type {Map<string, number>} */ call: new Map(),
|
|
46
|
-
/** @type {Map<string, number>} */ success: new Map(),
|
|
47
|
-
/** @type {Map<string, number>} */ fail: new Map(),
|
|
48
|
-
};
|
|
49
|
-
/**
|
|
50
|
-
* @param {counters[keyof counters]} counter
|
|
51
|
-
* @param {string} key
|
|
52
|
-
*/
|
|
53
|
-
function update(counter, key) {
|
|
54
|
-
const result = counter.get(key) || 0;
|
|
55
|
-
counter.set(key, result + 1);
|
|
56
|
-
setTimeout(() => {
|
|
57
|
-
const _result = counter.get(key) || 1;
|
|
58
|
-
counter.set(key, _result - 1);
|
|
59
|
-
}, ttl);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* @template T, TArgs
|
|
63
|
-
* @param {(...args: TArgs[]) => T} fn
|
|
64
|
-
* @param {string=} name
|
|
65
|
-
* @return {(...args: TArgs[]) => Promise<T>}
|
|
66
|
-
*/
|
|
67
|
-
function wrapWithMonitoring(fn, name = fn.name) {
|
|
68
|
-
return async function (...args) {
|
|
69
|
-
update(counters.call, name);
|
|
70
|
-
try {
|
|
71
|
-
const result = await fn.call(null, ...args);
|
|
72
|
-
update(counters.success, name);
|
|
73
|
-
return result;
|
|
74
|
-
} catch (e) {
|
|
75
|
-
update(counters.fail, name);
|
|
76
|
-
if (!networkConnectivityTestFailed) {
|
|
77
|
-
throttledTestNetworkConnectivity();
|
|
78
|
-
}
|
|
79
|
-
throw e;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
wrapWithMonitoring.isNetworkHealthy = async function isNetworkHealthy() {
|
|
84
|
-
if (networkConnectivityTestFailed || !(await testNetworkConnectivity())) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
const allFailed = sum([...counters.fail.values()]);
|
|
88
|
-
const allCalls = sum([...counters.call.values()]);
|
|
89
|
-
// we declare a test unhealthy network wise if
|
|
90
|
-
// 10% or more of requests (out of finished requests) failed
|
|
91
|
-
// note that the network can be unhealthy but the test would still pass
|
|
92
|
-
return allFailed < allCalls * 0.1;
|
|
93
|
-
};
|
|
94
|
-
wrapWithMonitoring.counters = counters; // expose the counters used to the outside
|
|
95
|
-
wrapWithMonitoring.isNetworkHealthy.counters = wrapWithMonitoring.counters;
|
|
96
|
-
wrapWithMonitoring.didNetworkConnectivityTestFail = () => networkConnectivityTestFailed;
|
|
97
|
-
return wrapWithMonitoring;
|
|
98
|
-
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
const pRetry = require('p-retry');
|
|
2
|
-
const { makeCounters } = require('./httpRequestCounters');
|
|
3
|
-
const { rejects, doesNotReject, strictEqual } = require('assert');
|
|
4
|
-
|
|
5
|
-
describe('the http request counters', () => {
|
|
6
|
-
let wrapWithMonitoring;
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
wrapWithMonitoring = makeCounters();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('marks an always failing network as unhealthy', async () => {
|
|
12
|
-
const fn = pRetry(wrapWithMonitoring(() => { throw new Error('bad network'); }), { retries: 30, minTimeout: 0, maxTimeout: 0 });
|
|
13
|
-
await rejects(fn);
|
|
14
|
-
strictEqual(await wrapWithMonitoring.isNetworkHealthy(), false);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('marks an unstable network as unhealthy', async () => {
|
|
18
|
-
const fn = pRetry(wrapWithMonitoring(() => { throw new Error('bad network'); }), { retries: 30, minTimeout: 0, maxTimeout: 0 });
|
|
19
|
-
const fn2 = pRetry(wrapWithMonitoring(() => 'hello'), { retries: 20, minTimeout: 0, maxTimeout: 0 });
|
|
20
|
-
await rejects(fn);
|
|
21
|
-
await doesNotReject(fn2);
|
|
22
|
-
strictEqual(await wrapWithMonitoring.isNetworkHealthy(), false);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('marks a trivial amount of failed requests as healthy', async () => {
|
|
26
|
-
const fn = pRetry(wrapWithMonitoring(() => { throw new Error('bad network'); }), { retries: 30, minTimeout: 0, maxTimeout: 0 });
|
|
27
|
-
await rejects(fn);
|
|
28
|
-
const fn2 = wrapWithMonitoring(() => 'hello');
|
|
29
|
-
await Promise.all(Array(290).fill().map(fn2));
|
|
30
|
-
strictEqual(await wrapWithMonitoring.isNetworkHealthy(), true);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('marks a healthy network as healthy', async () => {
|
|
34
|
-
const fn2 = wrapWithMonitoring(() => 'hello');
|
|
35
|
-
await Promise.all(Array(200).fill().map(fn2));
|
|
36
|
-
strictEqual(await wrapWithMonitoring.isNetworkHealthy(), true);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
const perf = require('./performance-logger');
|
|
2
|
-
const servicesApi = require('./testimServicesApi');
|
|
3
|
-
const localRunnerCache = require('./runnerFileCache');
|
|
4
|
-
const testimCustomToken = require('./testimCustomToken');
|
|
5
|
-
const { CLI_MODE } = require('./constants');
|
|
6
|
-
|
|
7
|
-
const FIVE_MINUTES_MS = 1000 * 60 * 5;
|
|
8
|
-
const TEN_HOURS_MS = 1000 * 60 * 60 * 10;
|
|
9
|
-
|
|
10
|
-
/** @param {import('../runOptions').RunnerOptions['mode']} mode */
|
|
11
|
-
function preloadSlowRequires(mode) {
|
|
12
|
-
process.nextTick(() => {
|
|
13
|
-
if (![CLI_MODE.SELENIUM, CLI_MODE.APPIUM].includes(mode)) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
// heuristic to pay the cost of loading the sessionPlayer here while we are waiting for the backend
|
|
17
|
-
try {
|
|
18
|
-
require('./getSessionPlayerRequire').getSessionPlayer();
|
|
19
|
-
// jsdom for the same reason, we don't require workerSelenium here since it actually takes longer to load
|
|
20
|
-
// then it takes for the backend to return 🤯
|
|
21
|
-
require('jsdom');
|
|
22
|
-
} catch (e) {
|
|
23
|
-
//silent catch
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** @param {import('../runOptions').RunnerOptions} options */
|
|
29
|
-
async function initializeUserWithAuth(options) {
|
|
30
|
-
const { project, token, lightweightMode, useLocalChromeDriver, useChromeLauncher, mode } = options;
|
|
31
|
-
|
|
32
|
-
const lightweightModeGeneral = Boolean(lightweightMode?.general);
|
|
33
|
-
const localGrid = Boolean(useLocalChromeDriver || useChromeLauncher);
|
|
34
|
-
const memoizationTTL = lightweightModeGeneral ? TEN_HOURS_MS : FIVE_MINUTES_MS;
|
|
35
|
-
|
|
36
|
-
perf.log('before initializeUserWithAuth');
|
|
37
|
-
const result = await localRunnerCache.memoize(async () => {
|
|
38
|
-
preloadSlowRequires(mode);
|
|
39
|
-
return await servicesApi.initializeUserWithAuth({
|
|
40
|
-
projectId: project,
|
|
41
|
-
token,
|
|
42
|
-
branchName: options.branch,
|
|
43
|
-
lightweightMode,
|
|
44
|
-
localGrid,
|
|
45
|
-
});
|
|
46
|
-
}, 'initializeUserWithAuth', memoizationTTL, { project, token, branchName: options.branch, lightweightModeGeneral, localGrid })();
|
|
47
|
-
perf.log('after initializeUserWithAuth');
|
|
48
|
-
|
|
49
|
-
testimCustomToken.initFromData(result.authData, options.project, options.token);
|
|
50
|
-
return result;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
module.exports = {
|
|
54
|
-
initializeUserWithAuth,
|
|
55
|
-
};
|
package/commons/lazyRequire.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const ora = require('ora');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const npmWrapper = require('./npmWrapper');
|
|
6
|
-
const { getLogger } = require('./logger');
|
|
7
|
-
const { getCliLocation } = require('../utils');
|
|
8
|
-
const { requireWithFallback } = require('./requireWithFallback');
|
|
9
|
-
|
|
10
|
-
const logger = getLogger('lazy-require');
|
|
11
|
-
// eslint-disable-next-line import/no-dynamic-require
|
|
12
|
-
const packageJson = require(path.resolve(getCliLocation(), 'package.json'));
|
|
13
|
-
const ongoingCalls = new Map();
|
|
14
|
-
|
|
15
|
-
module.exports = async function memoizedLazyRequireApi(dependency, options = {}) {
|
|
16
|
-
const packageLocally = npmWrapper.getPackageIfInstalledLocally(dependency);
|
|
17
|
-
if (packageLocally) {
|
|
18
|
-
return packageLocally;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
let spinner;
|
|
22
|
-
if (!options.silent) {
|
|
23
|
-
spinner = ora(`Installing ${dependency} before first usage...`).start();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
const requiredModule = await memoizedLazyRequire(dependency);
|
|
28
|
-
if (spinner) {
|
|
29
|
-
spinner.succeed();
|
|
30
|
-
}
|
|
31
|
-
return requiredModule;
|
|
32
|
-
} catch (error) {
|
|
33
|
-
logger.warn('failed to install dependency lazily', { dependency, err: error });
|
|
34
|
-
const depVersionToInstall = getVersionOfLazyDep(dependency);
|
|
35
|
-
const depWithVersions = `${dependency}@${depVersionToInstall}`;
|
|
36
|
-
|
|
37
|
-
const removeGlobal = process.argv.includes('npx');
|
|
38
|
-
const globalFlag = removeGlobal ? '' : '-g ';
|
|
39
|
-
const errorMessage = `Installation of ${dependency} failed. This typically means you are running an out-of-date version of Node.js or NPM.` +
|
|
40
|
-
`Please manually install by running the following command: npm install ${globalFlag}${depWithVersions}`;
|
|
41
|
-
|
|
42
|
-
if (spinner) {
|
|
43
|
-
spinner.fail(errorMessage);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
async function memoizedLazyRequire(identifier, options = {}) {
|
|
51
|
-
if (ongoingCalls.has(identifier)) {
|
|
52
|
-
return ongoingCalls.get(identifier);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
ongoingCalls.set(identifier, lazyRequireImpl(identifier, options));
|
|
56
|
-
ongoingCalls.get(identifier).catch(() => {
|
|
57
|
-
ongoingCalls.delete(identifier);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
return ongoingCalls.get(identifier);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async function lazyRequireImpl(dependency) {
|
|
64
|
-
const packageLocally = npmWrapper.getPackageIfInstalledLocally(dependency);
|
|
65
|
-
|
|
66
|
-
if (packageLocally) {
|
|
67
|
-
return packageLocally;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const depVersionToInstall = getVersionOfLazyDep(dependency);
|
|
71
|
-
|
|
72
|
-
const depWithVersions = `${dependency}@${depVersionToInstall}`;
|
|
73
|
-
|
|
74
|
-
await npmWrapper.installPackageLocally(getCliLocation(), depWithVersions);
|
|
75
|
-
|
|
76
|
-
return requireWithFallback(dependency);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
module.exports.installAllLazyDependencies = async function installAllLazyDependencies() {
|
|
80
|
-
const allLazyDependencies = Object.keys(packageJson.lazyDependencies);
|
|
81
|
-
|
|
82
|
-
for (const dep of allLazyDependencies) {
|
|
83
|
-
await lazyRequireImpl(dep);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// TODO: remove this once docker-build-tool is not using it
|
|
88
|
-
if (require.main === module) {
|
|
89
|
-
module.exports.installAllLazyDependencies();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
*
|
|
94
|
-
* @param {string} dependencyToFind
|
|
95
|
-
*/
|
|
96
|
-
function getVersionOfLazyDep(dependencyToFind) {
|
|
97
|
-
const depEntry = Object.entries(packageJson.lazyDependencies)
|
|
98
|
-
.find(([dep]) => dep === dependencyToFind);
|
|
99
|
-
|
|
100
|
-
if (!depEntry) {
|
|
101
|
-
throw new Error('The given package name is not lazyDependencies');
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return depEntry[1];
|
|
105
|
-
}
|
package/commons/logUtils.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const os = require('os');
|
|
2
|
-
const { getCliLocation } = require('../utils');
|
|
3
|
-
|
|
4
|
-
function additionalLogDetails() {
|
|
5
|
-
return {
|
|
6
|
-
cliLocation: getCliLocation(),
|
|
7
|
-
userInfo: os.userInfo(),
|
|
8
|
-
platform: os.platform(),
|
|
9
|
-
release: os.release(),
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module.exports = {
|
|
14
|
-
additionalLogDetails,
|
|
15
|
-
};
|
package/commons/logUtils.test.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
const { expect } = require('chai');
|
|
2
|
-
const os = require('os');
|
|
3
|
-
const { additionalLogDetails } = require('./logUtils');
|
|
4
|
-
const { getCliLocation } = require('../utils');
|
|
5
|
-
|
|
6
|
-
describe('logUtils', () => {
|
|
7
|
-
describe('additionalLogDetails', () => {
|
|
8
|
-
it('should return the expected unformation', () => {
|
|
9
|
-
const expected = {
|
|
10
|
-
cliLocation: getCliLocation(),
|
|
11
|
-
userInfo: os.userInfo(),
|
|
12
|
-
platform: os.platform(),
|
|
13
|
-
release: os.release(),
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const result = additionalLogDetails();
|
|
17
|
-
|
|
18
|
-
expect(result).to.eql(expected);
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
});
|