@testim/testim-cli 3.261.0 → 3.262.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/commons/testimServicesApi.js +10 -7
- package/executionQueue.js +9 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/player/stepActions/RefreshStepAction.js +7 -4
- package/player/stepActions/baseJsStepAction.js +45 -46
- package/player/stepActions/dropFileStepAction.js +11 -12
- package/player/stepActions/evaluateExpressionStepAction.js +32 -33
- package/player/stepActions/extensionOnlyStepAction.js +3 -4
- package/player/stepActions/extractTextStepAction.js +8 -10
- package/player/stepActions/hoverStepAction.js +3 -3
- package/player/stepActions/locateStepAction.js +39 -34
- package/player/stepActions/mouseStepAction.js +36 -34
- package/player/stepActions/navigationStepAction.js +7 -8
- package/player/stepActions/scrollStepAction.js +22 -22
- package/player/stepActions/stepAction.js +21 -21
- package/player/stepActions/stepActionRegistrar.js +63 -58
- package/player/stepActions/submitStepAction.js +2 -3
- package/player/stepActions/textStepAction.js +14 -14
- package/player/stepActions/textValidationStepAction.js +50 -38
- package/player/stepActions/wheelStepAction.js +5 -11
- package/processHandler.js +2 -0
- package/reports/junitReporter.js +18 -1
- package/runOptions.d.ts +4 -0
- package/runOptions.js +8 -1
- package/runners/TestPlanRunner.js +20 -19
- package/runners/runnerUtils.js +1 -2
- package/testRunHandler.js +18 -9
- package/testRunStatus.js +205 -157
- package/workers/BaseWorker.js +11 -0
- package/workers/WorkerExtension.js +117 -91
- package/workers/WorkerSelenium.js +8 -3
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const Promise = require('bluebird');
|
|
4
|
-
|
|
5
|
-
const { timeoutMessages, stepResult } = require('../commons/constants');
|
|
6
3
|
const BaseWorker = require('./BaseWorker');
|
|
7
|
-
const
|
|
4
|
+
const reporter = require('../reports/reporter');
|
|
8
5
|
const perf = require('../commons/performance-logger');
|
|
9
6
|
const ExtensionTestPlayer = require('../player/extensionTestPlayer');
|
|
10
7
|
const ChromeLauncherTestPlayer = require('../player/chromeLauncherTestPlayer');
|
|
11
|
-
const
|
|
8
|
+
const { TimeoutError } = require('../errors');
|
|
9
|
+
const { promiseTimeout } = require('../utils');
|
|
10
|
+
const { getLogger } = require('../commons/logger');
|
|
11
|
+
const { timeoutMessages, stepResult } = require('../commons/constants');
|
|
12
12
|
|
|
13
|
+
const logger = getLogger('worker-ext');
|
|
13
14
|
|
|
14
15
|
class WorkerExtension extends BaseWorker {
|
|
16
|
+
/** @override */
|
|
15
17
|
initPlayer() {
|
|
16
18
|
if (this.options.useChromeLauncher) {
|
|
17
19
|
return new ChromeLauncherTestPlayer(this.id);
|
|
@@ -31,7 +33,7 @@ class WorkerExtension extends BaseWorker {
|
|
|
31
33
|
this.executionId,
|
|
32
34
|
this.testResultId,
|
|
33
35
|
testRunHandler.seleniumPerfStats,
|
|
34
|
-
this.options.lightweightMode
|
|
36
|
+
this.options.lightweightMode?.general,
|
|
35
37
|
this.lambdatestService
|
|
36
38
|
);
|
|
37
39
|
} catch (err) {
|
|
@@ -45,115 +47,139 @@ class WorkerExtension extends BaseWorker {
|
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
/** @override */
|
|
48
51
|
async getBrowserOnce(testRunHandler, customExtensionLocalLocation, player, gridInfo) {
|
|
49
52
|
reporter.onGetSession(this.id, this.testName, testRunHandler.getRunMode());
|
|
50
53
|
return this._getBrowserOnce(testRunHandler, customExtensionLocalLocation, player, gridInfo);
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
/**
|
|
57
|
+
* @override
|
|
58
|
+
* @param {import('../testRunHandler')} testRunHandler
|
|
59
|
+
* @param {import('../player/extensionTestPlayer') | import('../player/chromeLauncherTestPlayer')} player
|
|
60
|
+
*/
|
|
61
|
+
async runTestOnce(testRunHandler, player) {
|
|
54
62
|
const { driver } = player;
|
|
55
63
|
const { testResultId, executionId, testId } = this;
|
|
56
64
|
perf.log('WorkerExtension runTestOnce');
|
|
57
65
|
|
|
58
|
-
const
|
|
66
|
+
const runViaCdpOrFallbackToAPI = async () => {
|
|
67
|
+
const testTimeout = this.options.timeoutWasGiven ? Math.max(10000, this.options.timeout) : this.options.testStartTimeout;
|
|
68
|
+
try {
|
|
69
|
+
return await promiseTimeout(testRunHandler.runTestUsingCDP(driver.cdpTestRunner), testTimeout, timeoutMessages.TEST_START_TIMEOUT_MSG);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
if (!(err instanceof TimeoutError)) {
|
|
72
|
+
throw err;
|
|
73
|
+
}
|
|
74
|
+
logger.warn('timeout while running test using CDP. Running checkViaRestAPIIfTestStarted', { testResultId });
|
|
75
|
+
return await testRunHandler.checkViaRestAPIIfTestStarted();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const navigateChromeSessionToRunTestim = async (url, startStatusDetails) => {
|
|
79
|
+
try {
|
|
80
|
+
const res = await driver.url(url);
|
|
81
|
+
startStatusDetails.driverUrlFinished = true;
|
|
82
|
+
return res;
|
|
83
|
+
} catch (err) {
|
|
84
|
+
logger.error('error from driver.url', { err, testResultId, executionId, testId, url, urlLength: url.length });
|
|
85
|
+
throw err;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const updateRunHandlerThatTestStartedAndChangeStatusDetails = async (startStatusDetails) => {
|
|
89
|
+
const res = await testRunHandler.onStarted(this.options.testStartTimeout);
|
|
90
|
+
startStatusDetails.testRunHandlerOnStartedHadFinished = true;
|
|
91
|
+
return res;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const runExtTest = async () => {
|
|
59
95
|
perf.log('WorkerExtension runExtTest');
|
|
60
|
-
const disableRemoteStep =
|
|
96
|
+
const disableRemoteStep = this.options.lightweightMode?.disableRemoteStep || this.options.disableSockets;
|
|
61
97
|
if (!disableRemoteStep) {
|
|
62
98
|
testRunHandler.listenToRemoteStep(driver);
|
|
63
99
|
}
|
|
64
100
|
if (this.options.useChromeLauncher) {
|
|
65
|
-
const testTimeout = this.options.timeoutWasGiven ?
|
|
66
|
-
Math.max(10000, this.options.timeout) :
|
|
67
|
-
this.options.testStartTimeout;
|
|
68
|
-
|
|
69
101
|
reporter.onWaitToTestStart(this.id);
|
|
70
102
|
reporter.onWaitToTestComplete(this.id, this.isCodeMode);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
.catch(err => {
|
|
79
|
-
logger.warn('failed to run test via CDP', { err });
|
|
80
|
-
throw err;
|
|
81
|
-
});
|
|
103
|
+
try {
|
|
104
|
+
const testResult = await runViaCdpOrFallbackToAPI();
|
|
105
|
+
return { ...testResult, ...testRunHandler.seleniumPerfStats.getStats() };
|
|
106
|
+
} catch (err) {
|
|
107
|
+
logger.warn('failed to run test via CDP', { err });
|
|
108
|
+
throw err;
|
|
109
|
+
}
|
|
82
110
|
}
|
|
83
111
|
|
|
84
112
|
const startStatusDetails = { driverUrlFinished: false, testRunHandlerOnStartedHadFinished: false }; //for logging / debugging purposes
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
logger.warn('failed to start url', { err });
|
|
140
|
-
reject(new Error(err));
|
|
141
|
-
}));
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const url = await testRunHandler.getRunTestUrl();
|
|
116
|
+
reporter.onWaitToTestStart(this.id);
|
|
117
|
+
try {
|
|
118
|
+
await promiseTimeout(Promise.all([
|
|
119
|
+
navigateChromeSessionToRunTestim(url, startStatusDetails),
|
|
120
|
+
updateRunHandlerThatTestStartedAndChangeStatusDetails(startStatusDetails),
|
|
121
|
+
]), this.options.testStartTimeout, timeoutMessages.TEST_START_TIMEOUT_MSG);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
if (!(err instanceof TimeoutError)) {
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
logger.warn('timeout occurred (see log\'s payload). Running checkViaRestAPIIfTestStarted', { testResultId, executionId, testId, ...startStatusDetails });
|
|
127
|
+
await testRunHandler.checkViaRestAPIIfTestStarted();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
reporter.onWaitToTestComplete(this.id, this.isCodeMode);
|
|
131
|
+
const onBrowserClosed = (err) => {
|
|
132
|
+
testRunHandler.onCompletedCleanup();
|
|
133
|
+
logger.warn('on browser closed error detected', { err, testResultId, executionId, testId });
|
|
134
|
+
driver.unregisterToClosedBrowser(onBrowserClosed);
|
|
135
|
+
err.type = stepResult.BROWSER_CLOSED;
|
|
136
|
+
throw err;
|
|
137
|
+
};
|
|
138
|
+
driver.registerToClosedBrowser(onBrowserClosed);
|
|
139
|
+
try {
|
|
140
|
+
const testResult = await promiseTimeout(testRunHandler.onCompleted(), this.testRunTimeout, timeoutMessages.TEST_COMPLETE_TIMEOUT_MSG);
|
|
141
|
+
driver.unregisterToClosedBrowser(onBrowserClosed);
|
|
142
|
+
if (this.lambdatestService.isLambdatestRun()) {
|
|
143
|
+
await driver.executeJS(`lambda-status=${!testResult.success ? 'failed' : 'passed'}`).catch(() => { });
|
|
144
|
+
}
|
|
145
|
+
if (!driver.isAlive()) {
|
|
146
|
+
logger.warn(`possible grid unresponsive for test ${this.testId}, result ${this.testResultId} (execution: ${this.executionId})`);
|
|
147
|
+
testResult.gridIssues = 'could not validate grid is alive';
|
|
148
|
+
}
|
|
149
|
+
const maxKeepAliveGap = driver.maxKeepAliveGap();
|
|
150
|
+
const MAX_KEEP_ALIVE_GAP = 30000;
|
|
151
|
+
if (maxKeepAliveGap >= MAX_KEEP_ALIVE_GAP) {
|
|
152
|
+
logger.warn(`possible browser keep alive issue ${this.testId}, result ${this.testResultId} (execution: ${this.executionId})`);
|
|
153
|
+
testResult.keepAliveIssue = maxKeepAliveGap;
|
|
154
|
+
}
|
|
155
|
+
return { ...testResult, ...testRunHandler.seleniumPerfStats.getStats() };
|
|
156
|
+
} catch (err) {
|
|
157
|
+
logger.warn('timeout wait until test completed', { err, testResultId, executionId, testId });
|
|
158
|
+
// complete time out
|
|
159
|
+
throw new Error(err);
|
|
160
|
+
} finally {
|
|
161
|
+
driver.unregisterToClosedBrowser(onBrowserClosed);
|
|
162
|
+
}
|
|
163
|
+
} catch (err) {
|
|
164
|
+
logger.warn('failed to start url', { err });
|
|
165
|
+
throw new Error(err);
|
|
166
|
+
}
|
|
142
167
|
};
|
|
143
168
|
|
|
144
169
|
driver.start();
|
|
145
170
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return Promise.reject(err);
|
|
171
|
+
try {
|
|
172
|
+
await super.runTestOnce(testRunHandler, player);
|
|
173
|
+
perf.log('WorkerExtension super.runTestOnce');
|
|
174
|
+
return await runExtTest();
|
|
175
|
+
} catch (err) {
|
|
176
|
+
logger.error('failed to run test', {
|
|
177
|
+
err,
|
|
178
|
+
testId: testRunHandler.getTestId(),
|
|
179
|
+
resultId: testRunHandler.getTestResultId(),
|
|
156
180
|
});
|
|
181
|
+
throw err;
|
|
182
|
+
}
|
|
157
183
|
}
|
|
158
184
|
}
|
|
159
185
|
|
|
@@ -80,6 +80,10 @@ class WorkerSelenium extends BaseWorker {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* @param {import('../testRunHandler')} testRunHandler
|
|
85
|
+
* @param {import('../player/seleniumTestPlayer')} seleniumTestPlayer
|
|
86
|
+
*/
|
|
83
87
|
async runTestOnce(testRunHandler, seleniumTestPlayer) {
|
|
84
88
|
const { driver, sessionPlayer } = seleniumTestPlayer;
|
|
85
89
|
const version = sessionPlayerInit.manifestVersion || 'runner';
|
|
@@ -111,10 +115,11 @@ class WorkerSelenium extends BaseWorker {
|
|
|
111
115
|
if (!sessionPlayer.callOrderScheduler) { // old session player
|
|
112
116
|
await testRunHandler.waitForExecutionStartedFinished();
|
|
113
117
|
} else {
|
|
114
|
-
sessionPlayer.callOrderScheduler.schedule(
|
|
118
|
+
sessionPlayer.callOrderScheduler.schedule(
|
|
119
|
+
() => testRunHandler.waitForExecutionStartedFinished(),
|
|
115
120
|
// this key is shared by clickim and this ensures that we do wait for the execution to be created before we do this.
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
{ key: `test-result:${this.userData.projectId}:${this.testResultId}` }
|
|
122
|
+
);
|
|
118
123
|
}
|
|
119
124
|
perf.log('right before playTestByCode');
|
|
120
125
|
return new Promise((resolve, reject) => sessionPlayer.playTestByCode(
|