@testim/testim-cli 3.244.0 → 3.247.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/chromiumInstaller.js +92 -0
- package/cli.js +89 -87
- package/cliAgentMode.js +39 -114
- package/commons/chromedriverWrapper.js +4 -3
- package/commons/featureFlags.js +1 -0
- package/commons/getSessionPlayerRequire.js +2 -1
- package/commons/httpRequestCounters.test.js +9 -9
- package/commons/npmWrapper.js +3 -3
- package/commons/npmWrapper.test.js +1 -1
- package/commons/prepareRunner.js +2 -0
- package/commons/socket/baseSocketServiceSocketIO.js +2 -2
- package/commons/testimDesiredCapabilitiesBuilder.js +1 -3
- package/commons/testimServicesApi.js +45 -39
- package/errors.js +2 -1
- package/npm-shrinkwrap.json +467 -366
- package/package.json +2 -2
- package/player/WebDriverHttpRequest.js +45 -37
- package/player/chromeLauncherTestPlayer.js +2 -2
- package/player/services/playbackTimeoutCalculator.js +5 -1
- package/player/stepActions/RefreshStepAction.js +2 -4
- package/player/stepActions/inputFileStepAction.js +6 -2
- package/player/stepActions/sfdcStepAction.js +27 -0
- package/player/stepActions/stepActionRegistrar.js +12 -0
- package/player/utils/screenshotUtils.js +2 -2
- package/player/utils/windowUtils.js +3 -3
- package/player/webdriver.js +51 -52
- package/runOptions.js +3 -1
- package/runner.js +44 -41
- package/services/lambdatestService.js +2 -2
- package/services/lambdatestService.test.js +2 -1
- package/testRunHandler.js +7 -3
- package/testRunStatus.js +2 -1
- package/utils.js +54 -15
- package/utils.test.js +26 -0
- package/workers/BaseWorker.js +9 -7
- package/workers/BaseWorker.test.js +11 -12
package/commons/npmWrapper.js
CHANGED
|
@@ -78,7 +78,7 @@ async function installPackageLocally(rootPath, packageName, execOptions) {
|
|
|
78
78
|
} catch (err) {
|
|
79
79
|
// ignore error
|
|
80
80
|
}
|
|
81
|
-
return await exec(`npm i ${packageName} --no-save --no-
|
|
81
|
+
return await exec(`npm i ${packageName} --no-save --no-prune --prefer-offline --no-audit --progress=false`, { ...execOptions, cwd: rootPath }).catch(err => {
|
|
82
82
|
const pathWithMissingPermissions = getPathWithMissingPermissions(err);
|
|
83
83
|
const npmEightMissingPermissions = npmSevenAndEightMissingPermissions(err);
|
|
84
84
|
if (pathWithMissingPermissions || npmEightMissingPermissions) {
|
|
@@ -110,7 +110,7 @@ Testim had missing write access to ${pathWithMissingPermissions || rootPath}
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
const localNpmLocation = path.resolve(require.resolve('npm').replace('index.js',''), 'bin','npm-cli.js');
|
|
113
|
+
const localNpmLocation = path.resolve(require.resolve('npm').replace('index.js', ''), 'bin', 'npm-cli.js');
|
|
114
114
|
|
|
115
115
|
function installPackages(prefix, packageNames, proxyUri, timeoutMs) {
|
|
116
116
|
return new Promise((resolve, reject) => {
|
|
@@ -121,7 +121,7 @@ function installPackages(prefix, packageNames, proxyUri, timeoutMs) {
|
|
|
121
121
|
let stdout = '';
|
|
122
122
|
let stderr = '';
|
|
123
123
|
|
|
124
|
-
const ops = '--no-save --no-package-lock --no-prune --prefer-offline --no-audit --
|
|
124
|
+
const ops = '--no-save --no-package-lock --no-prune --prefer-offline --no-audit --progress=false'.split(' ');
|
|
125
125
|
const npmInstall = spawn('node', [localNpmLocation, 'i', '--prefix', prefix, ...ops, ...packageNames, ...proxyFlag], envVars);
|
|
126
126
|
npmInstall.stderr.pipe(process.stderr);
|
|
127
127
|
npmInstall.stdout.pipe(process.stdout);
|
|
@@ -54,7 +54,7 @@ describe('npmWrapper', () => {
|
|
|
54
54
|
fakeChildProcess.exec.yields(undefined, []); //resolve without errors
|
|
55
55
|
const cwd = '/some/dir';
|
|
56
56
|
const pkg = 'some-package';
|
|
57
|
-
const expectedCmd = 'npm i some-package --no-save --no-
|
|
57
|
+
const expectedCmd = 'npm i some-package --no-save --no-prune --prefer-offline --no-audit --progress=false';
|
|
58
58
|
const expectedExecParams = { cwd };
|
|
59
59
|
|
|
60
60
|
await npmWrapper.installPackageLocally(cwd, pkg);
|
package/commons/prepareRunner.js
CHANGED
|
@@ -10,6 +10,7 @@ const Ajv = require('ajv');
|
|
|
10
10
|
const prepareRunnerAndTestimStartUtils = require('./prepareRunnerAndTestimStartUtils');
|
|
11
11
|
const mockNetworkRuleFileSchema = require('./mockNetworkRuleFileSchema.json');
|
|
12
12
|
const { initializeUserWithAuth } = require('./initializeUserWithAuth');
|
|
13
|
+
const { downloadAndInstallChromium } = require('../chromiumInstaller');
|
|
13
14
|
|
|
14
15
|
const MAX_RULE_FILE_SIZE_IN_MB = 1;
|
|
15
16
|
const PREPARE_MOCK_NETWORK_ERROR_PREFIX = 'JSON file supplied to --mock-network-pattern';
|
|
@@ -30,6 +31,7 @@ async function prepare(options) {
|
|
|
30
31
|
const hasNoGrid = !options.host && !options.gridId && !options.grid && (!options.testPlan || options.testPlan.length === 0);
|
|
31
32
|
const isTdkRun = options.files.length !== 0;
|
|
32
33
|
if ((hasNoGrid && isTdkRun) || options.useLocalChromeDriver) {
|
|
34
|
+
options.chromeBinaryLocation = options.downloadBrowser ? await downloadAndInstallChromium() : options.chromeBinaryLocation;
|
|
33
35
|
chromedriverPromise = prepareRunnerAndTestimStartUtils.prepareChromeDriver(
|
|
34
36
|
{ projectId: options.project, userId: options.user },
|
|
35
37
|
{ chromeBinaryLocation: options.chromeBinaryLocation },
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const Promise = require('bluebird');
|
|
4
|
+
const pRetry = require('p-retry');
|
|
4
5
|
const io = require('socket.io-client');
|
|
5
6
|
const config = require('../config');
|
|
6
|
-
const utils = require('../../utils');
|
|
7
7
|
|
|
8
8
|
const MAX_SOCKET_RECONNECT_ATTEMPT = 50;
|
|
9
9
|
const MAX_RECONNECT_ATTEMPT_BEFORE_SWITCH = 10;
|
|
@@ -163,7 +163,7 @@ class BaseSocketServiceSocketIO {
|
|
|
163
163
|
};
|
|
164
164
|
|
|
165
165
|
this.emitPromisQueue = (this.emitPromisQueue || Promise.resolve())
|
|
166
|
-
.then(() =>
|
|
166
|
+
.then(() => pRetry(emitAndWait, { retries: 200, minTimeout: 3000 }))
|
|
167
167
|
.finally(() => {
|
|
168
168
|
if (Object.keys(errorneousEvents).length > 0) {
|
|
169
169
|
logger.error('Bad acknowledge from socket emit', { errorneousEvents });
|
|
@@ -536,13 +536,11 @@ function buildSeleniumOptions(browserOptions, testName, testRunConfig, gridInfo,
|
|
|
536
536
|
);
|
|
537
537
|
|
|
538
538
|
let predefinedTestimExtension = null;
|
|
539
|
-
if (!browserOptions.ext && _.endsWith(gridInfo.host, '.testim.io') && !browserOptions.canary && browserOptions.mode === CLI_MODE.EXTENSION) {
|
|
539
|
+
if (!browserOptions.ext && !browserOptions.extensionPath && _.endsWith(gridInfo.host, '.testim.io') && !browserOptions.canary && browserOptions.mode === CLI_MODE.EXTENSION) {
|
|
540
540
|
if (browser === 'chrome') {
|
|
541
541
|
predefinedTestimExtension = '/opt/testim-headless';
|
|
542
542
|
} else if (browser === 'edge-chromium') {
|
|
543
543
|
predefinedTestimExtension = 'C:/selenium/testim-headless';
|
|
544
|
-
} else if (browser === 'firefox') {
|
|
545
|
-
predefinedTestimExtension = '/opt/testim-firefox-profile';
|
|
546
544
|
}
|
|
547
545
|
}
|
|
548
546
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const pako = require('pako');
|
|
4
|
+
const pRetry = require('p-retry');
|
|
4
5
|
const _ = require('lodash');
|
|
5
6
|
const testimCustomToken = require('./testimCustomToken');
|
|
6
7
|
const constants = require('./constants');
|
|
@@ -66,13 +67,13 @@ function getWithAuth(url, query, options, timeout) {
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
function getS3Artifact(url, timeout) {
|
|
69
|
-
return
|
|
70
|
+
return pRetry(() => getWithAuth(`/storage${url}`, null, { isBinary: true }, timeout), { retries: DEFAULT_REQUEST_RETRY });
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
function getTestPlan(projectId, testPlanNames) {
|
|
73
74
|
//TODO: need to be checked after 3 months to prevent users from using old version
|
|
74
75
|
const parseProperty = (dataValue) => (dataValue == null ? [] : (typeof (dataValue) === 'string' && JSON.parse(dataValue)) || dataValue);
|
|
75
|
-
return
|
|
76
|
+
return pRetry((() => getWithAuth('/testPlan', { projectId, name: testPlanNames.join(',') }), { retries: DEFAULT_REQUEST_RETRY }))
|
|
76
77
|
.then(body => body.map(testPlan => {
|
|
77
78
|
testPlan.testConfigIds = parseProperty(testPlan.testConfigIds);
|
|
78
79
|
testPlan.beforeAllLabels = parseProperty(testPlan.beforeAllLabels);
|
|
@@ -84,20 +85,20 @@ function getTestPlan(projectId, testPlanNames) {
|
|
|
84
85
|
|
|
85
86
|
|
|
86
87
|
function loadTest({ testId, branch, projectId, skipSharedSteps = false, useBranchMap = true }) {
|
|
87
|
-
return
|
|
88
|
+
return pRetry(() => getWithAuth(`/test/${testId}`, {
|
|
88
89
|
projectId,
|
|
89
90
|
branch,
|
|
90
91
|
skipSharedSteps,
|
|
91
92
|
useBranchMap,
|
|
92
|
-
}));
|
|
93
|
+
}), { retries: DEFAULT_REQUEST_RETRY });
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
function saveTestPlanResult(projectId, testPlanId, result) {
|
|
96
|
-
return
|
|
97
|
+
return pRetry(() => postAuth({ url: '/testPlan/result', body: { projectId, testPlanId, result } }), { retries: DEFAULT_REQUEST_RETRY });
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
function updateTestStatus(projectId, executionId, testId, resultId, status, data,
|
|
100
|
-
return
|
|
100
|
+
function updateTestStatus(projectId, executionId, testId, resultId, status, data, retries = DEFAULT_REQUEST_RETRY) {
|
|
101
|
+
return pRetry(() => putAuth('/result/run/test', {
|
|
101
102
|
runId: executionId,
|
|
102
103
|
testId,
|
|
103
104
|
resultId,
|
|
@@ -105,11 +106,11 @@ function updateTestStatus(projectId, executionId, testId, resultId, status, data
|
|
|
105
106
|
projectId,
|
|
106
107
|
runnerVersion,
|
|
107
108
|
...data,
|
|
108
|
-
}),
|
|
109
|
+
}), { retries });
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
function updateExecutionTests(executionId, runnerStatuses, status, reason, success, startTime, endTime, projectId) {
|
|
112
|
-
return
|
|
113
|
+
return pRetry(() => putAuth('/result/run/tests', {
|
|
113
114
|
runId: executionId,
|
|
114
115
|
runnerStatuses,
|
|
115
116
|
status,
|
|
@@ -118,7 +119,7 @@ function updateExecutionTests(executionId, runnerStatuses, status, reason, succe
|
|
|
118
119
|
startTime,
|
|
119
120
|
endTime,
|
|
120
121
|
projectId,
|
|
121
|
-
}), DEFAULT_REQUEST_RETRY);
|
|
122
|
+
}), { retries: DEFAULT_REQUEST_RETRY });
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
function reportExecutionStarted({
|
|
@@ -162,7 +163,7 @@ function reportExecutionStarted({
|
|
|
162
163
|
function reportExecutionFinished(status, executionId, projectId, success, tmsOptions = {}, remoteRunId, resultExtraData) {
|
|
163
164
|
const endTime = Date.now();
|
|
164
165
|
|
|
165
|
-
return
|
|
166
|
+
return pRetry(() => putAuth('/result/run', {
|
|
166
167
|
runId: executionId,
|
|
167
168
|
projectId,
|
|
168
169
|
endTime,
|
|
@@ -171,22 +172,22 @@ function reportExecutionFinished(status, executionId, projectId, success, tmsOpt
|
|
|
171
172
|
tmsOptions,
|
|
172
173
|
remoteRunId,
|
|
173
174
|
resultExtraData,
|
|
174
|
-
}), DEFAULT_REQUEST_RETRY);
|
|
175
|
+
}), { reties: DEFAULT_REQUEST_RETRY });
|
|
175
176
|
}
|
|
176
177
|
|
|
177
178
|
async function getTestPlanTestList(projectId, names, planIds, branch, intersections) {
|
|
178
|
-
return
|
|
179
|
+
return pRetry(() => postAuth({
|
|
179
180
|
url: '/testPlan/list',
|
|
180
181
|
body: { projectId, names, planIds, branch, intersections },
|
|
181
182
|
// people who send insane lists get a timeout :(
|
|
182
183
|
timeout: 120000,
|
|
183
|
-
}));
|
|
184
|
+
}), { reties: DEFAULT_REQUEST_RETRY });
|
|
184
185
|
}
|
|
185
186
|
|
|
186
187
|
function getSuiteTestList({
|
|
187
188
|
projectId, labels, testIds, testNames, testConfigNames, suiteNames, suiteIds, branch, rerunFailedByRunId, testConfigIds, intersections,
|
|
188
189
|
}) {
|
|
189
|
-
return
|
|
190
|
+
return pRetry(() => postAuth({
|
|
190
191
|
url: '/suite/v2/list',
|
|
191
192
|
body: {
|
|
192
193
|
projectId,
|
|
@@ -201,11 +202,11 @@ function getSuiteTestList({
|
|
|
201
202
|
testConfigIds,
|
|
202
203
|
intersections,
|
|
203
204
|
},
|
|
204
|
-
}));
|
|
205
|
+
}), { reties: DEFAULT_REQUEST_RETRY });
|
|
205
206
|
}
|
|
206
207
|
|
|
207
208
|
function getUsageForCurrentBillingPeriod(projectId) {
|
|
208
|
-
return
|
|
209
|
+
return pRetry(() => getWithAuth(`/plan/project/${projectId}/usage-current-billing-period`), { reties: DEFAULT_REQUEST_RETRY })
|
|
209
210
|
.catch((error) => {
|
|
210
211
|
logger.error('failed getting usage for current billing period', { projectId, error });
|
|
211
212
|
return undefined;
|
|
@@ -213,11 +214,11 @@ function getUsageForCurrentBillingPeriod(projectId) {
|
|
|
213
214
|
}
|
|
214
215
|
|
|
215
216
|
function isTestResultCompleted(resultId, projectId, testRetryKey) {
|
|
216
|
-
return
|
|
217
|
+
return pRetry(() => getWithAuth(`/result/${resultId}/isComplete`, { projectId, testRetryKey }), { reties: DEFAULT_REQUEST_RETRY });
|
|
217
218
|
}
|
|
218
219
|
|
|
219
220
|
function getTestResults(testId, resultId, projectId, branch) {
|
|
220
|
-
return
|
|
221
|
+
return pRetry(() => getWithAuth(`/test/v2/${testId}/result/${resultId}`, { projectId, branch }), { reties: DEFAULT_REQUEST_RETRY });
|
|
221
222
|
}
|
|
222
223
|
|
|
223
224
|
function keepAliveGrid(projectId, slots) {
|
|
@@ -245,19 +246,19 @@ function getHybridGridProvider(body) {
|
|
|
245
246
|
}
|
|
246
247
|
|
|
247
248
|
function getGridByName(companyId, projectId, gridName, browser, executionId) {
|
|
248
|
-
return
|
|
249
|
+
return pRetry(() => getWithAuth('/grid/name', {
|
|
249
250
|
companyId, projectId, name: gridName, browser, executionId, reqId: utils.guid(),
|
|
250
|
-
}));
|
|
251
|
+
}), { reties: DEFAULT_REQUEST_RETRY });
|
|
251
252
|
}
|
|
252
253
|
|
|
253
254
|
function getGridById(companyId, projectId, gridId, browser, executionId) {
|
|
254
|
-
return
|
|
255
|
+
return pRetry(() => getWithAuth(`/grid/${gridId}`, { companyId, projectId, browser, executionId, reqId: utils.guid() }), { reties: DEFAULT_REQUEST_RETRY });
|
|
255
256
|
}
|
|
256
257
|
|
|
257
258
|
|
|
258
259
|
async function initializeUserWithAuth({ projectId, token, branchName, lightweightMode, localGrid }) {
|
|
259
260
|
try {
|
|
260
|
-
return await
|
|
261
|
+
return await pRetry(() => httpRequest.post({
|
|
261
262
|
url: `${config.SERVICES_HOST}/executions/initialize`,
|
|
262
263
|
body: {
|
|
263
264
|
projectId,
|
|
@@ -266,7 +267,7 @@ async function initializeUserWithAuth({ projectId, token, branchName, lightweigh
|
|
|
266
267
|
lightweightMode,
|
|
267
268
|
localGrid,
|
|
268
269
|
},
|
|
269
|
-
}));
|
|
270
|
+
}), { reties: DEFAULT_REQUEST_RETRY });
|
|
270
271
|
} catch (e) {
|
|
271
272
|
logger.error('error initializing info from server', e);
|
|
272
273
|
if (e && e.message && e.message.includes('Bad Request')) {
|
|
@@ -288,7 +289,7 @@ async function getEditorUrl() {
|
|
|
288
289
|
return config.EDITOR_URL;
|
|
289
290
|
}
|
|
290
291
|
try {
|
|
291
|
-
return await
|
|
292
|
+
return await pRetry(() => getWithAuth('/system-info/editor-url'), { reties: DEFAULT_REQUEST_RETRY });
|
|
292
293
|
} catch (err) {
|
|
293
294
|
logger.error('cannot retrieve editor-url from server');
|
|
294
295
|
return 'https://app.testim.io';
|
|
@@ -296,20 +297,20 @@ async function getEditorUrl() {
|
|
|
296
297
|
}
|
|
297
298
|
|
|
298
299
|
function getAllGrids(companyId) {
|
|
299
|
-
return
|
|
300
|
+
return pRetry(() => getWithAuth('/grid', { companyId }), { reties: DEFAULT_REQUEST_RETRY });
|
|
300
301
|
}
|
|
301
302
|
|
|
302
|
-
const fetchLambdatestConfig = async () =>
|
|
303
|
+
const fetchLambdatestConfig = async () => pRetry(() => getWithAuth('/grid/lt/config'), { reties: DEFAULT_REQUEST_RETRY });
|
|
303
304
|
|
|
304
|
-
const getLabFeaturesByProjectId = async (projectId) =>
|
|
305
|
+
const getLabFeaturesByProjectId = async (projectId) => pRetry(() => getWithAuth(`/labFeature/v2/project/${projectId}`), { reties: DEFAULT_REQUEST_RETRY });
|
|
305
306
|
|
|
306
307
|
|
|
307
308
|
function getRealData(projectId, channel, query) {
|
|
308
|
-
return
|
|
309
|
+
return pRetry(() => getWithAuth(`/real-data/${channel}?${query}&projectId=${projectId}`), { reties: DEFAULT_REQUEST_RETRY });
|
|
309
310
|
}
|
|
310
311
|
|
|
311
312
|
function updateTestResult(projectId, resultId, testId, testResult, remoteRunId) {
|
|
312
|
-
return
|
|
313
|
+
return pRetry(() => postAuth({
|
|
313
314
|
url: '/result/test',
|
|
314
315
|
body: {
|
|
315
316
|
projectId,
|
|
@@ -318,11 +319,11 @@ function updateTestResult(projectId, resultId, testId, testResult, remoteRunId)
|
|
|
318
319
|
testResult,
|
|
319
320
|
remoteRunId,
|
|
320
321
|
},
|
|
321
|
-
}));
|
|
322
|
+
}), { reties: DEFAULT_REQUEST_RETRY });
|
|
322
323
|
}
|
|
323
324
|
|
|
324
325
|
function clearTestResult(projectId, resultId, testId, testResult) {
|
|
325
|
-
return
|
|
326
|
+
return pRetry(() => postAuth({
|
|
326
327
|
url: '/result/test/clear',
|
|
327
328
|
body: {
|
|
328
329
|
projectId,
|
|
@@ -330,11 +331,11 @@ function clearTestResult(projectId, resultId, testId, testResult) {
|
|
|
330
331
|
testId,
|
|
331
332
|
testResult,
|
|
332
333
|
},
|
|
333
|
-
}));
|
|
334
|
+
}), { reties: DEFAULT_REQUEST_RETRY });
|
|
334
335
|
}
|
|
335
336
|
|
|
336
337
|
function saveRemoteStep(projectId, resultId, stepId, remoteStep) {
|
|
337
|
-
return
|
|
338
|
+
return pRetry(() => postAuth({
|
|
338
339
|
url: '/remoteStep',
|
|
339
340
|
body: {
|
|
340
341
|
projectId,
|
|
@@ -342,7 +343,7 @@ function saveRemoteStep(projectId, resultId, stepId, remoteStep) {
|
|
|
342
343
|
stepId,
|
|
343
344
|
remoteStep,
|
|
344
345
|
},
|
|
345
|
-
}));
|
|
346
|
+
}), { reties: DEFAULT_REQUEST_RETRY });
|
|
346
347
|
}
|
|
347
348
|
|
|
348
349
|
function relativize(uri) {
|
|
@@ -381,9 +382,9 @@ function uploadArtifact(projectId, testId, testResultId, content, subType, mimeT
|
|
|
381
382
|
},
|
|
382
383
|
};
|
|
383
384
|
|
|
384
|
-
return
|
|
385
|
+
return pRetry(() => postAuthFormData(`/storage${storagePath}`, {}, files, {
|
|
385
386
|
'X-Asset-Encoding': 'gzip',
|
|
386
|
-
})).then(() => storagePath);
|
|
387
|
+
}), { reties: DEFAULT_REQUEST_RETRY }).then(() => storagePath);
|
|
387
388
|
}
|
|
388
389
|
|
|
389
390
|
const uploadRunDataArtifact = _.memoize(async (projectId, testId, testResultId, runData) => {
|
|
@@ -422,7 +423,7 @@ function addTestRetry({
|
|
|
422
423
|
previousTestResultId,
|
|
423
424
|
testResult,
|
|
424
425
|
}) {
|
|
425
|
-
return
|
|
426
|
+
return pRetry(() => postAuth({
|
|
426
427
|
url: '/result/test/retry',
|
|
427
428
|
body: {
|
|
428
429
|
projectId,
|
|
@@ -433,7 +434,7 @@ function addTestRetry({
|
|
|
433
434
|
runId,
|
|
434
435
|
testResult,
|
|
435
436
|
},
|
|
436
|
-
}), DEFAULT_REQUEST_RETRY);
|
|
437
|
+
}), { reties: DEFAULT_REQUEST_RETRY });
|
|
437
438
|
}
|
|
438
439
|
|
|
439
440
|
/**
|
|
@@ -475,6 +476,10 @@ function deleteCloudflareTunnel(companyId, tunnelId) {
|
|
|
475
476
|
}
|
|
476
477
|
}
|
|
477
478
|
|
|
479
|
+
function updateRemoteRunFailure(body) {
|
|
480
|
+
return httpRequest.post({ url: `${config.SERVICES_HOST}/result/remoteRunFailure`, body });
|
|
481
|
+
}
|
|
482
|
+
|
|
478
483
|
module.exports = {
|
|
479
484
|
getS3Artifact,
|
|
480
485
|
getTestPlan,
|
|
@@ -510,4 +515,5 @@ module.exports = {
|
|
|
510
515
|
getCloudflareTunnel,
|
|
511
516
|
forceUpdateCloudflareTunnelRoutes,
|
|
512
517
|
deleteCloudflareTunnel,
|
|
518
|
+
updateRemoteRunFailure,
|
|
513
519
|
};
|
package/errors.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { AbortError } = require('p-retry');
|
|
1
2
|
/**
|
|
2
3
|
* NoArgsError - throws when arguments not passed to cli
|
|
3
4
|
*
|
|
@@ -57,7 +58,7 @@ class GetBrowserError extends Error {
|
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
|
|
60
|
-
class PageNotAvailableError extends
|
|
61
|
+
class PageNotAvailableError extends AbortError {
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
class QuotaDepletedError extends Error { }
|