@testim/testim-cli 3.252.0 → 3.254.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 +15 -14
- package/agent/routers/codim/service.js +1 -1
- package/agent/routers/general/index.js +4 -8
- package/agent/routers/hybrid/registerRoutes.js +18 -18
- package/agent/routers/index.js +9 -8
- package/agent/routers/playground/router.js +12 -11
- package/agent/routers/playground/service.js +19 -18
- 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 +7 -6
- package/cliAgentMode.js +4 -5
- package/codim/codim-cli.js +11 -10
- 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/chrome-launcher.js +6 -6
- package/commons/constants.js +2 -0
- package/commons/detectDebugger.js +4 -2
- package/commons/getSessionPlayerRequire.js +2 -20
- package/commons/initializeUserWithAuth.js +2 -2
- package/commons/lazyRequire.js +10 -9
- package/commons/logger.js +4 -4
- package/commons/performance-logger.js +14 -8
- package/commons/prepareRunnerAndTestimStartUtils.js +6 -7
- 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 +44 -0
- package/commons/testimNgrok.js +2 -2
- package/commons/testimNgrok.test.js +1 -1
- package/commons/testimServicesApi.js +37 -21
- package/commons/xhr2.js +97 -100
- package/credentialsManager.js +17 -20
- package/errors.js +5 -0
- package/fixLocalBuild.js +2 -0
- package/npm-shrinkwrap.json +4455 -1576
- package/package.json +9 -7
- package/player/WebdriverioWebDriverApi.js +7 -2
- package/player/appiumTestPlayer.js +102 -0
- package/player/chromeLauncherTestPlayer.js +0 -1
- package/player/seleniumTestPlayer.js +3 -2
- package/player/services/frameLocator.js +2 -1
- package/player/services/mobileFrameLocatorMock.js +32 -0
- package/player/services/playbackTimeoutCalculator.js +1 -0
- package/player/services/portSelector.js +10 -8
- package/player/services/tabService.js +29 -0
- package/player/services/tabServiceMock.js +166 -0
- package/player/stepActions/navigationStepAction.js +11 -10
- package/player/stepActions/sleepStepAction.js +4 -5
- package/player/stepActions/stepAction.js +15 -1
- package/player/stepActions/textStepAction.js +4 -11
- package/player/utils/stepActionUtils.js +4 -2
- package/player/utils/windowUtils.js +139 -125
- package/player/webdriver.js +40 -26
- package/processHandler.js +3 -3
- package/processHandler.test.js +1 -1
- package/reports/consoleReporter.js +3 -2
- package/reports/debugReporter.js +41 -39
- package/reports/jsonReporter.js +53 -50
- package/reports/junitReporter.js +1 -2
- package/reports/reporter.js +135 -136
- package/runOptions.js +8 -7
- package/runner.js +13 -0
- package/runners/ParallelWorkerManager.js +2 -0
- package/runners/TestPlanRunner.js +142 -74
- package/runners/buildCodeTests.js +38 -37
- package/runners/runnerUtils.js +3 -3
- package/services/lambdatestService.js +3 -5
- package/stepPlayers/cliJsStepPlayback.js +22 -17
- package/testRunHandler.js +8 -0
- package/testRunStatus.js +458 -460
- package/{utils.js → utils/index.js} +25 -117
- package/utils/promiseUtils.js +78 -0
- package/utils/stringUtils.js +96 -0
- package/{utils.test.js → utils/utils.test.js} +2 -2
- package/workers/BaseWorker.js +29 -20
- package/workers/WorkerAppium.js +123 -0
- package/workers/WorkerExtensionSingleBrowser.js +4 -4
- package/workers/WorkerSelenium.js +5 -2
package/reports/debugReporter.js
CHANGED
|
@@ -16,33 +16,48 @@ const MASK_OPTIONS = {
|
|
|
16
16
|
testobjectSauce: undefined,
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
class DebugReporter {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.options = options;
|
|
22
|
+
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
24
|
+
onTestStarted(test, workerId) {
|
|
25
|
+
logger.info('Test Started', { testId: test.testId, testName: test.name, resultId: test.resultId, workerId });
|
|
26
|
+
}
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
28
|
+
onTestFinished(test, workerId) {
|
|
29
|
+
const gridData = this.options.gridData || {};
|
|
30
|
+
const provider = gridData.provider;
|
|
31
|
+
const host = gridData.host;
|
|
32
|
+
const gridId = gridData.gridId;
|
|
33
|
+
const gridType = gridData.type;
|
|
34
|
+
const failedGetBrowserAttempts = gridData.failedGetBrowserAttempts;
|
|
35
|
+
logger.info('Test Finished', {
|
|
36
|
+
testId: test.testId,
|
|
37
|
+
testName: test.name,
|
|
38
|
+
resultId: test.resultId,
|
|
39
|
+
success: test.success,
|
|
40
|
+
duration: test.duration,
|
|
41
|
+
browser: this.options.browser,
|
|
42
|
+
companyId: this.options.company.companyId,
|
|
43
|
+
grid: { provider, host, failedGetBrowserAttempts, id: gridId, type: gridType },
|
|
44
|
+
workerId,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
onTestPlanStarted(beforeTests, tests, afterTests, testPlanName, executionId, isAnonymous, configName) {
|
|
49
|
+
const args = stripTokenFromConsoleArguments(process.argv);
|
|
50
|
+
|
|
51
|
+
logger.info('Test Plan Started', { executionId, testPlanName, isAnonymous, configName, options: Object.assign({}, this.options, MASK_OPTIONS), args });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
onTestPlanFinished(testResults, testPlanName, duration, executionId, isAnonymous) {
|
|
55
|
+
const passed = Object.keys(testResults).filter(resultId => testResults[resultId].status === constants.runnerTestStatus.PASSED).length;
|
|
56
|
+
const failed = Object.keys(testResults).length - passed;
|
|
57
|
+
|
|
58
|
+
logger.info('Test Plan Finished', { isAnonymous, passed, failed, testPlanName, options: Object.assign({}, this.options, MASK_OPTIONS), duration, executionId });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
46
61
|
|
|
47
62
|
function stripTokenFromConsoleArguments(args) {
|
|
48
63
|
let indexOfTokenFlag = args.indexOf('--token');
|
|
@@ -57,24 +72,11 @@ function stripTokenFromConsoleArguments(args) {
|
|
|
57
72
|
|
|
58
73
|
return newArgs;
|
|
59
74
|
} catch (e) {
|
|
60
|
-
|
|
75
|
+
/* empty */
|
|
61
76
|
}
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
return args;
|
|
65
80
|
}
|
|
66
81
|
|
|
67
|
-
DebugReporter.prototype.onTestPlanStarted = function (beforeTests, tests, afterTests, testPlanName, executionId, isAnonymous, configName) {
|
|
68
|
-
const args = stripTokenFromConsoleArguments(process.argv);
|
|
69
|
-
|
|
70
|
-
logger.info('Test Plan Started', { executionId, testPlanName, isAnonymous, configName, options: Object.assign({}, this.options, MASK_OPTIONS), args });
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
DebugReporter.prototype.onTestPlanFinished = function (testResults, testPlanName, duration, executionId, isAnonymous) {
|
|
74
|
-
const passed = Object.keys(testResults).filter(resultId => testResults[resultId].status === constants.runnerTestStatus.PASSED).length;
|
|
75
|
-
const failed = Object.keys(testResults).length - passed;
|
|
76
|
-
|
|
77
|
-
logger.info('Test Plan Finished', { isAnonymous, passed, failed, testPlanName, options: Object.assign({}, this.options, MASK_OPTIONS), duration, executionId });
|
|
78
|
-
};
|
|
79
|
-
|
|
80
82
|
module.exports = DebugReporter;
|
package/reports/jsonReporter.js
CHANGED
|
@@ -1,52 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
class JsonReporter {
|
|
3
|
+
constructor(options) {
|
|
4
|
+
this.options = options;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
onTestStarted(test, workerId) {
|
|
8
|
+
const event = {
|
|
9
|
+
name: 'testStarted',
|
|
10
|
+
data: {
|
|
11
|
+
test,
|
|
12
|
+
workerId,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
console.log(JSON.stringify(event));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
onTestFinished(test, workerId) {
|
|
20
|
+
const event = {
|
|
21
|
+
name: 'testFinished',
|
|
22
|
+
data: {
|
|
23
|
+
test,
|
|
24
|
+
workerId,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
console.log(JSON.stringify(event));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onTestPlanStarted(beforeTests, tests, afterTests, testPlanName, executionId) {
|
|
32
|
+
const event = {
|
|
33
|
+
name: 'suiteStarted',
|
|
34
|
+
data: {
|
|
35
|
+
projectId: this.options.project,
|
|
36
|
+
executionId,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
console.log(JSON.stringify(event));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onTestPlanFinished(testResults) {
|
|
44
|
+
const event = {
|
|
45
|
+
name: 'suiteFinished',
|
|
46
|
+
data: {
|
|
47
|
+
testResults,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
console.log(JSON.stringify(event));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
51
54
|
|
|
52
55
|
module.exports = JsonReporter;
|
package/reports/junitReporter.js
CHANGED
|
@@ -5,11 +5,10 @@
|
|
|
5
5
|
const xml2js = require('xml2js');
|
|
6
6
|
const Promise = require('bluebird');
|
|
7
7
|
const fs = Promise.promisifyAll(require('fs'));
|
|
8
|
-
const utils = require('../utils
|
|
8
|
+
const utils = require('../utils');
|
|
9
9
|
const {
|
|
10
10
|
isAbortedTest, isSkippedTest, getFailedTests, isFailedTest, getFailureEvaluatingCount, getSkippedCount, getAbortedTests,
|
|
11
11
|
} = require('./reporterUtils');
|
|
12
|
-
const featureFlags = require('../commons/featureFlags.js');
|
|
13
12
|
const featureAvailabilityService = require('../commons/featureAvailabilityService');
|
|
14
13
|
|
|
15
14
|
class JunitReporter {
|
package/reports/reporter.js
CHANGED
|
@@ -3,53 +3,155 @@
|
|
|
3
3
|
const logger = require('../commons/logger').getLogger('reporter');
|
|
4
4
|
const Promise = require('bluebird');
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
class Reporter {
|
|
7
|
+
setOptions(options, branchToUse) {
|
|
8
|
+
this.reporters = [];
|
|
9
|
+
const optReporters = options.reporters;
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const optReporters = options.reporters;
|
|
11
|
+
const DebugReporter = require('./debugReporter');
|
|
12
|
+
this.reporters.push(new DebugReporter(options));
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
this.reporters.push(new DebugReporter(options));
|
|
14
|
-
|
|
15
|
-
if (optReporters === undefined || optReporters.length === 0) {
|
|
16
|
-
const ConsoleReporter = require('./consoleReporter');
|
|
17
|
-
this.reporters.push(new ConsoleReporter(options, branchToUse));
|
|
18
|
-
if (options !== undefined && options.reportFile !== undefined) {
|
|
19
|
-
const JunitReporter = require('./junitReporter');
|
|
20
|
-
this.reporters.push(new JunitReporter(options, branchToUse));
|
|
21
|
-
}
|
|
22
|
-
} else {
|
|
23
|
-
if (optReporters.indexOf('teamcity') > -1) {
|
|
24
|
-
const TeamCityReporter = require('./teamCityReporter');
|
|
25
|
-
this.reporters.push(new TeamCityReporter(options));
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (optReporters.indexOf('console') > -1) {
|
|
14
|
+
if (optReporters === undefined || optReporters.length === 0) {
|
|
29
15
|
const ConsoleReporter = require('./consoleReporter');
|
|
30
16
|
this.reporters.push(new ConsoleReporter(options, branchToUse));
|
|
31
|
-
|
|
17
|
+
if (options?.reportFile !== undefined) {
|
|
18
|
+
const JunitReporter = require('./junitReporter');
|
|
19
|
+
this.reporters.push(new JunitReporter(options, branchToUse));
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
if (optReporters.includes('teamcity')) {
|
|
23
|
+
const TeamCityReporter = require('./teamCityReporter');
|
|
24
|
+
this.reporters.push(new TeamCityReporter(options));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (optReporters.includes('console')) {
|
|
28
|
+
const ConsoleReporter = require('./consoleReporter');
|
|
29
|
+
this.reporters.push(new ConsoleReporter(options, branchToUse));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (optReporters.includes('junit')) {
|
|
33
|
+
const JunitReporter = require('./junitReporter');
|
|
34
|
+
this.reporters.push(new JunitReporter(options, branchToUse));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (optReporters.includes('json')) {
|
|
38
|
+
const JsonReporter = require('./jsonReporter');
|
|
39
|
+
this.reporters.push(new JsonReporter(options));
|
|
40
|
+
}
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
if (optReporters.includes('chrome')) {
|
|
43
|
+
const { ChromeReporter } = require('./chromeReporter');
|
|
44
|
+
this.reporters.push(new ChromeReporter(options, branchToUse));
|
|
45
|
+
}
|
|
36
46
|
}
|
|
47
|
+
}
|
|
37
48
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
onTestPlanFinished(testResults, testPlanName, startTime, executionId, isAnonymous, isCodeMode, childTestResults) {
|
|
50
|
+
let results = {};
|
|
51
|
+
|
|
52
|
+
// TODO: remove mutation of testResults from the Reporter
|
|
53
|
+
if (childTestResults) {
|
|
54
|
+
const childValues = Object.values(childTestResults);
|
|
55
|
+
if (childValues.length > 0) {
|
|
56
|
+
for (const child of Object.values(childTestResults)) {
|
|
57
|
+
results[child.id] = child;
|
|
58
|
+
}
|
|
59
|
+
for (const parent of Object.keys(testResults)) {
|
|
60
|
+
if (!childValues.some(c => c.parentResultId !== parent)) {
|
|
61
|
+
results[parent] = testResults[parent];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
logger.warn('childTestResults is not array');
|
|
66
|
+
results = testResults;
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
results = testResults;
|
|
41
70
|
}
|
|
42
71
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
72
|
+
return Promise.each(this.reporters, reporter => {
|
|
73
|
+
if (reporter?.onTestPlanFinished) {
|
|
74
|
+
const duration = Date.now() - (startTime || 0);
|
|
75
|
+
return reporter.onTestPlanFinished(results, testPlanName, duration, executionId, isAnonymous, isCodeMode);
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
onTestPlanStarted(beforeTests, tests, afterTests, testPlanName, executionId, isAnonymous, configName, isCodeMode) {
|
|
82
|
+
return Promise.each(this.reporters, reporter => {
|
|
83
|
+
if (reporter?.onTestPlanStarted) {
|
|
84
|
+
return reporter.onTestPlanStarted(beforeTests, tests, afterTests, testPlanName, executionId, isAnonymous, configName, isCodeMode);
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
onGetSlot(workerId, browser) {
|
|
91
|
+
return Promise.each(this.reporters, reporter => {
|
|
92
|
+
if (reporter?.onGetSlot) {
|
|
93
|
+
return reporter.onGetSlot(workerId, browser);
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
onGetSession(workerId, testName, mode) {
|
|
100
|
+
return Promise.each(this.reporters, reporter => {
|
|
101
|
+
if (reporter?.onGetSession) {
|
|
102
|
+
return reporter.onGetSession(workerId, testName, mode);
|
|
103
|
+
}
|
|
104
|
+
return undefined;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
onWaitToTestComplete(workerId, isCodeMode, debuggerAddress) {
|
|
109
|
+
return Promise.each(this.reporters, reporter => {
|
|
110
|
+
if (reporter?.onWaitToTestComplete) {
|
|
111
|
+
return reporter.onWaitToTestComplete(workerId, isCodeMode, debuggerAddress);
|
|
112
|
+
}
|
|
113
|
+
return undefined;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
onWaitToTestStart(workerId) {
|
|
118
|
+
return Promise.each(this.reporters, reporter => {
|
|
119
|
+
if (reporter?.onWaitToTestStart) {
|
|
120
|
+
return reporter.onWaitToTestStart(workerId);
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
onAllTestPlansFinished(testPlanResults) {
|
|
127
|
+
// TODO: remove mutation of testPlanResults from the Reporter
|
|
128
|
+
for (const result of testPlanResults) {
|
|
129
|
+
if (result.childTestResults) {
|
|
130
|
+
result.results = {};
|
|
131
|
+
const childValues = Object.values(result.childTestResults);
|
|
132
|
+
for (const child of childValues) {
|
|
133
|
+
result.results[child.id] = child;
|
|
134
|
+
}
|
|
135
|
+
for (const parent of Object.keys(testPlanResults)) {
|
|
136
|
+
if (!childValues.some(c => c.parentResultId !== parent)) {
|
|
137
|
+
result.results[parent] = testPlanResults[parent];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
46
141
|
}
|
|
142
|
+
|
|
143
|
+
return Promise.each(this.reporters, reporter => {
|
|
144
|
+
if (reporter?.onAllTestPlansFinished) {
|
|
145
|
+
return reporter.onAllTestPlansFinished(testPlanResults);
|
|
146
|
+
}
|
|
147
|
+
return undefined;
|
|
148
|
+
});
|
|
47
149
|
}
|
|
48
|
-
}
|
|
150
|
+
}
|
|
49
151
|
|
|
50
152
|
function addHook(name) {
|
|
51
153
|
Reporter.prototype[name] = function (...args) {
|
|
52
|
-
return Promise.filter(this.reporters, reporter => reporter
|
|
154
|
+
return Promise.filter(this.reporters, reporter => reporter?.[name]).each(reporter => reporter[name](...args));
|
|
53
155
|
};
|
|
54
156
|
}
|
|
55
157
|
|
|
@@ -66,107 +168,4 @@ addHook('onTestIgnored');
|
|
|
66
168
|
addHook('onWaitToTestStart');
|
|
67
169
|
addHook('onWaitToTestComplete');
|
|
68
170
|
|
|
69
|
-
Reporter.prototype.onTestPlanFinished = function (testResults, testPlanName, startTime, executionId, isAnonymous, isCodeMode, childTestResults) {
|
|
70
|
-
let results = {};
|
|
71
|
-
|
|
72
|
-
// TODO: remove mutation of testResults from the Reporter
|
|
73
|
-
if (childTestResults) {
|
|
74
|
-
const childValues = Object.values(childTestResults);
|
|
75
|
-
if (childValues.length > 0) {
|
|
76
|
-
for (const child of Object.values(childTestResults)) {
|
|
77
|
-
results[child.id] = child;
|
|
78
|
-
}
|
|
79
|
-
for (const parent of Object.keys(testResults)) {
|
|
80
|
-
if (!childValues.some(c => c.parentResultId !== parent)) {
|
|
81
|
-
results[parent] = testResults[parent];
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
} else {
|
|
85
|
-
logger.warn('childTestResults is not array');
|
|
86
|
-
results = testResults;
|
|
87
|
-
}
|
|
88
|
-
} else {
|
|
89
|
-
results = testResults;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return Promise.each(this.reporters, reporter => {
|
|
93
|
-
if (reporter && reporter.onTestPlanFinished) {
|
|
94
|
-
const duration = Date.now() - (startTime || 0);
|
|
95
|
-
return reporter.onTestPlanFinished(results, testPlanName, duration, executionId, isAnonymous, isCodeMode);
|
|
96
|
-
}
|
|
97
|
-
return undefined;
|
|
98
|
-
});
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
Reporter.prototype.onTestPlanStarted = function (beforeTests, tests, afterTests, testPlanName, executionId, isAnonymous, configName, isCodeMode) {
|
|
102
|
-
return Promise.each(this.reporters, reporter => {
|
|
103
|
-
if (reporter && reporter.onTestPlanStarted) {
|
|
104
|
-
return reporter.onTestPlanStarted(beforeTests, tests, afterTests, testPlanName, executionId, isAnonymous, configName, isCodeMode);
|
|
105
|
-
}
|
|
106
|
-
return undefined;
|
|
107
|
-
});
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
Reporter.prototype.onGetSlot = function (workerId, browser) {
|
|
111
|
-
return Promise.each(this.reporters, reporter => {
|
|
112
|
-
if (reporter && reporter.onGetSlot) {
|
|
113
|
-
return reporter.onGetSlot(workerId, browser);
|
|
114
|
-
}
|
|
115
|
-
return undefined;
|
|
116
|
-
});
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
Reporter.prototype.onGetSession = function (workerId, testName, mode) {
|
|
120
|
-
return Promise.each(this.reporters, reporter => {
|
|
121
|
-
if (reporter && reporter.onGetSession) {
|
|
122
|
-
return reporter.onGetSession(workerId, testName, mode);
|
|
123
|
-
}
|
|
124
|
-
return undefined;
|
|
125
|
-
});
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
Reporter.prototype.onWaitToTestComplete = function (workerId, isCodeMode, debuggerAddress) {
|
|
129
|
-
return Promise.each(this.reporters, reporter => {
|
|
130
|
-
if (reporter && reporter.onWaitToTestComplete) {
|
|
131
|
-
return reporter.onWaitToTestComplete(workerId, isCodeMode, debuggerAddress);
|
|
132
|
-
}
|
|
133
|
-
return undefined;
|
|
134
|
-
});
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
Reporter.prototype.onWaitToTestStart = function (workerId) {
|
|
138
|
-
return Promise.each(this.reporters, reporter => {
|
|
139
|
-
if (reporter && reporter.onWaitToTestStart) {
|
|
140
|
-
return reporter.onWaitToTestStart(workerId);
|
|
141
|
-
}
|
|
142
|
-
return undefined;
|
|
143
|
-
});
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
Reporter.prototype.onAllTestPlansFinished = function (testPlanResults) {
|
|
147
|
-
// TODO: remove mutation of testPlanResults from the Reporter
|
|
148
|
-
for (const result of testPlanResults) {
|
|
149
|
-
if (result.childTestResults) {
|
|
150
|
-
result.results = {};
|
|
151
|
-
const childValues = Object.values(result.childTestResults);
|
|
152
|
-
for (const child of childValues) {
|
|
153
|
-
result.results[child.id] = child;
|
|
154
|
-
}
|
|
155
|
-
for (const parent of Object.keys(testPlanResults)) {
|
|
156
|
-
if (!childValues.some(c => c.parentResultId !== parent)) {
|
|
157
|
-
result.results[parent] = testPlanResults[parent];
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return Promise.each(this.reporters, reporter => {
|
|
164
|
-
if (reporter && reporter.onAllTestPlansFinished) {
|
|
165
|
-
return reporter.onAllTestPlansFinished(testPlanResults);
|
|
166
|
-
}
|
|
167
|
-
return undefined;
|
|
168
|
-
});
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
|
|
172
171
|
module.exports = new Reporter();
|
package/runOptions.js
CHANGED
|
@@ -183,12 +183,12 @@ program
|
|
|
183
183
|
.option('-h, --headless [headless]', 'run in headless mode')
|
|
184
184
|
.option('-m, --mode [runner-mode]', 'use extension or selenium mode (extension/selenium/appium)')
|
|
185
185
|
.option('--branch [branch]', 'branch name', null)
|
|
186
|
-
.option('--base-url [base-url]', 'change
|
|
186
|
+
.option('--base-url [base-url]', 'change base-url to a specified url for all tests in current execution')
|
|
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
|
-
.option('--parallel [number-of-tests]', 'number of tests to run
|
|
190
|
-
.option('--before-parallel [number-of-tests]', 'number of tests to run
|
|
191
|
-
.option('--after-parallel [number-of-tests]', 'number of tests to run
|
|
189
|
+
.option('--parallel [number-of-tests]', 'number of tests to run in parallel')
|
|
190
|
+
.option('--before-parallel [number-of-tests]', 'number of tests to run in parallel during the before phase of a test plan')
|
|
191
|
+
.option('--after-parallel [number-of-tests]', 'number of tests to run in parallel during the after phase of a test plan')
|
|
192
192
|
.option('--canary [canary-mode]', 'enable canary mode', false)
|
|
193
193
|
.option('--test-plan [test-plan-name]', 'test plan to run', collect, [])
|
|
194
194
|
.option('--test-plan-id [test-plan-id]', 'test plan to run', collect, [])
|
|
@@ -203,7 +203,7 @@ program
|
|
|
203
203
|
.option('--proxy-for-grid [proxy-for-grid]', 'used together with --proxy to also router grid traffic through a proxy')
|
|
204
204
|
.option('--result-label [result-label]', 'result label', collect, [])
|
|
205
205
|
.option('-oen --override-execution-name [execution-name]', 'override the default execution name', '')
|
|
206
|
-
.option('--retries [max_num_of_retries]', 'number of
|
|
206
|
+
.option('--retries [max_num_of_retries]', 'number of retries on test failure, defaults to 0 (no retries)', 0)
|
|
207
207
|
.option('--set-retention [retention-in-days]', 'set the number of days for results retention')
|
|
208
208
|
.option('--user [user-id]', 'user ID for local Testim-CLI')
|
|
209
209
|
.option('--pass-zero-tests', 'don\'t fail the run if no tests were found')
|
|
@@ -347,7 +347,7 @@ program
|
|
|
347
347
|
.option('--use-prefeched-data [location]', 'use prefetched data from local cache file, and force using only cached data')
|
|
348
348
|
.option('--save-rca-locally [path]', 'save root cause analysis assets locally')
|
|
349
349
|
|
|
350
|
-
.option('--exit-code-ignore-failing-tests', '
|
|
350
|
+
.option('--exit-code-ignore-failing-tests', 'return exit code of zero when tests fail. non zero exit code will mean a real error occurred')
|
|
351
351
|
|
|
352
352
|
.option('--intersect-with-label [label]', 'Out of the execution\'s test list, run only those tests that have the specified label', collect, [])
|
|
353
353
|
.option('--intersect-with-suite [suiteName]', 'Out of the execution\'s test list, run only those tests that are included in the specified suite (by suite name)', collect, [])
|
|
@@ -495,6 +495,7 @@ module.exports = {
|
|
|
495
495
|
// non-proxy case
|
|
496
496
|
global.SuperagentProxy = require('superagent-proxy');
|
|
497
497
|
global.ProxyAgent = require('proxy-agent');
|
|
498
|
+
global.HttpsProxyAgent = require('https-proxy-agent');
|
|
498
499
|
}
|
|
499
500
|
|
|
500
501
|
if (program.proxyForGrid && !program.proxy) {
|
|
@@ -833,7 +834,7 @@ module.exports = {
|
|
|
833
834
|
throw new ArgError('after-parallel could not be a negative number or not number, --after-parallel <number-of-tests>');
|
|
834
835
|
}
|
|
835
836
|
|
|
836
|
-
if (![CLI_MODE.EXTENSION, CLI_MODE.SELENIUM].includes(program.mode)) {
|
|
837
|
+
if (![CLI_MODE.EXTENSION, CLI_MODE.SELENIUM, CLI_MODE.APPIUM].includes(program.mode)) {
|
|
837
838
|
throw new ArgError(`runner mode <${program.mode}> is not supported`);
|
|
838
839
|
}
|
|
839
840
|
|
package/runner.js
CHANGED
|
@@ -118,6 +118,14 @@ function setBranch(options, branchInfoFromServer) {
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
async function setSfdcCredential(options) {
|
|
122
|
+
const { projectData: { projectId } } = options;
|
|
123
|
+
const branch = branchService.getCurrentBranch();
|
|
124
|
+
if (_.get(options, 'company.activePlan.premiumFeatures.ttaForSalesforce')) {
|
|
125
|
+
options.sfdcCredential = await servicesApi.loadSfdcCredential({ projectId, branch });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
121
129
|
function setCompany(options, company) {
|
|
122
130
|
const { onprem, id, storageBaseUrl, storageType, name, activePlan = {} } = company;
|
|
123
131
|
if (onprem) {
|
|
@@ -194,6 +202,10 @@ async function setMockNetworkRules(options) {
|
|
|
194
202
|
}
|
|
195
203
|
}
|
|
196
204
|
|
|
205
|
+
/**
|
|
206
|
+
* @param {Awaited<ReturnType<typeof import('./runOptions')['process']>>} options
|
|
207
|
+
* @param {string=} customExtensionLocalLocation
|
|
208
|
+
*/
|
|
197
209
|
async function runRunner(options, customExtensionLocalLocation) {
|
|
198
210
|
perf.log('in runner.js runRunner');
|
|
199
211
|
|
|
@@ -265,6 +277,7 @@ async function init(options) {
|
|
|
265
277
|
setBranch(options, branchName);
|
|
266
278
|
setAllGrids(options, allGrids);
|
|
267
279
|
setAuthData(options, authData);
|
|
280
|
+
await setSfdcCredential(options);
|
|
268
281
|
|
|
269
282
|
if (!(options.lightweightMode && options.lightweightMode.disableLabs)) {
|
|
270
283
|
await labFeaturesService.loadLabFeatures(projectById.id, companyByProjectId.activePlan);
|
|
@@ -23,6 +23,8 @@ class ParallelWorkerManager {
|
|
|
23
23
|
switch (mode) {
|
|
24
24
|
case CLI_MODE.SELENIUM:
|
|
25
25
|
return require('../workers/WorkerSelenium');
|
|
26
|
+
case CLI_MODE.APPIUM:
|
|
27
|
+
return require('../workers/WorkerAppium');
|
|
26
28
|
default:
|
|
27
29
|
if (labFeaturesService.isFeatureAvailableForProject('useSameBrowserForMultiTests')) {
|
|
28
30
|
return require('../workers/WorkerExtensionSingleBrowser');
|