@testim/testim-cli 3.213.0 → 3.217.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/agent/routers/cliJsCode/service.js +46 -85
- package/agent/routers/codim/service.js +0 -2
- package/cli.js +0 -9
- package/cliAgentMode.js +0 -1
- package/codim/codim-npm-package/package-lock.json +3 -3
- package/codim/codim-npm-package/package.json +1 -1
- package/codim/template.js/package.json +4 -4
- package/codim/template.ts/package.json +4 -4
- package/commons/featureFlags.js +1 -1
- package/commons/httpRequest.js +4 -1
- package/commons/npmWrapper.js +14 -7
- package/commons/npmWrapper.test.js +1 -1
- package/commons/testimDesiredCapabilitiesBuilder.js +21 -0
- package/npm-shrinkwrap.json +21670 -6815
- package/package.json +16 -17
- package/player/seleniumTestPlayer.js +4 -2
- package/player/services/frameLocator.js +106 -102
- package/player/services/tabService.js +28 -28
- package/player/utils/imageCaptureUtils.js +10 -1
- package/player/utils/screenshotUtils.js +1 -1
- package/runOptions.js +22 -4
- package/runner.js +4 -3
- package/services/lambdatestService.js +1 -0
- package/testRunHandler.js +8 -5
- package/workers/WorkerExtension.js +2 -5
- package/workers/WorkerSelenium.js +5 -10
- package/workers/workerUtils.js +0 -39
- package/agent/routers/cliJsCode/runNpmWorker.js +0 -39
package/runner.js
CHANGED
|
@@ -25,6 +25,7 @@ const FREE_PLAN_MINIMUM_BROWSER_TIMEOUT = 30 * 60 * 1000;
|
|
|
25
25
|
const TestPlanRunner = require('./runners/TestPlanRunner');
|
|
26
26
|
const labFeaturesService = require('./services/labFeaturesService');
|
|
27
27
|
const featureAvailabilityService = require('./commons/featureAvailabilityService');
|
|
28
|
+
const featureFlagService = require('./commons/featureFlags');
|
|
28
29
|
|
|
29
30
|
const logger = require('./commons/logger').getLogger('runner');
|
|
30
31
|
|
|
@@ -268,12 +269,12 @@ async function init(options) {
|
|
|
268
269
|
await labFeaturesService.loadLabFeatures(projectById.id, companyByProjectId.activePlan);
|
|
269
270
|
}
|
|
270
271
|
|
|
271
|
-
if (options.lightweightMode && options.lightweightMode.type === '
|
|
272
|
+
if (options.lightweightMode && options.lightweightMode.type === 'turboMode' && (featureFlagService.flags.highSpeedMode.getValue() === 'disabled' || options.company.planType === 'free')) {
|
|
272
273
|
delete options.lightweightMode;
|
|
273
274
|
}
|
|
274
275
|
|
|
275
|
-
if (options.lightweightMode && options.lightweightMode.type === '
|
|
276
|
-
console.log('
|
|
276
|
+
if (options.lightweightMode && options.lightweightMode.type === 'turboMode') {
|
|
277
|
+
console.log('\nTurbo mode will ignore step delays. Test artifacts like screenshots and logs will only be saved for failed runs. For more information see our docs: https://help.testim.io/docs/turbo-mode');
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
gridService.keepAlive.start(project);
|
package/testRunHandler.js
CHANGED
|
@@ -18,7 +18,7 @@ const { SeleniumPerfStats } = require('./commons/SeleniumPerfStats');
|
|
|
18
18
|
const { preloadTests } = require('./commons/preloadTests');
|
|
19
19
|
|
|
20
20
|
const RETRIES_ON_TIMEOUT = 3;
|
|
21
|
-
const MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE =
|
|
21
|
+
const MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE = 20 * 1000; // max size, in characters, of stringified run data sent over URL params. Chosen arbitrarily, this value should be changed according to data.
|
|
22
22
|
const canSendRunDataOverUrl = (runData) => JSON.stringify(runData).length < MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE;
|
|
23
23
|
|
|
24
24
|
const TestRun = function (executionId, executionName, test, options, branchToUse, testRunStatus) {
|
|
@@ -181,8 +181,9 @@ TestRun.prototype.getRunRequestParams = async function () {
|
|
|
181
181
|
runRequestParams.lightweightMode.isRunDataSentInUrl = canSendRunDataOverUrl(runData);
|
|
182
182
|
if (runRequestParams.lightweightMode.isRunDataSentInUrl) {
|
|
183
183
|
runRequestParams.runData = runData;
|
|
184
|
+
logger.info(`Run data sent as URL param, test id: ${this.getTestId()} run data length: ${JSON.stringify(runData).length}`);
|
|
184
185
|
} else {
|
|
185
|
-
logger.warn(`Run data is too big to be sent as a URL param (
|
|
186
|
+
logger.warn(`Run data is too big to be sent as a URL param. Test id: ${this.getTestId()}, run data size: ${JSON.stringify(runData).length} (limit: ${MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE} characters)`);
|
|
186
187
|
}
|
|
187
188
|
runRequestParams.isLocalRun = Boolean(this._options.useLocalChromeDriver || this._options.useChromeLauncher);
|
|
188
189
|
}
|
|
@@ -203,9 +204,11 @@ TestRun.prototype.getRunRequestParams = async function () {
|
|
|
203
204
|
return runRequestParams;
|
|
204
205
|
};
|
|
205
206
|
|
|
206
|
-
TestRun.prototype.getRunTestUrl = function () {
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
TestRun.prototype.getRunTestUrl = async function () {
|
|
208
|
+
const runRequestParams = await this.getRunRequestParams();
|
|
209
|
+
const url = `https://run.testim.io/?params=${encodeURIComponent(JSON.stringify(runRequestParams))}`;
|
|
210
|
+
logger.info(`Test (${this.getTestId()}) run URL length: ${url.length}`);
|
|
211
|
+
return url;
|
|
209
212
|
};
|
|
210
213
|
|
|
211
214
|
TestRun.prototype.setSessionId = function (sessionId) {
|
|
@@ -110,14 +110,11 @@ class WorkerExtension extends BaseWorker {
|
|
|
110
110
|
};
|
|
111
111
|
driver.registerToClosedBrowser(onBrowserClosed);
|
|
112
112
|
return testRunHandler.onCompleted().timeout(this.testRunTimeout, timeoutMessages.TEST_COMPLETE_TIMEOUT_MSG)
|
|
113
|
-
.
|
|
113
|
+
.then(async testResult => {
|
|
114
114
|
driver.unregisterToClosedBrowser(onBrowserClosed);
|
|
115
115
|
if (this.lambdatestService.isLambdatestRun()) {
|
|
116
|
-
|
|
116
|
+
await driver.executeJS(`lambda-status=${!testResult.success ? 'failed' : 'passed'}`).catch(() => { });
|
|
117
117
|
}
|
|
118
|
-
return undefined;
|
|
119
|
-
})
|
|
120
|
-
.then(testResult => {
|
|
121
118
|
if (!driver.isAlive()) {
|
|
122
119
|
logger.warn(`possible grid unresponsive for test ${this.testId}, result ${this.testResultId} (execution: ${this.executionId})`);
|
|
123
120
|
testResult.gridIssues = 'could not validate grid is alive';
|
|
@@ -168,13 +168,10 @@ class WorkerSelenium extends BaseWorker {
|
|
|
168
168
|
}
|
|
169
169
|
throw err;
|
|
170
170
|
})
|
|
171
|
-
.
|
|
171
|
+
.then(async testResult => {
|
|
172
172
|
if (sessionPlayerInit.localAssetService) {
|
|
173
|
-
|
|
173
|
+
await sessionPlayerInit.localAssetService.drain();
|
|
174
174
|
}
|
|
175
|
-
return undefined;
|
|
176
|
-
})
|
|
177
|
-
.then(testResult => {
|
|
178
175
|
testResult.stepsResults = null;
|
|
179
176
|
testResult.resultId = this.testResultId;
|
|
180
177
|
if (!driver.isAlive()) {
|
|
@@ -187,13 +184,11 @@ class WorkerSelenium extends BaseWorker {
|
|
|
187
184
|
logger.warn(`possible browser keep alive issue ${this.testId}, result ${this.testResultId} (execution: ${this.executionId})`);
|
|
188
185
|
testResult.keepAliveIssue = maxKeepAliveGap;
|
|
189
186
|
}
|
|
190
|
-
|
|
191
|
-
})
|
|
192
|
-
.tap(testResult => {
|
|
187
|
+
const resultWithStats = { ...testResult, ...testRunHandler.seleniumPerfStats.getStats() };
|
|
193
188
|
if (this.lambdatestService.isLambdatestRun()) {
|
|
194
|
-
|
|
189
|
+
await driver.executeJS(`lambda-status=${!resultWithStats.success ? 'failed' : 'passed'}`).catch(() => { });
|
|
195
190
|
}
|
|
196
|
-
return
|
|
191
|
+
return resultWithStats;
|
|
197
192
|
});
|
|
198
193
|
}
|
|
199
194
|
|
package/workers/workerUtils.js
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
const Promise = require('bluebird');
|
|
2
|
-
const utils = require('../utils');
|
|
3
2
|
const gridService = require('../services/gridService');
|
|
4
3
|
const logger = require('../commons/logger').getLogger('worker-utils');
|
|
5
|
-
const { timeoutMessages } = require('../commons/constants');
|
|
6
|
-
const { GetBrowserError, PageNotAvailableError } = require('../errors');
|
|
7
|
-
|
|
8
|
-
const waitUntilBrowserTimeout = (err, startTime, interval, projectId, workerId, player, releaseSlotOnTestFinished) => {
|
|
9
|
-
logger.warn('failed getting browser from grid', { err });
|
|
10
|
-
return releasePlayer(workerId, releaseSlotOnTestFinished, projectId, player)
|
|
11
|
-
.then(() => {
|
|
12
|
-
const requestTime = Date.now() - startTime;
|
|
13
|
-
const timeDiff = interval - requestTime;
|
|
14
|
-
return Promise.delay(timeDiff).then(() => Promise.reject(err));
|
|
15
|
-
});
|
|
16
|
-
};
|
|
17
4
|
|
|
18
5
|
const releaseGridSlot = (workerId, releaseSlotOnTestFinished, projectId) => {
|
|
19
6
|
if (!releaseSlotOnTestFinished) {
|
|
@@ -29,29 +16,3 @@ const releasePlayer = (workerId, releaseSlotOnTestFinished, projectId, player) =
|
|
|
29
16
|
};
|
|
30
17
|
|
|
31
18
|
module.exports.releasePlayer = releasePlayer;
|
|
32
|
-
|
|
33
|
-
module.exports.getBrowserWithRetries = ({ getBrowserOnce, testPlayerFactory, releaseSlotOnTestFinished }, { totalTimeoutDuration, singleGetBrowserDuration, projectId, workerId, reporter }) => {
|
|
34
|
-
const maxGetBrowserAttempts = totalTimeoutDuration / singleGetBrowserDuration;
|
|
35
|
-
let failedAttempts = 0;
|
|
36
|
-
|
|
37
|
-
return utils.runWithRetries(() => {
|
|
38
|
-
const startTime = Date.now();
|
|
39
|
-
const player = testPlayerFactory();
|
|
40
|
-
return getBrowserOnce(player)
|
|
41
|
-
.then((getBrowserRes) => player || getBrowserRes)
|
|
42
|
-
.timeout(singleGetBrowserDuration, timeoutMessages.GET_BROWSER_TIMEOUT_MSG)
|
|
43
|
-
.catch(err => {
|
|
44
|
-
reporter.onGetBrowserFailure(workerId, projectId, ++failedAttempts);
|
|
45
|
-
throw err;
|
|
46
|
-
})
|
|
47
|
-
.tap(() => reporter.onGetBrowserSuccess(workerId, projectId))
|
|
48
|
-
.catch(err => waitUntilBrowserTimeout(err, startTime, singleGetBrowserDuration, projectId, workerId, player, releaseSlotOnTestFinished));
|
|
49
|
-
}, maxGetBrowserAttempts).catch(err => {
|
|
50
|
-
if (err instanceof PageNotAvailableError) {
|
|
51
|
-
throw err;
|
|
52
|
-
}
|
|
53
|
-
throw new GetBrowserError(err);
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
module.exports.isGetBrowserError = err => err && err.constructor && err.constructor.name === 'GetBrowserError';
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
module.exports = function (input) {
|
|
2
|
-
const {transactionId, packages, command, localPackageInstallFolder, proxyUri} = input;
|
|
3
|
-
return installLocalPackages(transactionId, packages, command, localPackageInstallFolder, proxyUri);
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const npm = require("npm");
|
|
8
|
-
const {NpmPackageError} = require('../../../errors');
|
|
9
|
-
|
|
10
|
-
function installLocalPackages(transactionId, packages, command, localPackageInstallFolder, proxyUri) {
|
|
11
|
-
if (!packages || packages.length === 0) {
|
|
12
|
-
return Promise.resolve();
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const installFolder = path.join(localPackageInstallFolder, `/${transactionId}`);
|
|
16
|
-
|
|
17
|
-
return new Promise((resolve, reject) => {
|
|
18
|
-
const npmLoadConfig = {
|
|
19
|
-
prefix: installFolder,
|
|
20
|
-
loglevel: 'silent',
|
|
21
|
-
};
|
|
22
|
-
if(proxyUri) {
|
|
23
|
-
npmLoadConfig.proxy = proxyUri;
|
|
24
|
-
npmLoadConfig["https-proxy"] = proxyUri;
|
|
25
|
-
}
|
|
26
|
-
npm.load(npmLoadConfig, (err) => {
|
|
27
|
-
if (err) {
|
|
28
|
-
return reject(err);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
npm.commands[command](packages, (installErr, data) => {
|
|
32
|
-
if (installErr) {
|
|
33
|
-
return reject(new NpmPackageError(installErr.message));
|
|
34
|
-
}
|
|
35
|
-
resolve(Object.assign({data, installFolder}));
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
}
|