@testim/testim-cli 3.285.0 → 3.287.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 +32 -9
- package/agent/routers/codim/service.js +10 -7
- package/cli/writeStackTrace.js +14 -13
- package/cli.js +12 -15
- package/commons/featureFlags.js +1 -0
- package/commons/getSessionPlayerRequire.js +23 -8
- package/commons/httpRequestCounters.js +2 -2
- package/commons/initializeUserWithAuth.js +1 -1
- package/commons/testimDesiredCapabilitiesBuilder.js +6 -1
- package/npm-shrinkwrap.json +2128 -964
- package/package.json +2 -2
- package/player/appiumTestPlayer.js +8 -20
- package/player/seleniumTestPlayer.js +10 -21
- package/player/services/frameLocator.js +4 -2
- package/player/services/tabService.js +13 -14
- package/player/stepActions/apiStepAction.js +6 -8
- package/player/stepActions/baseCliJsStepAction.js +3 -6
- package/player/stepActions/baseJsStepAction.js +10 -8
- package/player/stepActions/dropFileStepAction.js +5 -3
- package/player/stepActions/evaluateExpressionStepAction.js +6 -7
- package/player/stepActions/hoverStepAction.js +1 -3
- package/player/stepActions/inputFileStepAction.js +7 -6
- package/player/stepActions/locateStepAction.js +5 -6
- package/player/stepActions/mouseStepAction.js +9 -10
- package/player/stepActions/scrollStepAction.js +5 -7
- package/player/stepActions/selectOptionStepAction.js +3 -4
- package/player/stepActions/sfdcRecordedStepAction.js +1 -1
- package/player/stepActions/sfdcStepAction.js +1 -1
- package/player/stepActions/stepAction.js +7 -2
- package/player/stepActions/textStepAction.js +4 -7
- package/player/stepActions/textValidationStepAction.js +3 -10
- package/player/stepActions/wheelStepAction.js +1 -2
- package/player/utils/eyeSdkService.js +4 -3
- package/player/utils/stepActionUtils.js +9 -4
- package/player/webdriver.js +3 -3
- package/processHandler.js +3 -2
- package/processHandler.test.js +3 -4
- package/reports/debugReporter.js +1 -1
- package/runOptions.d.ts +2 -0
- package/runOptions.js +17 -8
- package/runners/TestPlanRunner.js +1 -1
- package/stepPlayers/hybridStepPlayback.js +23 -21
- package/stepPlayers/remoteStepPlayback.js +8 -6
- package/stepPlayers/tdkHybridStepPlayback.js +20 -17
- package/workers/BaseWorker.js +7 -6
- package/workers/WorkerAppium.js +8 -6
- package/workers/WorkerSelenium.js +16 -12
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const _ = require('lodash');
|
|
4
|
-
const sessionPlayerInit = require('../commons/getSessionPlayerRequire');
|
|
5
4
|
const perfLogger = require('../commons/performance-logger');
|
|
6
5
|
const { guid } = require('../utils');
|
|
6
|
+
const { AbortError } = require('../commons/AbortError');
|
|
7
7
|
const { getArgumentsFromContext } = require('../codim/hybrid-utils');
|
|
8
|
-
const {
|
|
8
|
+
const { getSessionPlayer } = require('../commons/getSessionPlayerRequire');
|
|
9
9
|
|
|
10
10
|
module.exports.execute = async function executeTdkFunction(player, hybridFunction, context, loginData, frameManager, step, source, abortSignal) {
|
|
11
11
|
function onAbort() {
|
|
12
12
|
player.sessionPlayer.stopPlaying();
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
abortSignal.addEventListener(
|
|
15
|
+
abortSignal.addEventListener('abort', onAbort);
|
|
16
16
|
|
|
17
17
|
function getLocator(arg) {
|
|
18
18
|
if (step.parameterValues) { // tdk is all grown up and can run real locators
|
|
19
19
|
const locateStep = step.parameterValues.find(param => param.type === 'locate' && param.id === arg.locatorId);
|
|
20
|
-
return { elementLocator: locateStep.elementLocator
|
|
20
|
+
return { elementLocator: locateStep.elementLocator, id: locateStep.id, name: 'Hybrid Step Locator' };
|
|
21
21
|
}
|
|
22
22
|
if (!arg.locatedElement.shadowPath) {
|
|
23
23
|
return arg; // wat
|
|
@@ -36,6 +36,7 @@ module.exports.execute = async function executeTdkFunction(player, hybridFunctio
|
|
|
36
36
|
const baseUrl = context.config.baseUrl;
|
|
37
37
|
const userData = _.cloneDeep(context); // the context contains everything needed as userData except login data
|
|
38
38
|
userData.loginData = loginData;
|
|
39
|
+
const sessionPlayerInit = getSessionPlayer();
|
|
39
40
|
const version = sessionPlayerInit.manifestVersion || 'runner';
|
|
40
41
|
const isLocalRun = false;
|
|
41
42
|
const overrideTestConfigId = null;
|
|
@@ -52,13 +53,14 @@ module.exports.execute = async function executeTdkFunction(player, hybridFunctio
|
|
|
52
53
|
sourceCode: fn.toString(),
|
|
53
54
|
sourceName: fn.name,
|
|
54
55
|
testId,
|
|
55
|
-
resultId: guid() // we don't want to reuse the resultId of the parent for the child - we need a new resultId
|
|
56
|
+
resultId: guid(), // we don't want to reuse the resultId of the parent for the child - we need a new resultId
|
|
56
57
|
};
|
|
57
58
|
const onlyLocalReporting = typeof hybridFunction.results === 'boolean' && !hybridFunction.results;
|
|
58
59
|
try {
|
|
59
60
|
perfLogger.log('tdkHybridStepPlayback before addAllTabs');
|
|
60
61
|
if (frameManager) { // we have a frameManager we can reuse
|
|
61
|
-
player.sessionPlayer.playbackAutUtils.frameManager =
|
|
62
|
+
player.sessionPlayer.playbackAutUtils.frameManager = frameManager;
|
|
63
|
+
player.sessionPlayer.frameManager = frameManager;
|
|
62
64
|
} else {
|
|
63
65
|
// otherwise, we have to tell the session player about them tabs
|
|
64
66
|
//TODO(benji) call getEditorUrl?
|
|
@@ -73,37 +75,38 @@ module.exports.execute = async function executeTdkFunction(player, hybridFunctio
|
|
|
73
75
|
}
|
|
74
76
|
function onAbort() {
|
|
75
77
|
reject(new AbortError());
|
|
76
|
-
abortSignal.removeEventListener(
|
|
78
|
+
abortSignal.removeEventListener('abort', onAbort);
|
|
77
79
|
}
|
|
78
80
|
|
|
79
|
-
abortSignal.addEventListener(
|
|
81
|
+
abortSignal.addEventListener('abort', onAbort);
|
|
80
82
|
|
|
81
|
-
player.sessionPlayer.playTestByCode(
|
|
82
|
-
|
|
83
|
+
player.sessionPlayer.playTestByCode(
|
|
84
|
+
testId, executionId, resultId, baseUrl, userData, version, resolve, isLocalRun, overrideTestConfigId, branch, [codeTest], testName, ignoreNavigation,
|
|
85
|
+
).catch(reject);
|
|
83
86
|
});
|
|
84
87
|
perfLogger.log('tdkHybridStepPlayback after playTestByCode');
|
|
85
88
|
// testResult.status?
|
|
86
89
|
return { success: testResult.success, shouldRetry: false, resultInfo: { testId, executionId, resultId: codeTest.resultId } };
|
|
87
90
|
} catch (e) {
|
|
88
|
-
return { success: false, error: e, shouldRetry: false }
|
|
91
|
+
return { success: false, error: e, shouldRetry: false };
|
|
89
92
|
} finally {
|
|
90
|
-
abortSignal.removeEventListener(
|
|
93
|
+
abortSignal.removeEventListener('abort', onAbort);
|
|
91
94
|
}
|
|
92
95
|
};
|
|
93
96
|
|
|
94
97
|
function resolveOnTestResultAndNotAssetsUploaded(player, resolve) {
|
|
95
|
-
const { commonConstants } =
|
|
96
|
-
player.sessionPlayer.playbackManager.on(commonConstants.playback.START, ({testResult}) => {
|
|
98
|
+
const { commonConstants } = getSessionPlayer();
|
|
99
|
+
player.sessionPlayer.playbackManager.on(commonConstants.playback.START, ({ testResult }) => {
|
|
97
100
|
let runnerStatus = testResult.runnerStatus;
|
|
98
101
|
Object.defineProperty(testResult, 'runnerStatus', {
|
|
99
|
-
get() { return runnerStatus },
|
|
100
|
-
set(value) {
|
|
102
|
+
get() { return runnerStatus; },
|
|
103
|
+
set(value) {
|
|
101
104
|
runnerStatus = value;
|
|
102
105
|
if (value === 'FINISHED') {
|
|
103
106
|
// resolve as soon as the runner is finished, before assets are uploaded
|
|
104
107
|
resolve(testResult);
|
|
105
108
|
}
|
|
106
|
-
}
|
|
109
|
+
},
|
|
107
110
|
});
|
|
108
111
|
});
|
|
109
112
|
}
|
package/workers/BaseWorker.js
CHANGED
|
@@ -207,8 +207,8 @@ class BaseWorker {
|
|
|
207
207
|
return player || getBrowserRes;
|
|
208
208
|
} catch (error) {
|
|
209
209
|
const grid = { provider: gridInfo.provider, host: gridInfo.host, failedGetBrowserAttempts, id: this.options.gridData.gridId, type: gridInfo.type };
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
const instanceType = this.options.mode === CLI_MODE.APPIUM ? 'device' : 'browser';
|
|
211
|
+
logger.error(`error getting ${instanceType} from grid`, { error, testId: this.testId, testResultId: this.testResultId, executionId: this.executionId, grid });
|
|
212
212
|
reporter.onGetBrowserFailure(this.id, projectId, ++failedGetBrowserAttempts);
|
|
213
213
|
player.onDone();
|
|
214
214
|
|
|
@@ -333,6 +333,7 @@ class BaseWorker {
|
|
|
333
333
|
* @param {boolean} wasNetworkHealthy
|
|
334
334
|
*/
|
|
335
335
|
const buildError = (err, wasNetworkHealthy) => {
|
|
336
|
+
const instanceType = this.options.mode === CLI_MODE.APPIUM ? 'device' : 'browser';
|
|
336
337
|
if (!wasNetworkHealthy && featureFlags.flags.errorMessageOnBadNetwork.isEnabled()) {
|
|
337
338
|
return {
|
|
338
339
|
errorType: NETWORK_ERROR,
|
|
@@ -342,7 +343,7 @@ class BaseWorker {
|
|
|
342
343
|
|
|
343
344
|
const msg = err instanceof Error ? err.message : err;
|
|
344
345
|
if (msg.includes(GET_BROWSER_TIMEOUT_MSG)) {
|
|
345
|
-
return { errorType: SETUP_TIMEOUT, reason:
|
|
346
|
+
return { errorType: SETUP_TIMEOUT, reason: `Test couldn't get ${instanceType}` };
|
|
346
347
|
}
|
|
347
348
|
if (msg.includes(TEST_START_TIMEOUT_MSG)) {
|
|
348
349
|
return { errorType: SETUP_TIMEOUT, reason: "Test couldn't be started" };
|
|
@@ -361,7 +362,7 @@ class BaseWorker {
|
|
|
361
362
|
|
|
362
363
|
if (err instanceof GetBrowserError && err.type) {
|
|
363
364
|
if (err.type === GRID_ERROR) {
|
|
364
|
-
return { errorType: GRID_ERROR, reason: `Test couldn't get
|
|
365
|
+
return { errorType: GRID_ERROR, reason: `Test couldn't get ${instanceType} from grid - ${err.message}` };
|
|
365
366
|
}
|
|
366
367
|
if (err.type === SELENIUM_ERROR) {
|
|
367
368
|
return { errorType: SELENIUM_ERROR, reason: `Failed to create new session - ${err.message}` };
|
|
@@ -372,7 +373,7 @@ class BaseWorker {
|
|
|
372
373
|
return { errorType: SELENIUM_ERROR, reason: 'Session terminated, it is possible that the cli could not connect to the grid to send keep-alive requests for a prolonged period' };
|
|
373
374
|
}
|
|
374
375
|
if (err.failure && err.failure instanceof SeleniumError) {
|
|
375
|
-
return { errorType: SELENIUM_ERROR, reason: `Test couldn't get
|
|
376
|
+
return { errorType: SELENIUM_ERROR, reason: `Test couldn't get ${instanceType} from grid - ${err.failure.message}` };
|
|
376
377
|
}
|
|
377
378
|
if (/SeleniumError: connect ECONNREFUSED/.test(err.message) || /Couldn't connect to selenium server/.test(err.message)) {
|
|
378
379
|
return { errorType: SELENIUM_ERROR, reason: 'Failed to connect to the grid, please check if the grid is accessible from your network' };
|
|
@@ -384,7 +385,7 @@ class BaseWorker {
|
|
|
384
385
|
return { errorType: SELENIUM_ERROR, reason: 'Session terminated, it is likely that the grid is not responding, please try to rerun the test' };
|
|
385
386
|
}
|
|
386
387
|
if (/forwarding the new session cannot find : Capabilities/.test(err.message)) {
|
|
387
|
-
return { errorType: SELENIUM_ERROR, reason:
|
|
388
|
+
return { errorType: SELENIUM_ERROR, reason: `Session could not be created, please check that the ${instanceType} you requested is supported in your plan` };
|
|
388
389
|
}
|
|
389
390
|
return { errorType: UNKNOWN_ERROR, reason: msg };
|
|
390
391
|
};
|
package/workers/WorkerAppium.js
CHANGED
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
const jsdom = require('jsdom');
|
|
4
4
|
const BaseWorker = require('./BaseWorker');
|
|
5
|
-
const
|
|
5
|
+
const config = require('../commons/config');
|
|
6
6
|
const reporter = require('../reports/reporter');
|
|
7
7
|
const AppiumTestPlayer = require('../player/appiumTestPlayer');
|
|
8
|
-
const sessionPlayerInit = require('../commons/getSessionPlayerRequire');
|
|
9
|
-
const AppiumApi = require('../commons/getSessionPlayerRequire').AppiumApi;
|
|
10
|
-
const desiredCapabilitiesBuilder = require('../commons/testimDesiredCapabilitiesBuilder');
|
|
11
8
|
const testimServicesApi = require('../commons/testimServicesApi');
|
|
12
|
-
const
|
|
9
|
+
const desiredCapabilitiesBuilder = require('../commons/testimDesiredCapabilitiesBuilder');
|
|
10
|
+
const { getSessionPlayer } = require('../commons/getSessionPlayerRequire');
|
|
11
|
+
const { getLogger } = require('../commons/logger');
|
|
12
|
+
|
|
13
|
+
const logger = getLogger('worker-appium');
|
|
13
14
|
|
|
14
15
|
class WorkerAppium extends BaseWorker {
|
|
15
16
|
/**
|
|
@@ -113,6 +114,7 @@ class WorkerAppium extends BaseWorker {
|
|
|
113
114
|
* @param {import('../player/appiumTestPlayer')} appiumTestPlayer
|
|
114
115
|
*/
|
|
115
116
|
async runTestOnce(testRunHandler, appiumTestPlayer) {
|
|
117
|
+
const sessionPlayerInit = getSessionPlayer();
|
|
116
118
|
const { driver, sessionPlayer } = appiumTestPlayer;
|
|
117
119
|
const version = sessionPlayerInit.manifestVersion || 'runner';
|
|
118
120
|
|
|
@@ -123,7 +125,7 @@ class WorkerAppium extends BaseWorker {
|
|
|
123
125
|
|
|
124
126
|
const serverAddress = this.getDirectAddressConnection(driver.activeSession.capabilities) || this.getServerAddressFromGrid(testRunHandler);
|
|
125
127
|
const DOMParser = new jsdom.JSDOM('').window.DOMParser;
|
|
126
|
-
sessionPlayer.playbackManager.appiumApi = new AppiumApi(serverAddress, driver.activeSession.sessionId, DOMParser);
|
|
128
|
+
sessionPlayer.playbackManager.appiumApi = new sessionPlayerInit.AppiumApi(serverAddress, driver.activeSession.sessionId, DOMParser);
|
|
127
129
|
if (sessionPlayerInit.localAssetService) {
|
|
128
130
|
sessionPlayerInit.localAssetService.initialize({ serverUrl: this.options.localRCASaver });
|
|
129
131
|
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const utils = require('../utils');
|
|
3
4
|
const BaseWorker = require('./BaseWorker');
|
|
4
|
-
const logger = require('../commons/logger').getLogger('worker-selenium');
|
|
5
5
|
const reporter = require('../reports/reporter');
|
|
6
|
-
const SeleniumTestPlayer = require('../player/seleniumTestPlayer');
|
|
7
|
-
const WindowUtils = require('../player/utils/windowUtils');
|
|
8
|
-
const sessionPlayerInit = require('../commons/getSessionPlayerRequire');
|
|
9
6
|
const perf = require('../commons/performance-logger');
|
|
10
|
-
const
|
|
11
|
-
const
|
|
7
|
+
const WindowUtils = require('../player/utils/windowUtils');
|
|
8
|
+
const SeleniumTestPlayer = require('../player/seleniumTestPlayer');
|
|
9
|
+
const { getLogger } = require('../commons/logger');
|
|
12
10
|
const { PageNotAvailableError } = require('../errors');
|
|
13
11
|
const { preloadTests } = require('../commons/preloadTests');
|
|
12
|
+
const { timeoutMessages } = require('../commons/constants');
|
|
13
|
+
const { getSessionPlayer } = require('../commons/getSessionPlayerRequire');
|
|
14
|
+
|
|
15
|
+
const logger = getLogger('worker-selenium');
|
|
14
16
|
|
|
15
17
|
// this navigation timeout is handled from outside the worker, so don't pass a small timeout to navigate
|
|
16
18
|
const NO_NAVIGATION_TIME_LIMIT = 1e9;
|
|
@@ -62,7 +64,7 @@ class WorkerSelenium extends BaseWorker {
|
|
|
62
64
|
this.testResultId,
|
|
63
65
|
testRunHandler.seleniumPerfStats,
|
|
64
66
|
fastInit,
|
|
65
|
-
this.lambdatestService
|
|
67
|
+
this.lambdatestService,
|
|
66
68
|
);
|
|
67
69
|
perf.log('in WorkerSelenium after driver.init');
|
|
68
70
|
await seleniumTestPlayer.addTab(undefined, { skipLoadInfo: fastInit });
|
|
@@ -93,7 +95,9 @@ class WorkerSelenium extends BaseWorker {
|
|
|
93
95
|
* @param {import('../player/seleniumTestPlayer')} seleniumTestPlayer
|
|
94
96
|
*/
|
|
95
97
|
async runTestOnce(testRunHandler, seleniumTestPlayer) {
|
|
98
|
+
const sessionPlayerInit = getSessionPlayer();
|
|
96
99
|
const { driver, sessionPlayer } = seleniumTestPlayer;
|
|
100
|
+
|
|
97
101
|
const version = sessionPlayerInit.manifestVersion || 'runner';
|
|
98
102
|
|
|
99
103
|
reporter.onWaitToTestComplete(this.id, this.isCodeMode);
|
|
@@ -126,7 +130,7 @@ class WorkerSelenium extends BaseWorker {
|
|
|
126
130
|
sessionPlayer.callOrderScheduler.schedule(
|
|
127
131
|
() => testRunHandler.waitForExecutionStartedFinished(),
|
|
128
132
|
// this key is shared by clickim and this ensures that we do wait for the execution to be created before we do this.
|
|
129
|
-
{ key: `test-result:${this.userData.projectId}:${this.testResultId}` }
|
|
133
|
+
{ key: `test-result:${this.userData.projectId}:${this.testResultId}` },
|
|
130
134
|
);
|
|
131
135
|
}
|
|
132
136
|
perf.log('right before playTestByCode');
|
|
@@ -144,7 +148,7 @@ class WorkerSelenium extends BaseWorker {
|
|
|
144
148
|
this.overrideTestConfigId,
|
|
145
149
|
this.branch,
|
|
146
150
|
testRunHandler.code,
|
|
147
|
-
testRunHandler.testName
|
|
151
|
+
testRunHandler.testName,
|
|
148
152
|
).catch(reject);
|
|
149
153
|
});
|
|
150
154
|
return utils
|
|
@@ -154,7 +158,7 @@ class WorkerSelenium extends BaseWorker {
|
|
|
154
158
|
return testResult;
|
|
155
159
|
}),
|
|
156
160
|
this.testRunTimeout,
|
|
157
|
-
timeoutMessages.TEST_COMPLETE_TIMEOUT_MSG
|
|
161
|
+
timeoutMessages.TEST_COMPLETE_TIMEOUT_MSG,
|
|
158
162
|
)
|
|
159
163
|
.catch(err => {
|
|
160
164
|
if (err instanceof utils.TimeoutError) {
|
|
@@ -187,7 +191,7 @@ class WorkerSelenium extends BaseWorker {
|
|
|
187
191
|
testRunHandler.remoteRunId,
|
|
188
192
|
undefined,
|
|
189
193
|
undefined,
|
|
190
|
-
preloadedTest
|
|
194
|
+
preloadedTest,
|
|
191
195
|
).catch(reject);
|
|
192
196
|
}),
|
|
193
197
|
this.testRunTimeout,
|
|
@@ -238,7 +242,7 @@ class WorkerSelenium extends BaseWorker {
|
|
|
238
242
|
}
|
|
239
243
|
}
|
|
240
244
|
function setupCliPerformanceMonitoring(sessionPlayer) {
|
|
241
|
-
const { playback } =
|
|
245
|
+
const { playback } = getSessionPlayer().commonConstants;
|
|
242
246
|
function monitorEvent(event) {
|
|
243
247
|
sessionPlayer.playbackManager.on(event, () => {
|
|
244
248
|
perf.log(`Got event ${event}`);
|