@testim/testim-cli 3.199.0 → 3.203.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/commons/featureFlags.js +1 -3
- package/commons/logger.js +58 -48
- package/commons/testimServicesApi.js +14 -0
- package/executionQueue.js +2 -2
- package/lib/coralogix-winston.transport.js +106 -0
- package/npm-shrinkwrap.json +655 -262
- package/package.json +8 -8
- package/player/stepActions/pixelValidationStepAction.js +3 -2
- package/player/stepActions/salesforceAutoLoginStepAction.js +2 -2
- package/player/stepActions/stepActionRegistrar.js +0 -2
- package/player/utils/eyeSdkService.js +8 -2
- package/reports/junitReporter.js +0 -3
- package/runner.js +1 -10
- package/runners/ParallelWorkerManager.js +2 -2
- package/runners/TestPlanRunner.js +47 -15
- package/services/gridService.js +1 -6
- package/stepPlayers/hybridStepPlayback.js +4 -1
- package/stepPlayers/tdkHybridStepPlayback.js +1 -0
- package/testRunHandler.js +14 -6
- package/testRunStatus.js +2 -15
- package/workers/BaseWorker.js +1 -3
- package/workers/WorkerSelenium.js +3 -0
- package/lib/coralogix-bunyan.stream.js +0 -56
- package/player/stepActions/salesforceApexActionStepAction.js +0 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testim/testim-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.203.0",
|
|
4
4
|
"description": "Command line interface for running Testing on your CI",
|
|
5
5
|
"author": "Oren Rubin",
|
|
6
6
|
"contributors": [{
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"typescript": "3.9.3"
|
|
37
37
|
},
|
|
38
38
|
"lazyDependencies": {
|
|
39
|
-
"ngrok": "3.
|
|
39
|
+
"ngrok": "3.4.0",
|
|
40
40
|
"webpack": "4.43.0",
|
|
41
41
|
"playwright": "0.12.1",
|
|
42
42
|
"puppeteer": "2.1.1",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"bluebird": "3.7.2",
|
|
61
61
|
"bluebird-retry": "0.11.0",
|
|
62
62
|
"body-parser": "1.19.0",
|
|
63
|
-
"
|
|
64
|
-
"
|
|
63
|
+
"winston": "3.3.3",
|
|
64
|
+
"winston-transport": "4.4.0",
|
|
65
65
|
"chalk": "4.1.0",
|
|
66
66
|
"chrome-launcher": "0.13.4",
|
|
67
67
|
"combine-source-map": "0.8.0",
|
|
@@ -79,10 +79,10 @@
|
|
|
79
79
|
"glob": "7.1.6",
|
|
80
80
|
"istanbul-lib-report": "3.0.0",
|
|
81
81
|
"istanbul-reports": "3.0.2",
|
|
82
|
-
"jimp": "0.
|
|
82
|
+
"jimp": "0.16.1",
|
|
83
83
|
"jsdom": "16.7.0",
|
|
84
84
|
"jsonwebtoken": "8.5.1",
|
|
85
|
-
"lodash": "4.17.
|
|
85
|
+
"lodash": "4.17.21",
|
|
86
86
|
"memory-fs": "0.5.0",
|
|
87
87
|
"memorystream": "0.3.1",
|
|
88
88
|
"mkdirp": "1.0.4",
|
|
@@ -105,9 +105,9 @@
|
|
|
105
105
|
"superagent-proxy": "3.0.0",
|
|
106
106
|
"test-exclude": "6.0.0",
|
|
107
107
|
"threads": "0.12.0",
|
|
108
|
-
"ua-parser-js": "0.7.
|
|
108
|
+
"ua-parser-js": "0.7.28",
|
|
109
109
|
"validate-npm-package-name": "3.0.0",
|
|
110
|
-
"ws": "
|
|
110
|
+
"ws": "8.2.3",
|
|
111
111
|
"xml2js": "0.4.23",
|
|
112
112
|
"yaml": "1.10.0"
|
|
113
113
|
},
|
|
@@ -7,9 +7,10 @@ const logger = require('../../commons/logger').getLogger('pixel-validation-step-
|
|
|
7
7
|
|
|
8
8
|
class PixelValidationStepAction extends StepAction {
|
|
9
9
|
async performAction() {
|
|
10
|
-
const { shouldUseVisualGrid, applitoolsSdkConfig: config } = this.context;
|
|
10
|
+
const { shouldUseVisualGrid, applitoolsSdkConfig: config, testResultId } = this.context;
|
|
11
11
|
this.runContext = this.context.getRunContext(undefined);
|
|
12
|
-
const
|
|
12
|
+
const batchId = (config.batch && config.batch.id) || testResultId;
|
|
13
|
+
const eyeManager = await eyeSdkService.getManager(shouldUseVisualGrid, this.context.config.applitoolsConcurrency || 5, batchId, this.runContext.applitoolsIntegrationData);
|
|
13
14
|
const targetElementData = this.getTarget() || {};
|
|
14
15
|
try {
|
|
15
16
|
const openedEye = await eyeManager.openEyes({ driver: this.driver.client, config });
|
|
@@ -7,7 +7,7 @@ class SalesforceAutoLoginStepAction extends NavigationStepAction {
|
|
|
7
7
|
try {
|
|
8
8
|
salesforceUrl = await this.updateBaseUrl(salesforceUrl);
|
|
9
9
|
await this.driver.url(salesforceUrl);
|
|
10
|
-
await Promise.delay(
|
|
10
|
+
await Promise.delay(5000); // wait a little for the page to load (fixes screenshots and clicking on elements in username verification screen)
|
|
11
11
|
let newUrl = await this.driver.getUrl();
|
|
12
12
|
// Verify username screen
|
|
13
13
|
const isUsernameVerificationNeeded = newUrl.includes(this.step.USERNAME_VERIFICATION_PATH_ID);
|
|
@@ -22,7 +22,7 @@ class SalesforceAutoLoginStepAction extends NavigationStepAction {
|
|
|
22
22
|
await Promise.delay(5000);
|
|
23
23
|
newUrl = await this.driver.getUrl(); // If we managed to continue correctly we want to get the new redirected url
|
|
24
24
|
}
|
|
25
|
-
await Promise.delay(
|
|
25
|
+
await Promise.delay(1500);
|
|
26
26
|
return {
|
|
27
27
|
success: true,
|
|
28
28
|
newUrl,
|
|
@@ -24,7 +24,6 @@ const TdkHybridStepAction = require('./tdkHybridStepAction');
|
|
|
24
24
|
const PixelValidationStepAction = require('./pixelValidationStepAction');
|
|
25
25
|
|
|
26
26
|
const SalesforceAutoLoginStepAction = require('./salesforceAutoLoginStepAction');
|
|
27
|
-
const SalesforceApexActionStepAction = require('./salesforceApexActionStepAction');
|
|
28
27
|
|
|
29
28
|
const CliJsStepAction = require('./cliJsStepAction');
|
|
30
29
|
const CliConditionStepAction = require('./cliConditionStepAction');
|
|
@@ -87,7 +86,6 @@ module.exports = function (driver, stepActionFactory, runMode) {
|
|
|
87
86
|
'tdk-hybrid': TdkHybridStepAction,
|
|
88
87
|
|
|
89
88
|
'salesforce-autologin': SalesforceAutoLoginStepAction,
|
|
90
|
-
'salesforce-apex-action': SalesforceApexActionStepAction,
|
|
91
89
|
};
|
|
92
90
|
|
|
93
91
|
register(STEP_ACTION_MAPPING, stepActionFactory);
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// https://github.com/applitools/eyes.sdk.javascript1/blob/master/packages/eyes-webdriverio-4/src/spec-driver.ts
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @type {{ EyeSdkBuilder: typeof import('../../../../clickim/src/background/eyeSdkBuilder').EyeSdkBuilder }}
|
|
5
|
+
*/
|
|
6
|
+
const sessionPlayer = require('../../commons/getSessionPlayerRequire');
|
|
3
7
|
const { makeSDK } = require('@applitools/eyes-sdk-core');
|
|
4
8
|
const { W3C_ELEMENT_ID } = require('../constants');
|
|
5
9
|
const _ = require('lodash');
|
|
@@ -222,8 +226,10 @@ class EyeSdkService {
|
|
|
222
226
|
VisualGridClient: require('@applitools/visual-grid-client'),
|
|
223
227
|
});
|
|
224
228
|
}
|
|
225
|
-
getManager(useVisualGrid, concurrency) {
|
|
226
|
-
|
|
229
|
+
async getManager(useVisualGrid, concurrency, batchId, applitoolsIntegrationData) {
|
|
230
|
+
const manager = await this.sdk.makeManager({ type: useVisualGrid ? 'vg' : 'classic', concurrency });
|
|
231
|
+
sessionPlayer.EyeSdkBuilder.rememberCreatedBatch(batchId, applitoolsIntegrationData);
|
|
232
|
+
return manager;
|
|
227
233
|
}
|
|
228
234
|
}
|
|
229
235
|
|
package/reports/junitReporter.js
CHANGED
|
@@ -50,9 +50,6 @@ class JunitReporter {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function getPrintName(testResult) {
|
|
53
|
-
if (!featureFlags.flags.testNameTestDataInJunitReport.isEnabled()) {
|
|
54
|
-
return testResult.name;
|
|
55
|
-
}
|
|
56
53
|
const testData = testResult.testData || {};
|
|
57
54
|
const testDataNumber = typeof testData.total === 'number' ? ` - ${testData.index} / ${testData.total} Data set` : '';
|
|
58
55
|
return `${testResult.name}${testDataNumber}`;
|
package/runner.js
CHANGED
|
@@ -286,16 +286,7 @@ async function init(options) {
|
|
|
286
286
|
reporter.setOptions(options, branchToUse);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
function run(options, customExtensionLocalLocation) {
|
|
290
|
-
perf.log('in runner.js run');
|
|
291
|
-
|
|
292
|
-
if (options.files.length > 0 && !featureFlags.flags.enableTDKRun.isEnabled()) {
|
|
293
|
-
throw new ArgError('run command is not supported, please sign up to the Testim Development Kit beta - https://go.testim.io/testims-new-beta-testim-tdk-testim-development-kit-testautomation');
|
|
294
|
-
}
|
|
295
|
-
return runRunner(options, customExtensionLocalLocation);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
289
|
module.exports = {
|
|
299
|
-
run,
|
|
290
|
+
run: runRunner,
|
|
300
291
|
init: Promise.method(init),
|
|
301
292
|
};
|
|
@@ -46,14 +46,14 @@ class ParallelWorkerManager {
|
|
|
46
46
|
return Array.from(new Array(count), createWorker);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
async runTests(testList, testStatus, executionId, options, branchToUse, authData, workerCount, stopOnError) {
|
|
49
|
+
async runTests(testList, testStatus, executionId, executionName, options, branchToUse, authData, workerCount, stopOnError) {
|
|
50
50
|
if (testList && testList.length === 0) {
|
|
51
51
|
return undefined;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
const runAndWaitToComplete = token => new Promise((resolve, reject) => {
|
|
55
55
|
const projectId = options.project;
|
|
56
|
-
const executionQueue = new ExecutionQueue(executionId, testList, options, branchToUse, testStatus);
|
|
56
|
+
const executionQueue = new ExecutionQueue(executionId, executionName, testList, options, branchToUse, testStatus);
|
|
57
57
|
|
|
58
58
|
const combinedTestResults = {};
|
|
59
59
|
const testCount = testList.length;
|
|
@@ -19,6 +19,7 @@ const { getSuite, calcTestResultStatus, validateConfig } = require('./runnerUtil
|
|
|
19
19
|
const { StopRunOnError, ArgError } = require('../errors');
|
|
20
20
|
const Logger = require('../commons/logger');
|
|
21
21
|
const perf = require('../commons/performance-logger');
|
|
22
|
+
const featureFlags = require('../commons/featureFlags');
|
|
22
23
|
|
|
23
24
|
const guid = utils.guid;
|
|
24
25
|
const logger = Logger.getLogger('test-plan-runner');
|
|
@@ -29,30 +30,30 @@ class TestPlanRunner {
|
|
|
29
30
|
this.workerManager = new ParallelWorkerManager(customExtensionLocalLocation);
|
|
30
31
|
this.startTime = Date.now();
|
|
31
32
|
}
|
|
32
|
-
runTestAllPhases(beforeTests, tests, afterTests, branchToUse, tpOptions, executionId, testStatus) {
|
|
33
|
+
runTestAllPhases(beforeTests, tests, afterTests, branchToUse, tpOptions, executionId, executionName, testStatus) {
|
|
33
34
|
const executionResults = {};
|
|
34
35
|
const authData = testimCustomToken.getTokenV3UserData();
|
|
35
36
|
|
|
36
|
-
const runBeforeTests = (beforeTests, testStatus, executionId, tpOptions, branchToUse, authData) => {
|
|
37
|
+
const runBeforeTests = (beforeTests, testStatus, executionId, executionName, tpOptions, branchToUse, authData) => {
|
|
37
38
|
const workerCount = 1;
|
|
38
39
|
const stopOnError = true;
|
|
39
|
-
return this.workerManager.runTests(beforeTests, testStatus, executionId, tpOptions, branchToUse, authData, workerCount, stopOnError)
|
|
40
|
+
return this.workerManager.runTests(beforeTests, testStatus, executionId, executionName, tpOptions, branchToUse, authData, workerCount, stopOnError)
|
|
40
41
|
.then(beforeTestsResults => Object.assign(executionResults, beforeTestsResults));
|
|
41
42
|
};
|
|
42
43
|
|
|
43
|
-
const runTestPlanTests = (tests, testStatus, executionId, tpOptions, branchToUse, authData) => {
|
|
44
|
+
const runTestPlanTests = (tests, testStatus, executionId, executionName, tpOptions, branchToUse, authData) => {
|
|
44
45
|
const workerCount = config.TESTIM_CONCURRENT_WORKER_COUNT || tpOptions.parallel;
|
|
45
46
|
const stopOnError = false;
|
|
46
47
|
perf.log('right before this.workerManager.runTests');
|
|
47
|
-
return this.workerManager.runTests(tests, testStatus, executionId, tpOptions, branchToUse, authData, workerCount, stopOnError)
|
|
48
|
+
return this.workerManager.runTests(tests, testStatus, executionId, executionName, tpOptions, branchToUse, authData, workerCount, stopOnError)
|
|
48
49
|
.log('right after this.workerManager.runTests')
|
|
49
50
|
.then(testsResults => Object.assign(executionResults, testsResults));
|
|
50
51
|
};
|
|
51
52
|
|
|
52
|
-
const runAfterTests = (afterTests, testStatus, executionId, tpOptions, branchToUse, authData) => {
|
|
53
|
+
const runAfterTests = (afterTests, testStatus, executionId, executionName, tpOptions, branchToUse, authData) => {
|
|
53
54
|
const workerCount = 1;
|
|
54
55
|
const stopOnError = false;
|
|
55
|
-
return this.workerManager.runTests(afterTests, testStatus, executionId, tpOptions, branchToUse, authData, workerCount, stopOnError)
|
|
56
|
+
return this.workerManager.runTests(afterTests, testStatus, executionId, executionName, tpOptions, branchToUse, authData, workerCount, stopOnError)
|
|
56
57
|
.then(afterTestsResults => Object.assign(executionResults, afterTestsResults));
|
|
57
58
|
};
|
|
58
59
|
|
|
@@ -63,11 +64,11 @@ class TestPlanRunner {
|
|
|
63
64
|
const sessionType = utils.getSessionType(tpOptions);
|
|
64
65
|
analyticsService.analyticsExecsStart({ authData, executionId, projectId: tpOptions.project, sessionType });
|
|
65
66
|
perf.log('right before runBeforeTests');
|
|
66
|
-
return runBeforeTests(beforeTests, testStatus, executionId, tpOptions, branchToUse, authData)
|
|
67
|
+
return runBeforeTests(beforeTests, testStatus, executionId, executionName, tpOptions, branchToUse, authData)
|
|
67
68
|
.log('right before runTestPlanTests')
|
|
68
|
-
.then(() => runTestPlanTests(tests, testStatus, executionId, tpOptions, branchToUse, authData))
|
|
69
|
+
.then(() => runTestPlanTests(tests, testStatus, executionId, executionName, tpOptions, branchToUse, authData))
|
|
69
70
|
.log('right after runTestPlanTests')
|
|
70
|
-
.then(() => runAfterTests(afterTests, testStatus, executionId, tpOptions, branchToUse, authData))
|
|
71
|
+
.then(() => runAfterTests(afterTests, testStatus, executionId, executionName, tpOptions, branchToUse, authData))
|
|
71
72
|
.then(() => executionResults)
|
|
72
73
|
.catch(err => {
|
|
73
74
|
logger.error('error running test plan', { err });
|
|
@@ -75,6 +76,41 @@ class TestPlanRunner {
|
|
|
75
76
|
return catchBeforeTestsFailed(executionId);
|
|
76
77
|
}
|
|
77
78
|
throw err;
|
|
79
|
+
})
|
|
80
|
+
.finally(async () => {
|
|
81
|
+
if ((tpOptions.lightweightMode && tpOptions.lightweightMode.disablePixelValidation) || !featureFlags.flags.applitoolsNewIntegration.isEnabled()) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// When sessionPlayer is available, use it - as it only attempts to close batches that exist.
|
|
85
|
+
if (tpOptions.mode === constants.CLI_MODE.SELENIUM) {
|
|
86
|
+
/**
|
|
87
|
+
* @type {{ EyeSdkBuilder: typeof import('../../../clickim/src/background/eyeSdkBuilder').EyeSdkBuilder }}
|
|
88
|
+
*/
|
|
89
|
+
const sessionPlayerInit = require('../commons/getSessionPlayerRequire');
|
|
90
|
+
// TODO: remove once session player released.
|
|
91
|
+
if (typeof sessionPlayerInit.EyeSdkBuilder.closeBatch !== 'function') {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
await sessionPlayerInit.EyeSdkBuilder.closeBatch(executionId);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
if (!tpOptions.company || !tpOptions.company.activePlan || !tpOptions.company.activePlan.premiumFeatures || !tpOptions.company.activePlan.premiumFeatures.applitools) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const applitoolsIntegrationData = await testimServicesApi.getApplitoolsIntegrationData(tpOptions.project);
|
|
102
|
+
if (_.isEmpty(applitoolsIntegrationData)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const { runKey: apiKey, url: serverUrl } = applitoolsIntegrationData;
|
|
106
|
+
const tmpSDK = require('@applitools/eyes-sdk-core').makeSDK({ name: 'Testim.io', version: '4.0.0', spec: {} });
|
|
107
|
+
await tmpSDK.closeBatches({ batchIds: [executionId], serverUrl, apiKey });
|
|
108
|
+
} catch (err) {
|
|
109
|
+
if (err.message && err.message.startsWith('Request failed with status code 404')) { // If a batch with this name did not exist, do not log an error.
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
logger.error('Failed closing batch in extension mode', { err, projectId: tpOptions.project });
|
|
113
|
+
}
|
|
78
114
|
});
|
|
79
115
|
}
|
|
80
116
|
|
|
@@ -150,10 +186,6 @@ class TestPlanRunner {
|
|
|
150
186
|
|
|
151
187
|
const isCodeMode = tpOptions.files.length > 0;
|
|
152
188
|
|
|
153
|
-
if (isCodeMode && tpOptions.mode === constants.CLI_MODE.SELENIUM) {
|
|
154
|
-
// in selenium mode we don't need to wait for the runner and clickim to sync, so we don't need to wait for reports.
|
|
155
|
-
testStatus.setAsyncReporting(true);
|
|
156
|
-
}
|
|
157
189
|
const testListInfoPromise = tpOptions.lightweightMode && tpOptions.lightweightMode.onlyTestIdsNoSuite ?
|
|
158
190
|
{ beforeTests, tests, afterTests } :
|
|
159
191
|
testStatus.executionStart(executionId, projectId, this.startTime, testPlanName);
|
|
@@ -171,7 +203,7 @@ class TestPlanRunner {
|
|
|
171
203
|
}
|
|
172
204
|
|
|
173
205
|
perf.log('before runTestAllPhases');
|
|
174
|
-
const results = await this.runTestAllPhases(testListInfo.beforeTests, testListInfo.tests, testListInfo.afterTests, branch, tpOptions, executionId, testStatus);
|
|
206
|
+
const results = await this.runTestAllPhases(testListInfo.beforeTests, testListInfo.tests, testListInfo.afterTests, branch, tpOptions, executionId, testPlanName || 'All Tests', testStatus);
|
|
175
207
|
const childResults = await Bluebird.resolve(childTestResults)
|
|
176
208
|
.timeout(TDK_CHILD_RESULTS_TIMEOUT)
|
|
177
209
|
.catch(async () => {
|
package/services/gridService.js
CHANGED
|
@@ -50,13 +50,12 @@ function getSerializableObject(grid) {
|
|
|
50
50
|
(tunnel && grid.hybrid.external && grid.hybrid.external[grid.hybrid.tunnel] && grid.hybrid.external[grid.hybrid.tunnel].user) : user;
|
|
51
51
|
const tunnelKey = type === gridTypes.HYBRID ?
|
|
52
52
|
(tunnel && grid.hybrid.external && grid.hybrid.external[grid.hybrid.tunnel] && grid.hybrid.external[grid.hybrid.tunnel].key) : key;
|
|
53
|
-
const arn = (grid && grid.external && grid.external.arn) || (tunnel && grid.hybrid.external && grid.hybrid.external[grid.hybrid.tunnel] && grid.hybrid.external[grid.hybrid.tunnel].arn);
|
|
54
53
|
const name = grid && grid.name;
|
|
55
54
|
const gridId = grid && (grid._id || grid.gridId);
|
|
56
55
|
const provider = grid && grid.provider;
|
|
57
56
|
|
|
58
57
|
return {
|
|
59
|
-
host, port, path, protocol, accessToken, slotId, gridId, tunnel, user, key, type, name,
|
|
58
|
+
host, port, path, protocol, accessToken, slotId, gridId, tunnel, user, key, type, name, provider, tunnelUser, tunnelKey,
|
|
60
59
|
};
|
|
61
60
|
}
|
|
62
61
|
|
|
@@ -245,10 +244,6 @@ async function getTestPlanGridData(options) {
|
|
|
245
244
|
if (testPlanGrids.includes(undefined)) {
|
|
246
245
|
throw new ArgError('failed to find one of the test plan defined grid');
|
|
247
246
|
}
|
|
248
|
-
const gridTypes = _(testPlanGrids).map(grid => grid.type).uniq().value();
|
|
249
|
-
if (gridTypes.includes('testimMobile') && gridTypes.length > 1) {
|
|
250
|
-
throw new ArgError('Test plans cannot include two different grid types');
|
|
251
|
-
}
|
|
252
247
|
return getSerializableObject(_.first(testPlanGrids));
|
|
253
248
|
}
|
|
254
249
|
|
|
@@ -6,6 +6,7 @@ const perfLogger = require('../commons/performance-logger');
|
|
|
6
6
|
const MemoryFS = require('memory-fs');
|
|
7
7
|
const mfs = new MemoryFS();
|
|
8
8
|
const AbortController = require("abort-controller");
|
|
9
|
+
const logger = require('../commons/logger').getLogger('hybrid-step-playback');
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* @type {Map<string, import("abort-controller")>}
|
|
@@ -119,10 +120,12 @@ module.exports.execute = async function execute(step, context, driver, loginData
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
return { success: false, shouldRetry: false, reason: 'unknown hybrid format ' + hybridFunction.type };
|
|
123
|
+
} catch (err) {
|
|
124
|
+
logger.log('error running hybrid step', { err });
|
|
122
125
|
} finally {
|
|
123
126
|
runningStepsAbortControllersRegistry.delete(context.stepResultId);
|
|
124
127
|
}
|
|
125
|
-
}
|
|
128
|
+
};
|
|
126
129
|
|
|
127
130
|
module.exports.abort = function abort(stepResultId) {
|
|
128
131
|
const abortController = runningStepsAbortControllersRegistry.get(stepResultId);
|
package/testRunHandler.js
CHANGED
|
@@ -15,13 +15,13 @@ const utils = require('./utils');
|
|
|
15
15
|
const config = require('./commons/config');
|
|
16
16
|
const analytics = require('./commons/testimAnalytics');
|
|
17
17
|
const { SeleniumPerfStats } = require('./commons/SeleniumPerfStats');
|
|
18
|
-
const featureFlags = require('./commons/featureFlags');
|
|
19
18
|
const { preloadTests } = require('./commons/preloadTests');
|
|
20
19
|
|
|
21
20
|
const RETRIES_ON_TIMEOUT = 3;
|
|
22
21
|
|
|
23
|
-
const TestRun = function (executionId, test, options, branchToUse, testRunStatus) {
|
|
22
|
+
const TestRun = function (executionId, executionName, test, options, branchToUse, testRunStatus) {
|
|
24
23
|
this._executionId = executionId;
|
|
24
|
+
this._executionName = executionName;
|
|
25
25
|
this._testStatus = test.testStatus;
|
|
26
26
|
this._testId = test.testId;
|
|
27
27
|
this._testName = test.name;
|
|
@@ -81,6 +81,10 @@ TestRun.prototype.getExecutionId = function () {
|
|
|
81
81
|
return this._executionId;
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
+
TestRun.prototype.getExecutionName = function () {
|
|
85
|
+
return this._executionName;
|
|
86
|
+
};
|
|
87
|
+
|
|
84
88
|
TestRun.prototype.getNativeAppData = function () {
|
|
85
89
|
if (this._nativeApp && !this._options.baseUrl) {
|
|
86
90
|
return this._nativeApp;
|
|
@@ -122,6 +126,7 @@ TestRun.prototype.getRunRequestParams = async function () {
|
|
|
122
126
|
refreshToken: testimCustomToken.getRefreshToken(),
|
|
123
127
|
projectId: this._options.project,
|
|
124
128
|
executionId: this._executionId,
|
|
129
|
+
executionName: this._executionName,
|
|
125
130
|
testId: this._testId,
|
|
126
131
|
resultId: this._testResultId,
|
|
127
132
|
baseUrl: this._baseUrl,
|
|
@@ -232,6 +237,12 @@ TestRun.prototype.clearTestResult = function () {
|
|
|
232
237
|
if (this._options.mockNetworkRules) {
|
|
233
238
|
runData.mockNetworkRules = this._options.mockNetworkRules;
|
|
234
239
|
}
|
|
240
|
+
const mustClearPreviousStepResults = !this.isAllowReportTestResultRetries() && (this._timeoutRetryCount > 1 || this._retryCount > 1);
|
|
241
|
+
|
|
242
|
+
if (this._options.lightweightMode && this._options.lightweightMode.disableResults &&
|
|
243
|
+
!mustClearPreviousStepResults) {
|
|
244
|
+
return Promise.resolve();
|
|
245
|
+
}
|
|
235
246
|
|
|
236
247
|
this.clearTestResultFinished = testimServicesApi.uploadRunDataArtifact(this._options.project, this._testId, this._testResultId, runData)
|
|
237
248
|
.catch(err => {
|
|
@@ -252,9 +263,6 @@ TestRun.prototype.clearTestResult = function () {
|
|
|
252
263
|
testRetryKey: this.getRetryKey(),
|
|
253
264
|
});
|
|
254
265
|
});
|
|
255
|
-
if (this._testRunStatus.asyncReporting) {
|
|
256
|
-
return Promise.resolve();
|
|
257
|
-
}
|
|
258
266
|
return this.clearTestResultFinished;
|
|
259
267
|
};
|
|
260
268
|
|
|
@@ -531,7 +539,7 @@ TestRun.prototype.isAllowReportTestResultRetries = function () {
|
|
|
531
539
|
TestRun.prototype.onRetry = async function () {
|
|
532
540
|
this._previousTestResultId = this._testResultId;
|
|
533
541
|
|
|
534
|
-
if (!
|
|
542
|
+
if (!this.isAllowReportTestResultRetries()) {
|
|
535
543
|
return;
|
|
536
544
|
}
|
|
537
545
|
|
package/testRunStatus.js
CHANGED
|
@@ -43,7 +43,6 @@ const RunStatus = function (testInfoList, options, testPlanId, branchToUse) {
|
|
|
43
43
|
this.exportsGlobal = {};
|
|
44
44
|
this.testInfoList = testInfoList;
|
|
45
45
|
|
|
46
|
-
this.asyncReporting = false; // whether or not we wait for result reporting
|
|
47
46
|
this.executionStartedPromise = Promise.resolve();
|
|
48
47
|
|
|
49
48
|
const browserNames = utils.getUniqBrowsers(options, testInfoList);
|
|
@@ -92,9 +91,6 @@ const RunStatus = function (testInfoList, options, testPlanId, branchToUse) {
|
|
|
92
91
|
RunStatus.prototype.waitForExecutionStartedFinished = function () {
|
|
93
92
|
return this.executionStartedPromise;
|
|
94
93
|
};
|
|
95
|
-
RunStatus.prototype.setAsyncReporting = function (isAsyncReportingEnabled = false) {
|
|
96
|
-
this.asyncReporting = isAsyncReportingEnabled;
|
|
97
|
-
};
|
|
98
94
|
RunStatus.prototype.getTestResult = function (resultId) {
|
|
99
95
|
return this.testRunStatus[resultId];
|
|
100
96
|
};
|
|
@@ -157,7 +153,7 @@ RunStatus.prototype.updateTestStatusRunning = function (test, executionId, testR
|
|
|
157
153
|
return this.executionStartedPromise;
|
|
158
154
|
}
|
|
159
155
|
|
|
160
|
-
|
|
156
|
+
return servicesApi.updateTestDataArtifact(projectId, test.testId, test.resultId, test.config.testData, projectData.defaults)
|
|
161
157
|
.catch(err => {
|
|
162
158
|
logger.error('failed to upload test data artifact (runner)', { err });
|
|
163
159
|
return '';
|
|
@@ -169,12 +165,6 @@ RunStatus.prototype.updateTestStatusRunning = function (test, executionId, testR
|
|
|
169
165
|
await this.executionStartedPromise;
|
|
170
166
|
return servicesApi.updateTestStatus(projectId, executionId, test.testId, test.resultId, 'RUNNING', { startTime: test.startTime, config: testConfig, remoteRunId, testRetryKey });
|
|
171
167
|
});
|
|
172
|
-
if (this.asyncReporting) {
|
|
173
|
-
// silence is golden
|
|
174
|
-
} else {
|
|
175
|
-
return res;
|
|
176
|
-
}
|
|
177
|
-
return servicesApi.updateTestStatus(projectId, executionId, test.testId, test.resultId, 'RUNNING', { startTime: test.startTime, config: test.config, remoteRunId, testRetryKey });
|
|
178
168
|
};
|
|
179
169
|
|
|
180
170
|
RunStatus.prototype.testStartReport = function (test, executionId, testRetryKey) {
|
|
@@ -406,10 +396,7 @@ RunStatus.prototype.executionStart = function (executionId, projectId, startTime
|
|
|
406
396
|
const ret = servicesApi.reportExecutionStarted(data);
|
|
407
397
|
this.executionStartedPromise = ret;
|
|
408
398
|
ret.catch(e => logger.error(e));
|
|
409
|
-
|
|
410
|
-
return ret;
|
|
411
|
-
}
|
|
412
|
-
return undefined;
|
|
399
|
+
return ret;
|
|
413
400
|
});
|
|
414
401
|
};
|
|
415
402
|
|
package/workers/BaseWorker.js
CHANGED
|
@@ -90,9 +90,7 @@ class BaseWorker {
|
|
|
90
90
|
resultId: testRunHandler.getTestResultId(),
|
|
91
91
|
seleniumSession: player.getSessionId(),
|
|
92
92
|
});
|
|
93
|
-
|
|
94
|
-
return undefined;
|
|
95
|
-
}
|
|
93
|
+
|
|
96
94
|
return await testRunHandler.clearTestResult();
|
|
97
95
|
}
|
|
98
96
|
|
|
@@ -88,6 +88,9 @@ class WorkerSelenium extends BaseWorker {
|
|
|
88
88
|
|
|
89
89
|
setupCliPerformanceMonitoring(sessionPlayer);
|
|
90
90
|
|
|
91
|
+
sessionPlayer.playbackManager.executionId = testRunHandler.getExecutionId();
|
|
92
|
+
sessionPlayer.playbackManager.executionName = testRunHandler.getExecutionName();
|
|
93
|
+
|
|
91
94
|
sessionPlayer.setLightweightMode(this.options.lightweightMode);
|
|
92
95
|
if (sessionPlayerInit.localAssetService) {
|
|
93
96
|
sessionPlayerInit.localAssetService.initialize({ serverUrl: this.options.localRCASaver });
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// This is copied from coralogix-bunyan-stream pacakge and altered to expose waitForFlush
|
|
4
|
-
|
|
5
|
-
const coralogixLogger = require('@testim/coralogix-logger');
|
|
6
|
-
|
|
7
|
-
const sevMap = {
|
|
8
|
-
10: coralogixLogger.Severity.debug,
|
|
9
|
-
30: coralogixLogger.Severity.info,
|
|
10
|
-
40: coralogixLogger.Severity.warning,
|
|
11
|
-
50: coralogixLogger.Severity.error,
|
|
12
|
-
60: coralogixLogger.Severity.critical,
|
|
13
|
-
20: coralogixLogger.Severity.debug,
|
|
14
|
-
};
|
|
15
|
-
const CoralogixStream = (function () {
|
|
16
|
-
function CoralogixStream(options) {
|
|
17
|
-
if (!options) options = {};
|
|
18
|
-
CoralogixStream.logger = this.logger = new coralogixLogger.CoralogixLogger(options.category);
|
|
19
|
-
}
|
|
20
|
-
CoralogixStream.waitForFlush = function () {
|
|
21
|
-
return CoralogixStream.logger.waitForFlush();
|
|
22
|
-
};
|
|
23
|
-
CoralogixStream.prototype.write = function (rec) {
|
|
24
|
-
const log = new coralogixLogger.Log();
|
|
25
|
-
log.severity = sevMap[rec.level];
|
|
26
|
-
log.category = rec.category;
|
|
27
|
-
if (rec.className) log.className = rec.className;
|
|
28
|
-
if (rec.methodName) log.methodName = rec.methodName;
|
|
29
|
-
if (rec.threadId) log.threadId = rec.threadId;
|
|
30
|
-
log.text = this.removeStaticFields(rec);
|
|
31
|
-
this.logger.addLog(log);
|
|
32
|
-
};
|
|
33
|
-
CoralogixStream.prototype.removeStaticFields = function (json) {
|
|
34
|
-
delete json.threadId;
|
|
35
|
-
delete json.methodName;
|
|
36
|
-
delete json.className;
|
|
37
|
-
delete json.category;
|
|
38
|
-
return JSON.stringify(json, this.replaceErrors);
|
|
39
|
-
};
|
|
40
|
-
CoralogixStream.prototype.replaceErrors = function (key, value) {
|
|
41
|
-
if (value instanceof Error) {
|
|
42
|
-
const error = {};
|
|
43
|
-
Object.getOwnPropertyNames(value).forEach((key) => {
|
|
44
|
-
error[key] = value[key];
|
|
45
|
-
});
|
|
46
|
-
return error;
|
|
47
|
-
}
|
|
48
|
-
return value;
|
|
49
|
-
};
|
|
50
|
-
CoralogixStream.configure = function (config) {
|
|
51
|
-
coralogixLogger.CoralogixLogger.configure(config);
|
|
52
|
-
};
|
|
53
|
-
return CoralogixStream;
|
|
54
|
-
}());
|
|
55
|
-
|
|
56
|
-
module.exports = { CoralogixStream };
|