@testim/testim-cli 3.253.0 → 3.255.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/OverrideTestDataBuilder.js +1 -1
- package/agent/routers/cliJsCode/index.js +4 -4
- package/agent/routers/cliJsCode/router.js +46 -42
- package/agent/routers/cliJsCode/service.js +18 -13
- package/agent/routers/codim/router.js +14 -17
- package/agent/routers/codim/router.test.js +19 -21
- package/agent/routers/codim/service.js +16 -16
- package/agent/routers/general/index.js +4 -8
- package/agent/routers/hybrid/registerRoutes.js +18 -18
- package/agent/routers/index.js +7 -7
- package/agent/routers/playground/router.js +11 -10
- package/agent/routers/playground/service.js +22 -23
- package/agent/routers/standalone-browser/registerRoutes.js +10 -10
- package/cdpTestRunner.js +4 -3
- package/chromiumInstaller.js +4 -5
- package/cli/onExit.js +2 -2
- package/cli.js +11 -10
- package/cliAgentMode.js +8 -8
- package/codim/codim-cli.js +20 -17
- package/codim/hybrid-utils.js +1 -1
- package/codim/measure-perf.js +9 -6
- package/codim/template.js/tests/examples/01-simple-text-validation.test.js +6 -6
- package/codim/template.js/tests/examples/02-using-locators.test.js +13 -15
- package/codim/template.js/tests/examples/03-using-hooks.test.js +17 -19
- package/codim/template.js/tests/examples/04-skip-and-only.test.js +16 -17
- package/codim/template.js/tests/examples/05-multiple-windows.test.js +16 -17
- package/codim/template.js/webpack.config.js +1 -1
- package/codim/template.ts/webpack.config.js +3 -3
- package/commons/AbortError.js +4 -4
- package/commons/detectDebugger.js +4 -2
- package/commons/featureFlags.js +8 -0
- package/commons/httpRequest.js +5 -1
- package/commons/httpRequestCounters.js +21 -10
- package/commons/lazyRequire.js +14 -12
- package/commons/logger.js +4 -4
- package/commons/performance-logger.js +14 -8
- package/commons/preloadTests.js +2 -2
- package/commons/prepareRunner.js +4 -2
- package/commons/prepareRunnerAndTestimStartUtils.js +40 -42
- package/commons/runnerFileCache.js +1 -1
- package/commons/socket/baseSocketServiceSocketIO.js +32 -34
- package/commons/socket/realDataService.js +6 -5
- package/commons/socket/realDataServiceSocketIO.js +4 -4
- package/commons/socket/remoteStepService.js +4 -3
- package/commons/socket/remoteStepServiceSocketIO.js +11 -12
- package/commons/socket/socketService.js +50 -52
- package/commons/socket/testResultServiceSocketIO.js +11 -11
- package/commons/testimDesiredCapabilitiesBuilder.js +3 -2
- package/commons/testimNgrok.js +2 -2
- package/commons/testimNgrok.test.js +1 -1
- package/commons/testimServicesApi.js +27 -20
- package/commons/testimTunnel.test.js +2 -1
- package/commons/xhr2.js +97 -100
- package/coverage/SummaryToObjectReport.js +0 -1
- package/coverage/jsCoverage.js +12 -10
- package/errors.js +5 -0
- package/fixLocalBuild.js +2 -0
- package/inputFileUtils.js +11 -9
- package/npm-shrinkwrap.json +2286 -1284
- package/package.json +9 -8
- package/player/appiumTestPlayer.js +1 -1
- package/player/chromeLauncherTestPlayer.js +0 -1
- package/player/services/tabService.js +15 -1
- package/player/services/tabServiceMock.js +166 -0
- package/player/stepActions/locateStepAction.js +2 -0
- package/player/stepActions/navigationStepAction.js +11 -10
- package/player/stepActions/sleepStepAction.js +4 -5
- package/player/stepActions/textStepAction.js +4 -11
- package/player/utils/imageCaptureUtils.js +81 -120
- package/player/utils/windowUtils.js +4 -3
- package/player/webdriver.js +26 -23
- package/processHandler.js +3 -3
- package/processHandler.test.js +1 -1
- package/reports/consoleReporter.js +3 -2
- package/reports/junitReporter.js +7 -9
- package/reports/reporter.js +34 -39
- package/runOptions.d.ts +260 -0
- package/runOptions.js +59 -44
- package/runner.js +14 -0
- package/runners/ParallelWorkerManager.js +9 -10
- package/runners/TestPlanRunner.js +142 -78
- package/runners/buildCodeTests.js +38 -37
- package/runners/runnerUtils.js +3 -3
- package/services/gridService.js +36 -40
- package/services/lambdatestService.js +3 -5
- package/stepPlayers/cliJsStepPlayback.js +22 -17
- package/testRunHandler.js +8 -0
- package/testRunStatus.js +9 -6
- package/utils/argsUtils.js +86 -0
- package/utils/argsUtils.test.js +32 -0
- package/utils/fsUtils.js +154 -0
- package/{utils.js → utils/index.js} +19 -262
- package/utils/promiseUtils.js +89 -0
- package/utils/stringUtils.js +98 -0
- package/utils/stringUtils.test.js +22 -0
- package/utils/timeUtils.js +25 -0
- package/utils/utils.test.js +27 -0
- package/workers/BaseWorker.js +16 -14
- package/workers/WorkerAppium.js +1 -1
- package/workers/WorkerExtension.js +6 -7
- package/workers/WorkerExtensionSingleBrowser.js +4 -4
- package/workers/WorkerSelenium.js +5 -2
- package/utils.test.js +0 -68
package/workers/BaseWorker.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const Bluebird = require('bluebird');
|
|
4
3
|
const moment = require('moment');
|
|
5
4
|
const pRetry = require('p-retry');
|
|
6
5
|
const ms = require('ms');
|
|
@@ -128,8 +127,7 @@ class BaseWorker {
|
|
|
128
127
|
let gridInfo = await pRetry(async () => {
|
|
129
128
|
const startTime = Date.now();
|
|
130
129
|
try {
|
|
131
|
-
return await
|
|
132
|
-
.timeout(this.options.getBrowserTimeout, timeoutMessages.GET_BROWSER_TIMEOUT_MSG);
|
|
130
|
+
return await utils.promiseTimeout(this.getSlotOnce(testRunHandler), this.options.getBrowserTimeout, timeoutMessages.GET_BROWSER_TIMEOUT_MSG);
|
|
133
131
|
} catch (error) {
|
|
134
132
|
logger.error('error getting grid slot', { error, testId: this.testId, testResultId: this.testResultId, executionId: this.executionId });
|
|
135
133
|
failedGetSlotAttempts++;
|
|
@@ -156,11 +154,13 @@ class BaseWorker {
|
|
|
156
154
|
this.options.gridData.host = gridInfo.host;
|
|
157
155
|
this.options.gridData.failedGetBrowserAttempts = failedGetBrowserAttempts;
|
|
158
156
|
const getSessionTimeout = this.setSessionTimeout();
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
157
|
+
perf.log('before getBrowserOnce');
|
|
158
|
+
const getBrowserRes = await utils.promiseTimeout(
|
|
159
|
+
this.getBrowserOnce(testRunHandler, customExtensionLocalLocation, player, gridInfo),
|
|
160
|
+
getSessionTimeout,
|
|
161
|
+
timeoutMessages.GET_BROWSER_TIMEOUT_MSG,
|
|
162
|
+
);
|
|
163
|
+
perf.log('after getBrowserOnce');
|
|
164
164
|
reporter.onGetBrowserSuccess(this.id, projectId);
|
|
165
165
|
return player || getBrowserRes;
|
|
166
166
|
} catch (error) {
|
|
@@ -243,7 +243,7 @@ class BaseWorker {
|
|
|
243
243
|
const testRetryKey = testRunHandler.getRetryKey();
|
|
244
244
|
testResult.testRetryKey = testRetryKey;
|
|
245
245
|
await this.onTestCompleted(this.id, this.testId, testResult, sessionId, shouldRerun);
|
|
246
|
-
if (this.executionQueue.hasMoreTests() && !
|
|
246
|
+
if (this.executionQueue.hasMoreTests() && !this.options.lightweightMode?.general) {
|
|
247
247
|
await utils.delay(DELAY_BETWEEN_TESTS);
|
|
248
248
|
}
|
|
249
249
|
await this.runTestCleanup();
|
|
@@ -264,11 +264,11 @@ class BaseWorker {
|
|
|
264
264
|
return await runTestAndCalcResult(testRunHandler, shouldRerun);
|
|
265
265
|
}
|
|
266
266
|
return await runNextTest();
|
|
267
|
-
} catch (
|
|
268
|
-
if (
|
|
267
|
+
} catch (error) {
|
|
268
|
+
if (error instanceof StopRunOnError) {
|
|
269
269
|
return undefined;
|
|
270
270
|
}
|
|
271
|
-
logger.error('failed to process test result', {
|
|
271
|
+
logger.error('failed to process test result', { error });
|
|
272
272
|
runNextTest();
|
|
273
273
|
return undefined;
|
|
274
274
|
}
|
|
@@ -342,7 +342,7 @@ class BaseWorker {
|
|
|
342
342
|
}
|
|
343
343
|
logger.warn('error on run', { err });
|
|
344
344
|
|
|
345
|
-
const projectId = this.userData
|
|
345
|
+
const projectId = this.userData?.projectId;
|
|
346
346
|
const { errorType, reason } = buildError(err, wasNetworkHealthy);
|
|
347
347
|
testimServicesApi.updateTestResult(projectId, this.testResultId, this.testId, {
|
|
348
348
|
status: testRunStatus.COMPLETED,
|
|
@@ -358,7 +358,7 @@ class BaseWorker {
|
|
|
358
358
|
const recoverTestResults = async (runError, testRunHandler) => {
|
|
359
359
|
const testId = this.testId;
|
|
360
360
|
const resultId = this.testResultId;
|
|
361
|
-
const projectId = this.userData
|
|
361
|
+
const projectId = this.userData?.projectId;
|
|
362
362
|
const branch = this.branch;
|
|
363
363
|
if (!testId || !resultId || !projectId || !branch) {
|
|
364
364
|
// Not enough data to call the API
|
|
@@ -409,6 +409,7 @@ class BaseWorker {
|
|
|
409
409
|
});
|
|
410
410
|
|
|
411
411
|
const testRunHandler = this.executionQueue.getNext();
|
|
412
|
+
|
|
412
413
|
if (!testRunHandler) { // no more tests to run
|
|
413
414
|
return this.onQueueCompleted();
|
|
414
415
|
}
|
|
@@ -418,6 +419,7 @@ class BaseWorker {
|
|
|
418
419
|
this.overrideTestConfigId = testRunHandler.getOverrideTestConfigId();
|
|
419
420
|
this.testRunConfig = testRunHandler.getRunConfig();
|
|
420
421
|
this.branch = testRunHandler.getBranch();
|
|
422
|
+
|
|
421
423
|
return runTestAndCalcResult(testRunHandler);
|
|
422
424
|
}
|
|
423
425
|
}
|
package/workers/WorkerAppium.js
CHANGED
|
@@ -113,7 +113,7 @@ class WorkerAppium extends BaseWorker {
|
|
|
113
113
|
}
|
|
114
114
|
try {
|
|
115
115
|
await super.runTestOnce(testRunHandler, appiumTestPlayer);
|
|
116
|
-
await runAppiumTest.call(this);
|
|
116
|
+
return await runAppiumTest.call(this);
|
|
117
117
|
} catch (err) {
|
|
118
118
|
logger.error('failed to run test once', { err });
|
|
119
119
|
throw err;
|
|
@@ -10,7 +10,6 @@ const ExtensionTestPlayer = require('../player/extensionTestPlayer');
|
|
|
10
10
|
const ChromeLauncherTestPlayer = require('../player/chromeLauncherTestPlayer');
|
|
11
11
|
const reporter = require('../reports/reporter');
|
|
12
12
|
|
|
13
|
-
const TEST_START_TIMEOUT_MS = parseInt(process.env.TESTIM_TEST_START_TIMEOUT, 10) || (2 * 60 * 1000);
|
|
14
13
|
|
|
15
14
|
class WorkerExtension extends BaseWorker {
|
|
16
15
|
initPlayer() {
|
|
@@ -65,7 +64,7 @@ class WorkerExtension extends BaseWorker {
|
|
|
65
64
|
if (this.options.useChromeLauncher) {
|
|
66
65
|
const testTimeout = this.options.timeoutWasGiven ?
|
|
67
66
|
Math.max(10000, this.options.timeout) :
|
|
68
|
-
|
|
67
|
+
this.options.testStartTimeout;
|
|
69
68
|
|
|
70
69
|
reporter.onWaitToTestStart(this.id);
|
|
71
70
|
reporter.onWaitToTestComplete(this.id, this.isCodeMode);
|
|
@@ -82,20 +81,20 @@ class WorkerExtension extends BaseWorker {
|
|
|
82
81
|
});
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
const
|
|
84
|
+
const startStatusDetails = { driverUrlFinished: false, testRunHandlerOnStartedHadFinished: false }; //for logging / debugging purposes
|
|
86
85
|
return new Promise((resolve, reject) => testRunHandler.getRunTestUrl()
|
|
87
86
|
.then(url => {
|
|
88
87
|
reporter.onWaitToTestStart(this.id);
|
|
89
88
|
return Promise.all([
|
|
90
|
-
driver.url(url).tap(() => {
|
|
89
|
+
driver.url(url).tap(() => { startStatusDetails.driverUrlFinished = true; }).catch(err => {
|
|
91
90
|
logger.error('error from driver.url', { err, testResultId, executionId, testId, url, urlLength: url.length });
|
|
92
91
|
throw err;
|
|
93
92
|
}),
|
|
94
|
-
testRunHandler.onStarted(
|
|
93
|
+
testRunHandler.onStarted(this.options.testStartTimeout).tap(() => { startStatusDetails.testRunHandlerOnStartedHadFinished = true; }),
|
|
95
94
|
])
|
|
96
|
-
.timeout(
|
|
95
|
+
.timeout(this.options.testStartTimeout, timeoutMessages.TEST_START_TIMEOUT_MSG)
|
|
97
96
|
.catch(Promise.TimeoutError, () => {
|
|
98
|
-
logger.warn('timeout occurred (see log\'s payload). Running checkViaRestAPIIfTestStarted', { testResultId, executionId, testId, ...
|
|
97
|
+
logger.warn('timeout occurred (see log\'s payload). Running checkViaRestAPIIfTestStarted', { testResultId, executionId, testId, ...startStatusDetails });
|
|
99
98
|
return testRunHandler.checkViaRestAPIIfTestStarted();
|
|
100
99
|
});
|
|
101
100
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const { delay } = require('../utils');
|
|
4
4
|
const { releasePlayer } = require('./workerUtils');
|
|
5
5
|
const WorkerExtension = require('./WorkerExtension');
|
|
6
6
|
const perf = require('../commons/performance-logger');
|
|
@@ -14,7 +14,7 @@ class WorkerExtensionSingleBrowser extends WorkerExtension {
|
|
|
14
14
|
if (!this.testPlayer) {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
await releasePlayer(this.id, this.releaseSlotOnTestFinished, this.userData
|
|
17
|
+
await releasePlayer(this.id, this.releaseSlotOnTestFinished, this.userData?.projectId, this.testPlayer);
|
|
18
18
|
this.testPlayer = null;
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -58,8 +58,8 @@ class WorkerExtensionSingleBrowser extends WorkerExtension {
|
|
|
58
58
|
await this.onQueueCompleted();
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
|
-
if (this.options.lightweightMode
|
|
62
|
-
await
|
|
61
|
+
if (this.options.lightweightMode?.general) {
|
|
62
|
+
await delay(DELAY_BETWEEN_TESTS);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -92,12 +92,15 @@ class WorkerSelenium extends BaseWorker {
|
|
|
92
92
|
sessionPlayer.playbackManager.executionName = testRunHandler.getExecutionName();
|
|
93
93
|
|
|
94
94
|
sessionPlayer.setLightweightMode(this.options.lightweightMode);
|
|
95
|
+
if (testRunHandler.getSfdcCredential()) {
|
|
96
|
+
sessionPlayer.setSfdcCredential(testRunHandler.getSfdcCredential());
|
|
97
|
+
}
|
|
95
98
|
if (sessionPlayerInit.localAssetService) {
|
|
96
99
|
sessionPlayerInit.localAssetService.initialize({ serverUrl: this.options.localRCASaver });
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
let preloadedTest = null;
|
|
100
|
-
if (this.options.lightweightMode
|
|
103
|
+
if (this.options.lightweightMode?.preloadTests) {
|
|
101
104
|
const preloadedTests = await preloadTests(this.options);
|
|
102
105
|
preloadedTest = preloadedTests[this.testId];
|
|
103
106
|
}
|
|
@@ -208,7 +211,7 @@ class WorkerSelenium extends BaseWorker {
|
|
|
208
211
|
function setupCliPerformanceMonitoring(sessionPlayer) {
|
|
209
212
|
const { playback } = sessionPlayerInit.commonConstants;
|
|
210
213
|
function monitorEvent(event) {
|
|
211
|
-
sessionPlayer.playbackManager.on(event, (
|
|
214
|
+
sessionPlayer.playbackManager.on(event, () => {
|
|
212
215
|
perf.log(`Got event ${event}`);
|
|
213
216
|
});
|
|
214
217
|
}
|
package/utils.test.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
const chai = require('chai');
|
|
2
|
-
const utils = require('./utils');
|
|
3
|
-
|
|
4
|
-
const expect = chai.expect;
|
|
5
|
-
|
|
6
|
-
describe('utils', () => {
|
|
7
|
-
describe('calcPercentile', () => {
|
|
8
|
-
it('should calc some precentiles', () => {
|
|
9
|
-
// Arrange:
|
|
10
|
-
const arr = [4, 5, 1, 2, 7, 8, 3, 6, 9, 10];
|
|
11
|
-
|
|
12
|
-
// Act:
|
|
13
|
-
const p0 = utils.calcPercentile(arr, 0);
|
|
14
|
-
const p50 = utils.calcPercentile(arr, 50);
|
|
15
|
-
const p90 = utils.calcPercentile(arr, 90);
|
|
16
|
-
const p95 = utils.calcPercentile(arr, 95);
|
|
17
|
-
const p100 = utils.calcPercentile(arr, 100);
|
|
18
|
-
|
|
19
|
-
// Assert:
|
|
20
|
-
expect(p0).to.eql(1);
|
|
21
|
-
expect(p50).to.eql(5);
|
|
22
|
-
expect(p90).to.eql(9);
|
|
23
|
-
expect(p95).to.eql(10);
|
|
24
|
-
expect(p100).to.eql(10);
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
describe('getTestUrl', () => {
|
|
28
|
-
it('should create properly escaped test URL', () => {
|
|
29
|
-
expect(utils.getTestUrl('http://localhost:8080', 'project', 'test')).to.equal('http://localhost:8080/#/project/project/branch/master/test/test');
|
|
30
|
-
expect(utils.getTestUrl('http://localhost:8080', 'project', 'test', 'result')).to.equal('http://localhost:8080/#/project/project/branch/master/test/test?result-id=result');
|
|
31
|
-
expect(utils.getTestUrl('http://localhost:8080', 'project', 'test', 'result', null)).to.equal('http://localhost:8080/#/project/project/branch/master/test/test?result-id=result');
|
|
32
|
-
expect(utils.getTestUrl('http://localhost:8080', 'project', 'test', 'result', 'normal-branch-name'))
|
|
33
|
-
.to.equal('http://localhost:8080/#/project/project/branch/normal-branch-name/test/test?result-id=result');
|
|
34
|
-
expect(utils.getTestUrl('http://localhost:8080', 'project', 'test', 'result', 'branch/with/slashes'))
|
|
35
|
-
.to.equal('http://localhost:8080/#/project/project/branch/branch%2Fwith%2Fslashes/test/test?result-id=result');
|
|
36
|
-
expect(utils.getTestUrl('http://localhost:8080', 'project', 'test', 'result', 'branch with spaces'))
|
|
37
|
-
.to.equal('http://localhost:8080/#/project/project/branch/branch%20with%20spaces/test/test?result-id=result');
|
|
38
|
-
expect(utils.getTestUrl('http://localhost:8080', 'project', 'test', 'result', 'encoded%20branch'))
|
|
39
|
-
.to.equal('http://localhost:8080/#/project/project/branch/encoded%2520branch/test/test?result-id=result');
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
describe('getArgsOnRemoteRunFailure', () => {
|
|
44
|
-
let originalArgv;
|
|
45
|
-
|
|
46
|
-
beforeEach(() => {
|
|
47
|
-
originalArgv = process.argv;
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
afterEach(() => {
|
|
51
|
-
process.argv = originalArgv;
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should return undefined if no remote run is current', () => {
|
|
55
|
-
process.argv = ['node', 'file.js', '--token', 'token', '--project', 'project-id'];
|
|
56
|
-
expect(utils.getArgsOnRemoteRunFailure()).to.be.undefined;
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('should return details if remote run is current', () => {
|
|
60
|
-
process.argv = ['node', 'file.js', '--token', 'token', '--project', 'project-id', '--remoteRunId', 'remote-run-id'];
|
|
61
|
-
expect(utils.getArgsOnRemoteRunFailure()).to.eql({
|
|
62
|
-
remoteRunId: 'remote-run-id',
|
|
63
|
-
projectId: 'project-id',
|
|
64
|
-
token: 'token',
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
});
|