@testim/testim-cli 3.236.0 → 3.237.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/executionQueue.js +4 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/player/webdriver.js +9 -8
- package/runOptions.js +18 -0
- package/runners/ParallelWorkerManager.js +14 -5
- package/runners/TestPlanRunner.js +2 -2
package/executionQueue.js
CHANGED
|
@@ -7,6 +7,10 @@ class ExecutionQueue {
|
|
|
7
7
|
this._waitingTests = testList.map(testInfo => new TestRun(executionId, executionName, testInfo, options, branchToUse, testStatus));
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
stop() {
|
|
11
|
+
this._waitingTests = [];
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
getNext() {
|
|
11
15
|
const nextTestRunHandler = this._waitingTests.shift();
|
|
12
16
|
if (nextTestRunHandler) {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testim/testim-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.237.0",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@testim/testim-cli",
|
|
9
|
-
"version": "3.
|
|
9
|
+
"version": "3.237.0",
|
|
10
10
|
"license": "Proprietary",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@applitools/eyes-sdk-core": "13.2.0",
|
package/package.json
CHANGED
package/player/webdriver.js
CHANGED
|
@@ -332,7 +332,7 @@ class WebDriver extends WebDriverApi {
|
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
getElementTextJS(locatedElement) {
|
|
335
|
-
function extractTextCode(locatedElement) {
|
|
335
|
+
function extractTextCode(locatedElement, ignoreHiddenTagsText) {
|
|
336
336
|
// copy of utils.getElementTextContent to run inside content script
|
|
337
337
|
// sadly .children doesn't work for SVG elements in IE11
|
|
338
338
|
function clearTitleTags(node) {
|
|
@@ -362,14 +362,15 @@ class WebDriver extends WebDriverApi {
|
|
|
362
362
|
return element.shadowRoot.textContent.replace(/(\r\n|\n|\r)/gm, "");
|
|
363
363
|
}
|
|
364
364
|
} catch (err) { }
|
|
365
|
-
if (
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
hiddenChildren.forEach(child
|
|
365
|
+
if (ignoreHiddenTagsText && Array.prototype.some.call(element.children, function (elem) { return elem.hidden; })) {
|
|
366
|
+
var dupElement = element.cloneNode(true);
|
|
367
|
+
var hiddenChildren = Array.prototype.filter.call(dupElement.children, function (elem) { return elem.hidden; });
|
|
368
|
+
hiddenChildren.forEach(function (child) {
|
|
369
369
|
dupElement.removeChild(child);
|
|
370
370
|
});
|
|
371
|
-
return dupElement.textContent.replace(/(\r\n|\n|\r)/gm,
|
|
372
|
-
}
|
|
371
|
+
return dupElement.textContent.replace(/(\r\n|\n|\r)/gm, '');
|
|
372
|
+
}
|
|
373
|
+
return element.textContent.replace(/(\r\n|\n|\r)/gm, '');
|
|
373
374
|
}
|
|
374
375
|
|
|
375
376
|
function getElementTextContent(element) {
|
|
@@ -399,7 +400,7 @@ class WebDriver extends WebDriverApi {
|
|
|
399
400
|
var getLocatedElement = ${codeSnippets().getLocatedElementCode};
|
|
400
401
|
var extractText = ${extractTextCode.toString()};
|
|
401
402
|
return extractText.apply(null, arguments)
|
|
402
|
-
`, locatedElement)
|
|
403
|
+
`, locatedElement, this.ignoreHiddenTagsText)
|
|
403
404
|
.then(result => result.value);
|
|
404
405
|
}
|
|
405
406
|
|
package/runOptions.js
CHANGED
|
@@ -187,6 +187,8 @@ program
|
|
|
187
187
|
.option('--token [token]', 'identification token to testim')
|
|
188
188
|
.option('--is-regression-baseline-run', 'save doms and run results as regression baseline data')
|
|
189
189
|
.option('--parallel [number-of-tests]', 'number of tests to run on parallel')
|
|
190
|
+
.option('--before-parallel [number-of-tests]', 'number of tests to run on parallel in the before phase of a test plan')
|
|
191
|
+
.option('--after-parallel [number-of-tests]', 'number of tests to run on parallel in the after phase of a test plan')
|
|
190
192
|
.option('--canary [canary-mode]', 'enable canary mode', false)
|
|
191
193
|
.option('--test-plan [test-plan-name]', 'test plan to run', collect, [])
|
|
192
194
|
.option('--test-plan-id [test-plan-id]', 'test plan to run', collect, [])
|
|
@@ -762,7 +764,9 @@ module.exports = {
|
|
|
762
764
|
|
|
763
765
|
const timeoutWasGiven = Boolean(program.timeout);
|
|
764
766
|
program.timeout = !program.timeout || typeof program.timeout === 'boolean' ? 10 * 60 * 1000 : Number(program.timeout);
|
|
767
|
+
program.beforeParallel = !program.beforeParallel || typeof program.beforeParallel === 'boolean' ? 1 : Number(program.beforeParallel);
|
|
765
768
|
program.parallel = !program.parallel || typeof program.parallel === 'boolean' ? 1 : Number(program.parallel);
|
|
769
|
+
program.afterParallel = !program.afterParallel || typeof program.afterParallel === 'boolean' ? 1 : Number(program.afterParallel);
|
|
766
770
|
|
|
767
771
|
|
|
768
772
|
if (program.parallel > 1 && program.run && !program.gridId && !program.grid &&
|
|
@@ -817,10 +821,18 @@ module.exports = {
|
|
|
817
821
|
throw new ArgError('test run timeout could not be a negative number, --timeout <run-timeout>');
|
|
818
822
|
}
|
|
819
823
|
|
|
824
|
+
if (program.beforeParallel <= 0 || _.isNaN(program.beforeParallel)) {
|
|
825
|
+
throw new ArgError('before-parallel could not be a negative number or not number, --before-parallel <number-of-tests>');
|
|
826
|
+
}
|
|
827
|
+
|
|
820
828
|
if (program.parallel <= 0 || _.isNaN(program.parallel)) {
|
|
821
829
|
throw new ArgError('parallel could not be a negative number or not number, --parallel <number-of-tests>');
|
|
822
830
|
}
|
|
823
831
|
|
|
832
|
+
if (program.afterParallel <= 0 || _.isNaN(program.afterParallel)) {
|
|
833
|
+
throw new ArgError('after-parallel could not be a negative number or not number, --after-parallel <number-of-tests>');
|
|
834
|
+
}
|
|
835
|
+
|
|
824
836
|
if (![CLI_MODE.EXTENSION, CLI_MODE.SELENIUM].includes(program.mode)) {
|
|
825
837
|
throw new ArgError(`runner mode <${program.mode}> is not supported`);
|
|
826
838
|
}
|
|
@@ -866,6 +878,10 @@ module.exports = {
|
|
|
866
878
|
);
|
|
867
879
|
}
|
|
868
880
|
|
|
881
|
+
if (!isTestPlanSpecified && (program.beforeParallel !== 1 || program.afterParallel !== 1)) {
|
|
882
|
+
throw new ArgError('cannot set --before-parallel or --after-parallel without --test-plan option');
|
|
883
|
+
}
|
|
884
|
+
|
|
869
885
|
if (
|
|
870
886
|
(program.testId.length ||
|
|
871
887
|
isTestPlanSpecified ||
|
|
@@ -1089,7 +1105,9 @@ module.exports = {
|
|
|
1089
1105
|
mode: program.mode,
|
|
1090
1106
|
isRegressionBaselineRun: program.isRegressionBaselineRun,
|
|
1091
1107
|
browser: program.browser,
|
|
1108
|
+
beforeParallel: program.beforeParallel,
|
|
1092
1109
|
parallel: program.parallel,
|
|
1110
|
+
afterParallel: program.afterParallel,
|
|
1093
1111
|
canary: program.canary,
|
|
1094
1112
|
rerunFailedByRunId: program.rerunFailedByRunId,
|
|
1095
1113
|
disableGridCheck: program.disableGridCheck,
|
|
@@ -50,6 +50,8 @@ class ParallelWorkerManager {
|
|
|
50
50
|
return undefined;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
let stoppedOnError = false;
|
|
54
|
+
let runningTests = 0;
|
|
53
55
|
const runAndWaitToComplete = token => new Promise((resolve, reject) => {
|
|
54
56
|
const projectId = options.project;
|
|
55
57
|
const executionQueue = new ExecutionQueue(executionId, executionName, testList, options, branchToUse, testStatus);
|
|
@@ -68,6 +70,7 @@ class ParallelWorkerManager {
|
|
|
68
70
|
const sessionType = utils.getSessionType(options);
|
|
69
71
|
|
|
70
72
|
const onTestStarted = (wid, testId, resultId, isRerun, testRetryKey) => {
|
|
73
|
+
runningTests++;
|
|
71
74
|
analyticsService.analyticsTestStart({
|
|
72
75
|
authData,
|
|
73
76
|
executionId,
|
|
@@ -150,11 +153,12 @@ class ParallelWorkerManager {
|
|
|
150
153
|
isStartUp,
|
|
151
154
|
});
|
|
152
155
|
if (stopOnError && !testResult.success) {
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
executionQueue.stop();
|
|
157
|
+
stoppedOnError = true;
|
|
155
158
|
}
|
|
159
|
+
runningTests--;
|
|
156
160
|
const completedTests = Object.keys(combinedTestResults).length;
|
|
157
|
-
if (completedTests === testCount) {
|
|
161
|
+
if (completedTests === testCount || (stopOnError && runningTests === 0)) {
|
|
158
162
|
resolve(combinedTestResults);
|
|
159
163
|
return undefined;
|
|
160
164
|
}
|
|
@@ -164,8 +168,9 @@ class ParallelWorkerManager {
|
|
|
164
168
|
const onTestIgnored = (wid, testResult) => {
|
|
165
169
|
combinedTestResults[testResult.resultId] = testResult;
|
|
166
170
|
testStatus.onTestIgnored(wid, testResult.resultId);
|
|
171
|
+
runningTests--;
|
|
167
172
|
const completedTests = Object.keys(combinedTestResults).length;
|
|
168
|
-
if (completedTests === testCount) {
|
|
173
|
+
if (completedTests === testCount || (stopOnError && runningTests === 0)) {
|
|
169
174
|
resolve(combinedTestResults);
|
|
170
175
|
}
|
|
171
176
|
};
|
|
@@ -195,7 +200,11 @@ class ParallelWorkerManager {
|
|
|
195
200
|
|
|
196
201
|
try {
|
|
197
202
|
const token = await testimCustomToken.getCustomTokenV3();
|
|
198
|
-
|
|
203
|
+
const result = await runAndWaitToComplete(token);
|
|
204
|
+
if (stoppedOnError) {
|
|
205
|
+
throw new StopRunOnError();
|
|
206
|
+
}
|
|
207
|
+
return result;
|
|
199
208
|
} catch (err) {
|
|
200
209
|
logger.error('failed running parallel workers', { executionId, err });
|
|
201
210
|
throw err;
|
|
@@ -35,7 +35,7 @@ class TestPlanRunner {
|
|
|
35
35
|
const authData = testimCustomToken.getTokenV3UserData();
|
|
36
36
|
|
|
37
37
|
const runBeforeTests = () => {
|
|
38
|
-
const workerCount = 1;
|
|
38
|
+
const workerCount = tpOptions.beforeParallel || 1;
|
|
39
39
|
const stopOnError = true;
|
|
40
40
|
return this.workerManager.runTests(beforeTests, testStatus, executionId, executionName, tpOptions, branchToUse, authData, workerCount, stopOnError)
|
|
41
41
|
.then(beforeTestsResults => Object.assign(executionResults, beforeTestsResults));
|
|
@@ -51,7 +51,7 @@ class TestPlanRunner {
|
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
const runAfterTests = () => {
|
|
54
|
-
const workerCount = 1;
|
|
54
|
+
const workerCount = tpOptions.afterParallel || 1;
|
|
55
55
|
const stopOnError = false;
|
|
56
56
|
return this.workerManager.runTests(afterTests, testStatus, executionId, executionName, tpOptions, branchToUse, authData, workerCount, stopOnError)
|
|
57
57
|
.then(afterTestsResults => Object.assign(executionResults, afterTestsResults));
|