@testim/testim-cli 3.254.0 → 3.255.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/codim/router.test.js +9 -12
- package/agent/routers/codim/service.js +16 -16
- package/agent/routers/playground/service.js +5 -7
- package/cli.js +4 -4
- package/cliAgentMode.js +4 -3
- package/codim/codim-cli.js +10 -8
- package/commons/featureFlags.js +8 -0
- package/commons/httpRequest.js +5 -1
- package/commons/httpRequestCounters.js +21 -10
- package/commons/lazyRequire.js +4 -3
- package/commons/preloadTests.js +2 -2
- package/commons/prepareRunner.js +4 -2
- package/commons/prepareRunnerAndTestimStartUtils.js +40 -41
- package/commons/runnerFileCache.js +1 -1
- package/commons/testimTunnel.test.js +2 -1
- package/coverage/SummaryToObjectReport.js +0 -1
- package/coverage/jsCoverage.js +12 -10
- package/inputFileUtils.js +11 -9
- package/npm-shrinkwrap.json +187 -444
- package/package.json +4 -3
- package/player/services/tabService.js +15 -1
- package/player/stepActions/locateStepAction.js +2 -0
- package/player/utils/imageCaptureUtils.js +81 -120
- package/player/webdriver.js +25 -22
- package/reports/junitReporter.js +6 -7
- package/reports/reporter.js +34 -39
- package/runOptions.d.ts +260 -0
- package/runOptions.js +53 -38
- package/runner.js +2 -1
- package/runners/ParallelWorkerManager.js +9 -10
- package/runners/TestPlanRunner.js +5 -9
- package/services/gridService.js +36 -40
- package/testRunStatus.js +8 -5
- package/utils/argsUtils.js +86 -0
- package/utils/argsUtils.test.js +32 -0
- package/utils/fsUtils.js +154 -0
- package/utils/index.js +10 -161
- package/utils/promiseUtils.js +13 -2
- package/utils/stringUtils.js +4 -2
- package/utils/stringUtils.test.js +22 -0
- package/utils/timeUtils.js +25 -0
- package/utils/utils.test.js +0 -41
- package/workers/WorkerExtension.js +6 -7
package/reports/reporter.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const logger = require('../commons/logger').getLogger('reporter');
|
|
4
|
-
const Promise = require('bluebird');
|
|
5
4
|
|
|
6
5
|
class Reporter {
|
|
7
6
|
setOptions(options, branchToUse) {
|
|
@@ -46,7 +45,7 @@ class Reporter {
|
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
onTestPlanFinished(testResults, testPlanName, startTime, executionId, isAnonymous, isCodeMode, childTestResults) {
|
|
48
|
+
async onTestPlanFinished(testResults, testPlanName, startTime, executionId, isAnonymous, isCodeMode, childTestResults) {
|
|
50
49
|
let results = {};
|
|
51
50
|
|
|
52
51
|
// TODO: remove mutation of testResults from the Reporter
|
|
@@ -68,62 +67,55 @@ class Reporter {
|
|
|
68
67
|
} else {
|
|
69
68
|
results = testResults;
|
|
70
69
|
}
|
|
71
|
-
|
|
72
|
-
return Promise.each(this.reporters, reporter => {
|
|
70
|
+
for (const reporter of this.reporters) {
|
|
73
71
|
if (reporter?.onTestPlanFinished) {
|
|
74
72
|
const duration = Date.now() - (startTime || 0);
|
|
75
|
-
|
|
73
|
+
await reporter.onTestPlanFinished(results, testPlanName, duration, executionId, isAnonymous, isCodeMode);
|
|
76
74
|
}
|
|
77
|
-
|
|
78
|
-
});
|
|
75
|
+
}
|
|
79
76
|
}
|
|
80
77
|
|
|
81
|
-
onTestPlanStarted(beforeTests, tests, afterTests, testPlanName, executionId, isAnonymous, configName, isCodeMode) {
|
|
82
|
-
|
|
78
|
+
async onTestPlanStarted(beforeTests, tests, afterTests, testPlanName, executionId, isAnonymous, configName, isCodeMode) {
|
|
79
|
+
for (const reporter of this.reporters) {
|
|
83
80
|
if (reporter?.onTestPlanStarted) {
|
|
84
|
-
|
|
81
|
+
await reporter.onTestPlanStarted(beforeTests, tests, afterTests, testPlanName, executionId, isAnonymous, configName, isCodeMode);
|
|
85
82
|
}
|
|
86
|
-
|
|
87
|
-
});
|
|
83
|
+
}
|
|
88
84
|
}
|
|
89
85
|
|
|
90
|
-
onGetSlot(workerId, browser) {
|
|
91
|
-
|
|
86
|
+
async onGetSlot(workerId, browser) {
|
|
87
|
+
for (const reporter of this.reporters) {
|
|
92
88
|
if (reporter?.onGetSlot) {
|
|
93
|
-
|
|
89
|
+
await reporter.onGetSlot(workerId, browser);
|
|
94
90
|
}
|
|
95
|
-
|
|
96
|
-
});
|
|
91
|
+
}
|
|
97
92
|
}
|
|
98
93
|
|
|
99
|
-
onGetSession(workerId, testName, mode) {
|
|
100
|
-
|
|
94
|
+
async onGetSession(workerId, testName, mode) {
|
|
95
|
+
for (const reporter of this.reporters) {
|
|
101
96
|
if (reporter?.onGetSession) {
|
|
102
|
-
|
|
97
|
+
await reporter.onGetSession(workerId, testName, mode);
|
|
103
98
|
}
|
|
104
|
-
|
|
105
|
-
});
|
|
99
|
+
}
|
|
106
100
|
}
|
|
107
101
|
|
|
108
|
-
onWaitToTestComplete(workerId, isCodeMode, debuggerAddress) {
|
|
109
|
-
|
|
102
|
+
async onWaitToTestComplete(workerId, isCodeMode, debuggerAddress) {
|
|
103
|
+
for (const reporter of this.reporters) {
|
|
110
104
|
if (reporter?.onWaitToTestComplete) {
|
|
111
|
-
|
|
105
|
+
await reporter.onWaitToTestComplete(workerId, isCodeMode, debuggerAddress);
|
|
112
106
|
}
|
|
113
|
-
|
|
114
|
-
});
|
|
107
|
+
}
|
|
115
108
|
}
|
|
116
109
|
|
|
117
|
-
onWaitToTestStart(workerId) {
|
|
118
|
-
|
|
110
|
+
async onWaitToTestStart(workerId) {
|
|
111
|
+
for (const reporter of this.reporters) {
|
|
119
112
|
if (reporter?.onWaitToTestStart) {
|
|
120
|
-
|
|
113
|
+
await reporter.onWaitToTestStart(workerId);
|
|
121
114
|
}
|
|
122
|
-
|
|
123
|
-
});
|
|
115
|
+
}
|
|
124
116
|
}
|
|
125
117
|
|
|
126
|
-
onAllTestPlansFinished(testPlanResults) {
|
|
118
|
+
async onAllTestPlansFinished(testPlanResults) {
|
|
127
119
|
// TODO: remove mutation of testPlanResults from the Reporter
|
|
128
120
|
for (const result of testPlanResults) {
|
|
129
121
|
if (result.childTestResults) {
|
|
@@ -140,18 +132,21 @@ class Reporter {
|
|
|
140
132
|
}
|
|
141
133
|
}
|
|
142
134
|
|
|
143
|
-
|
|
135
|
+
for (const reporter of this.reporters) {
|
|
144
136
|
if (reporter?.onAllTestPlansFinished) {
|
|
145
|
-
|
|
137
|
+
await reporter.onAllTestPlansFinished(testPlanResults);
|
|
146
138
|
}
|
|
147
|
-
|
|
148
|
-
});
|
|
139
|
+
}
|
|
149
140
|
}
|
|
150
141
|
}
|
|
151
142
|
|
|
152
143
|
function addHook(name) {
|
|
153
|
-
Reporter.prototype[name] = function (...args) {
|
|
154
|
-
|
|
144
|
+
Reporter.prototype[name] = async function (...args) {
|
|
145
|
+
for (const reporter of this.reporters) {
|
|
146
|
+
if (reporter?.[name]) {
|
|
147
|
+
await reporter[name](...args);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
155
150
|
};
|
|
156
151
|
}
|
|
157
152
|
|
package/runOptions.d.ts
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
interface LoginModeOptions {
|
|
2
|
+
loginMode: true;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
interface InitModeOptions {
|
|
6
|
+
initCodimMode: true;
|
|
7
|
+
initTestProject: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface AgentModeOptions {
|
|
11
|
+
agentMode: true;
|
|
12
|
+
project?: string;
|
|
13
|
+
token?: string;
|
|
14
|
+
agentPort: number;
|
|
15
|
+
agentBind?: string;
|
|
16
|
+
openEditor?: boolean;
|
|
17
|
+
installPlaygroundPlaywrightDeps: boolean;
|
|
18
|
+
installPlaygroundPuppeteerDeps: boolean;
|
|
19
|
+
installPlaygroundSeleniumDeps: boolean;
|
|
20
|
+
startTestimBrowser: boolean;
|
|
21
|
+
ext?: string;
|
|
22
|
+
extensionPath?: string;
|
|
23
|
+
playerLocation: string;
|
|
24
|
+
canary?: boolean;
|
|
25
|
+
playerPath?: string;
|
|
26
|
+
playerRequirePath?: string;
|
|
27
|
+
downloadBrowser: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface TunnelDaemonOptions {
|
|
31
|
+
tunnelOnlyMode: true;
|
|
32
|
+
tunnelRoutes: string[];
|
|
33
|
+
tunnelRoutesOutput: string;
|
|
34
|
+
tunnelHostHeader?: string;
|
|
35
|
+
tunnelRegion?: string;
|
|
36
|
+
}
|
|
37
|
+
interface NgrokTunnelOptions {
|
|
38
|
+
tunnelPort: number;
|
|
39
|
+
tunnelDiagnostics?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type TunnelOptions = (TunnelDaemonOptions | NgrokTunnelOptions) & {
|
|
43
|
+
tunnel: true;
|
|
44
|
+
tunnelUseHttpAddress?: boolean;
|
|
45
|
+
token: string;
|
|
46
|
+
project: string;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
type CodeCoverageReporter = 'clover' | 'html' | 'json-summary' | 'json' | 'lcov' | 'lcovonly' | 'teamcity' | 'text-lcov' | 'text-summary' | 'text';
|
|
50
|
+
|
|
51
|
+
interface LightweightSettings {
|
|
52
|
+
type: 'lightweight' | 'turboMode';
|
|
53
|
+
general: boolean;
|
|
54
|
+
disableLabs: boolean;
|
|
55
|
+
disableFeatureFlags: boolean;
|
|
56
|
+
disableAssets: boolean;
|
|
57
|
+
disablePixelValidation: boolean;
|
|
58
|
+
disableResults: boolean;
|
|
59
|
+
disableStepDelay: boolean;
|
|
60
|
+
disableRemoteStep: boolean;
|
|
61
|
+
assumePreloadedSharedSteps: boolean;
|
|
62
|
+
disableVisibilityCheck: boolean;
|
|
63
|
+
disableLocators: boolean;
|
|
64
|
+
bypassSetup: boolean;
|
|
65
|
+
disableAutoImprove: boolean;
|
|
66
|
+
disableQuotaBlocking: boolean;
|
|
67
|
+
onlyTestIdsNoSuite: boolean;
|
|
68
|
+
uploadAssetsAndResultsOnFailure: boolean;
|
|
69
|
+
preloadTests: boolean;
|
|
70
|
+
disableProjectDefaults: boolean;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// TODO: consider typing better, based on the validations we do (example: must have one of grid/grid-id/host&port/test plan)
|
|
74
|
+
interface RunnerOptions extends Partial<Omit<TunnelOptions, 'tunnelOnlyMode' | 'tunnel'>> {
|
|
75
|
+
token: string;
|
|
76
|
+
project: string;
|
|
77
|
+
user?: string;
|
|
78
|
+
webpackConfig?: string;
|
|
79
|
+
headless?: boolean;
|
|
80
|
+
disableNativeEvents?: boolean;
|
|
81
|
+
baseUrl?: string;
|
|
82
|
+
branch: string;
|
|
83
|
+
autoDetect: boolean;
|
|
84
|
+
userParamsData: object;
|
|
85
|
+
mode: 'selenium' | 'extension';
|
|
86
|
+
isRegressionBaselineRun?: boolean;
|
|
87
|
+
canary?: boolean;
|
|
88
|
+
rerunFailedByRunId?: string;
|
|
89
|
+
disableTimeoutRetry?: boolean;
|
|
90
|
+
resultLabels: string[];
|
|
91
|
+
path?: string;
|
|
92
|
+
protocol?: string;
|
|
93
|
+
testobjectSauce: { testobjectApiKey?: string };
|
|
94
|
+
overrideExecutionName?: string;
|
|
95
|
+
passZeroTests: boolean;
|
|
96
|
+
runQuarantinedTests: boolean;
|
|
97
|
+
downloadBrowser: boolean;
|
|
98
|
+
disableSockets: boolean;
|
|
99
|
+
disableCookiesSameSiteNoneRequiresSecure: boolean;
|
|
100
|
+
shouldMonitorPerformance?: boolean;
|
|
101
|
+
exitCodeIgnoreFailingTests?: boolean;
|
|
102
|
+
seleniumCapsFileContent: object;
|
|
103
|
+
retentionDays?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
|
|
104
|
+
retries?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20;
|
|
105
|
+
|
|
106
|
+
// #region What to execute
|
|
107
|
+
testId: string[];
|
|
108
|
+
name: string[];
|
|
109
|
+
label: string[];
|
|
110
|
+
suites: string[];
|
|
111
|
+
suiteIds: string[];
|
|
112
|
+
testPlan: string[];
|
|
113
|
+
testPlanIds: string[];
|
|
114
|
+
files: string[];
|
|
115
|
+
// #endregion
|
|
116
|
+
|
|
117
|
+
// #region Test config to use
|
|
118
|
+
testConfigNames?: string[];
|
|
119
|
+
testConfigIds?: string[];
|
|
120
|
+
// #endregion
|
|
121
|
+
|
|
122
|
+
// #region Grid details
|
|
123
|
+
grid?: string;
|
|
124
|
+
gridId?: string;
|
|
125
|
+
host?: string;
|
|
126
|
+
port?: number;
|
|
127
|
+
gridUsername?: string;
|
|
128
|
+
gridPassword?: string;
|
|
129
|
+
useLocalChromeDriver?: boolean;
|
|
130
|
+
chromeBinaryLocation?: string;
|
|
131
|
+
useChromeLauncher?: boolean;
|
|
132
|
+
|
|
133
|
+
disableGridCheck: boolean;
|
|
134
|
+
browser?: 'ie11' | 'ie' | 'internet explorer' | 'edge' | 'edge-chromium' | 'firefox' | 'safari' | 'chrome';
|
|
135
|
+
|
|
136
|
+
proxyForGrid: string;
|
|
137
|
+
|
|
138
|
+
experitestToken?: string;
|
|
139
|
+
saucelabs: { username: string; accessKey: string };
|
|
140
|
+
perfecto: { securityToken?: string; location?: string };
|
|
141
|
+
browserstack: { 'browserstack.user': string; 'browserstack.key': string };
|
|
142
|
+
// #endregion
|
|
143
|
+
|
|
144
|
+
// #region Report settings
|
|
145
|
+
reportFile?: string;
|
|
146
|
+
reportFileClassname?: string;
|
|
147
|
+
reporters?: string[];
|
|
148
|
+
// #endregion
|
|
149
|
+
|
|
150
|
+
// #region Parallel settings
|
|
151
|
+
beforeParallel: number;
|
|
152
|
+
parallel: number;
|
|
153
|
+
afterParallel: number;
|
|
154
|
+
//#endregion
|
|
155
|
+
|
|
156
|
+
// #region TMS
|
|
157
|
+
tmsSuppressReporting: boolean;
|
|
158
|
+
tmsRunId?: string;
|
|
159
|
+
tmsCustomFields?: string;
|
|
160
|
+
// #endregion
|
|
161
|
+
|
|
162
|
+
// #region Extension debugging
|
|
163
|
+
ext?: string;
|
|
164
|
+
extensionLocation?: string[];
|
|
165
|
+
extensionPath?: string;
|
|
166
|
+
// #endregion
|
|
167
|
+
|
|
168
|
+
// #region Session Player debugging
|
|
169
|
+
playerLocation: string;
|
|
170
|
+
playerPath?: string;
|
|
171
|
+
playerRequirePath?: string;
|
|
172
|
+
// #endregion
|
|
173
|
+
|
|
174
|
+
// #region Tunnel
|
|
175
|
+
tunnel?: boolean;
|
|
176
|
+
externalLambdatestTunnelId?: string;
|
|
177
|
+
externalLambdatestUseWss?: string;
|
|
178
|
+
externalLambdatestDisableAutomationTunneling: boolean;
|
|
179
|
+
externalLambdatestMitm: boolean;
|
|
180
|
+
// #endregion
|
|
181
|
+
|
|
182
|
+
// #region Hooks
|
|
183
|
+
beforeTest?: Function;
|
|
184
|
+
afterTest?: Function;
|
|
185
|
+
beforeSuite?: Function;
|
|
186
|
+
afterSuite?: Function;
|
|
187
|
+
// #endregion
|
|
188
|
+
|
|
189
|
+
// #region Timeouts
|
|
190
|
+
testStartTimeout: number;
|
|
191
|
+
timeout: number;
|
|
192
|
+
timeoutWasGiven: boolean;
|
|
193
|
+
browserTimeout: number;
|
|
194
|
+
newBrowserWaitTimeout: number;
|
|
195
|
+
getBrowserTimeout: number;
|
|
196
|
+
getBrowserRetries: number;
|
|
197
|
+
getSessionTimeout: number;
|
|
198
|
+
getSessionRetries: number;
|
|
199
|
+
driverRequestTimeout: number;
|
|
200
|
+
driverRequestRetries: number;
|
|
201
|
+
// #endregion
|
|
202
|
+
|
|
203
|
+
// #region Mock network
|
|
204
|
+
overrideMappingFile?: string;
|
|
205
|
+
mockNetworkRules?: object;
|
|
206
|
+
disableMockNetwork?: boolean;
|
|
207
|
+
// #endregion
|
|
208
|
+
|
|
209
|
+
// #region Code coverage
|
|
210
|
+
codeCoverageUrlFilter?: string;
|
|
211
|
+
collectCodeCoverage?: boolean;
|
|
212
|
+
codeCoverageReportPath?: string;
|
|
213
|
+
codeCoverageSourceMapPath?: string;
|
|
214
|
+
codeCoverageReporter: CodeCoverageReporter[];
|
|
215
|
+
codeCoverageInclude: string[];
|
|
216
|
+
// #endregion
|
|
217
|
+
|
|
218
|
+
// #region Remote run options
|
|
219
|
+
executionId?: string;
|
|
220
|
+
remoteRunId?: string;
|
|
221
|
+
schedulerId?: string;
|
|
222
|
+
source?: string;
|
|
223
|
+
resultId?: string;
|
|
224
|
+
// #endregion
|
|
225
|
+
|
|
226
|
+
// #region Customer Extension
|
|
227
|
+
installCustomExtension?: string;
|
|
228
|
+
// #endregion
|
|
229
|
+
|
|
230
|
+
// #region Capabilities format
|
|
231
|
+
w3cCapabilities: boolean;
|
|
232
|
+
oldCapabilities: boolean;
|
|
233
|
+
// #endregion
|
|
234
|
+
|
|
235
|
+
// #region Chrome specific settings
|
|
236
|
+
chromeBlockLocation: boolean;
|
|
237
|
+
chromeUserDataDir: false | string;
|
|
238
|
+
chromeExtraPrefs: object;
|
|
239
|
+
chromeExtraArgs: string[];
|
|
240
|
+
// #endregion
|
|
241
|
+
|
|
242
|
+
// #region Lightweight / Turbo Mode
|
|
243
|
+
lightweightMode?: LightweightSettings;
|
|
244
|
+
createPrefechedData?: boolean;
|
|
245
|
+
saveRCALocally?: boolean | string;
|
|
246
|
+
// #endregion
|
|
247
|
+
|
|
248
|
+
// #region intersections
|
|
249
|
+
intersections: { labels?: string[]; suiteNames?: string[]; suiteIds?: string[] };
|
|
250
|
+
// #endregion
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
type Options = |
|
|
254
|
+
LoginModeOptions |
|
|
255
|
+
InitModeOptions |
|
|
256
|
+
AgentModeOptions |
|
|
257
|
+
TunnelOptions |
|
|
258
|
+
RunnerOptions;
|
|
259
|
+
|
|
260
|
+
export function process(): Promise<Options>;
|
package/runOptions.js
CHANGED
|
@@ -2,22 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
const { CLI_MODE } = require('./commons/constants');
|
|
6
|
-
const { EDGE_CHROMIUM_MIN_VERSION } = require('./player/constants');
|
|
7
|
-
const program = require('commander');
|
|
8
5
|
const fs = require('fs');
|
|
9
6
|
const ms = require('ms');
|
|
10
|
-
const Promise = require('bluebird');
|
|
11
|
-
const NoArgsError = require('./errors.js').NoArgsError;
|
|
12
|
-
const ArgError = require('./errors.js').ArgError;
|
|
13
7
|
const url = require('url');
|
|
14
8
|
const _ = require('lodash');
|
|
15
9
|
const path = require('path');
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
const program = require('commander');
|
|
16
12
|
const utils = require('./utils');
|
|
17
|
-
const runOptionsAgentFlow = require('./runOptionsAgentFlow');
|
|
18
13
|
const runOptionsUtils = require('./runOptionsUtils');
|
|
14
|
+
const runOptionsAgentFlow = require('./runOptionsAgentFlow');
|
|
19
15
|
const localRunnerCache = require('./commons/runnerFileCache');
|
|
20
|
-
const
|
|
16
|
+
const { CLI_MODE } = require('./commons/constants');
|
|
17
|
+
const { NoArgsError, ArgError } = require('./errors');
|
|
18
|
+
const { EDGE_CHROMIUM_MIN_VERSION } = require('./player/constants');
|
|
21
19
|
|
|
22
20
|
const camelizeHyphenValues = (prop) => prop.replace(/-([a-z])/g, (m, w) => w.toUpperCase());
|
|
23
21
|
|
|
@@ -114,6 +112,10 @@ const printUsage = () => {
|
|
|
114
112
|
return line.includes('--high-speed'); // high speed mode was renamed to turbo mode
|
|
115
113
|
}
|
|
116
114
|
|
|
115
|
+
function isTestStartTimeout(line) {
|
|
116
|
+
return line.includes('--test-start-timeout');
|
|
117
|
+
}
|
|
118
|
+
|
|
117
119
|
program.help((txt) => {
|
|
118
120
|
const lines = txt.split('\n');
|
|
119
121
|
return lines
|
|
@@ -129,7 +131,8 @@ const printUsage = () => {
|
|
|
129
131
|
!isWebdriverTimeout(ln) &&
|
|
130
132
|
!isSaveRCALocally(ln) &&
|
|
131
133
|
!isExitCodeIgnoreFailingTests(ln) &&
|
|
132
|
-
!isDeprecatedHighSpeed(ln)
|
|
134
|
+
!isDeprecatedHighSpeed(ln) &&
|
|
135
|
+
!isTestStartTimeout(ln)
|
|
133
136
|
)
|
|
134
137
|
.join('\n');
|
|
135
138
|
});
|
|
@@ -217,17 +220,18 @@ program
|
|
|
217
220
|
.option('--file-cache-location [directory]', ' internal CLI file caching location')
|
|
218
221
|
|
|
219
222
|
// Timeout
|
|
220
|
-
.option('--timeout [test-timeout]', 'test
|
|
221
|
-
.option('--
|
|
222
|
-
.option('--
|
|
223
|
+
.option('--test-start-timeout [test-start-timeout]', 'The time to wait for a test to start after getting a browser session', Number, Number(process.env.TESTIM_TEST_START_TIMEOUT) || (2 * 60 * 1000))
|
|
224
|
+
.option('--timeout [test-timeout]', 'Test run timeout in milliseconds', Number)
|
|
225
|
+
.option('--browser-timeout [open-browser-timeout]', 'Get browser from grid timeout in milliseconds', Number)
|
|
226
|
+
.option('--new-browser-wait-timeout [max-wait-to-browser]', 'Maximum get browser wait in minutes', Number)
|
|
223
227
|
|
|
224
228
|
// New Timeouts
|
|
225
|
-
.option('--get-browser-timeout [get-browser-timeout]', 'Timeout for a single attempt to get browser from the grid configured in the project\'s plan') // getBrowserTimeout
|
|
226
|
-
.option('--get-browser-retries [get-browser-retries]', 'Number of attempts to get browser from the grid configured in the project\'s plan') // getBrowserRetries
|
|
227
|
-
.option('--get-session-timeout [get-session-timeout]', 'Timeout for "/session" request to the selenium server', ms('90s')) // getSessionTimeout
|
|
228
|
-
.option('--get-session-retries [get-session-retries]', 'Retries for "/session" request to the selenium server', 3) // getSessionRetries
|
|
229
|
-
.option('--driver-request-timeout [driver-request-timeout]', 'Timeout for any WebDriver request to the grid server', ms('90s')) // driverRequestTimeout
|
|
230
|
-
.option('--driver-request-retries [driver-request-retries]', 'Retries for any WebDriver request to the grid server', 3) // driverRequestRetries
|
|
229
|
+
.option('--get-browser-timeout [get-browser-timeout]', 'Timeout for a single attempt to get browser from the grid configured in the project\'s plan', Number) // getBrowserTimeout
|
|
230
|
+
.option('--get-browser-retries [get-browser-retries]', 'Number of attempts to get browser from the grid configured in the project\'s plan', Number) // getBrowserRetries
|
|
231
|
+
.option('--get-session-timeout [get-session-timeout]', 'Timeout for "/session" request to the selenium server', Number, ms('90s')) // getSessionTimeout
|
|
232
|
+
.option('--get-session-retries [get-session-retries]', 'Retries for "/session" request to the selenium server', Number, 3) // getSessionRetries
|
|
233
|
+
.option('--driver-request-timeout [driver-request-timeout]', 'Timeout for any WebDriver request to the grid server', Number, ms('90s')) // driverRequestTimeout
|
|
234
|
+
.option('--driver-request-retries [driver-request-retries]', 'Retries for any WebDriver request to the grid server', Number, 3) // driverRequestRetries
|
|
231
235
|
|
|
232
236
|
// Run chrome ext mode locally
|
|
233
237
|
.option('--use-local-chrome-driver [use-local-chrome-driver]', 'use a local ChromeDriver instance instead of a selenium grid')
|
|
@@ -510,8 +514,10 @@ module.exports = {
|
|
|
510
514
|
try {
|
|
511
515
|
let options = {};
|
|
512
516
|
if (program.configFile) {
|
|
517
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
513
518
|
options = require(path.join(process.cwd(), program.configFile)).config;
|
|
514
519
|
} else if (program.optionsFile) {
|
|
520
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
515
521
|
options = require(path.join(process.cwd(), program.optionsFile));
|
|
516
522
|
}
|
|
517
523
|
|
|
@@ -546,19 +552,20 @@ module.exports = {
|
|
|
546
552
|
}
|
|
547
553
|
|
|
548
554
|
|
|
549
|
-
const isTestConfigSpecified =
|
|
550
|
-
const isTestPlanSpecified =
|
|
551
|
-
const isSuiteSpecified =
|
|
555
|
+
const isTestConfigSpecified = program.testConfig?.length || program.testConfigId?.length;
|
|
556
|
+
const isTestPlanSpecified = program.testPlan?.length || program.testPlanId?.length;
|
|
557
|
+
const isSuiteSpecified = program.suite?.length || program.suiteId?.length;
|
|
552
558
|
|
|
553
559
|
if (program.seleniumCapsFile) {
|
|
554
560
|
try {
|
|
561
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
555
562
|
seleniumCapsFileContent = require(path.join(process.cwd(), program.seleniumCapsFile));
|
|
556
563
|
} catch (err) {
|
|
557
|
-
|
|
564
|
+
throw new ArgError(`Failed to parse selenium caps file file error: ${err.message}`);
|
|
558
565
|
}
|
|
559
566
|
}
|
|
560
567
|
|
|
561
|
-
if (program.reporters
|
|
568
|
+
if (program.reporters?.includes('junit') && !program.reportFile) {
|
|
562
569
|
console.log('Warning: please define --report-file option for JUnit reporter');
|
|
563
570
|
}
|
|
564
571
|
|
|
@@ -575,9 +582,10 @@ module.exports = {
|
|
|
575
582
|
}
|
|
576
583
|
if (program.chromeExtraPrefs) {
|
|
577
584
|
try {
|
|
585
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
578
586
|
chromeExtraPrefs = require(path.join(process.cwd(), program.chromeExtraPrefs));
|
|
579
587
|
} catch (err) {
|
|
580
|
-
|
|
588
|
+
throw new ArgError(`Failed to read/open chrome extra prefs file error: ${err.message}`);
|
|
581
589
|
}
|
|
582
590
|
}
|
|
583
591
|
|
|
@@ -598,9 +606,10 @@ module.exports = {
|
|
|
598
606
|
|
|
599
607
|
if (program.paramsFile) {
|
|
600
608
|
try {
|
|
609
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
601
610
|
userParamsData = Object.assign({}, userParamsData, require(path.join(process.cwd(), program.paramsFile)));
|
|
602
611
|
} catch (err) {
|
|
603
|
-
|
|
612
|
+
throw new ArgError(`Failed to read/open params file error: ${err.message}`);
|
|
604
613
|
}
|
|
605
614
|
}
|
|
606
615
|
|
|
@@ -608,7 +617,7 @@ module.exports = {
|
|
|
608
617
|
try {
|
|
609
618
|
userParamsData = Object.assign({}, userParamsData, JSON.parse(program.params));
|
|
610
619
|
} catch (err) {
|
|
611
|
-
|
|
620
|
+
throw new ArgError(`Failed to parse params string error: ${err.message}`);
|
|
612
621
|
}
|
|
613
622
|
}
|
|
614
623
|
|
|
@@ -627,6 +636,7 @@ module.exports = {
|
|
|
627
636
|
|
|
628
637
|
if (program.sauceOptions) {
|
|
629
638
|
try {
|
|
639
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
630
640
|
const sOptions = require(path.join(process.cwd(), program.sauceOptions));
|
|
631
641
|
const isMobile = sOptions.platformName && ['ios', 'android'].includes(sOptions.platformName.toLowerCase());
|
|
632
642
|
if (sOptions.browserName) {
|
|
@@ -649,12 +659,12 @@ module.exports = {
|
|
|
649
659
|
|
|
650
660
|
const isBadVersion = parseFloat(sOptions.version) < 50 && !['dev', 'beta'].includes(sOptions.version);
|
|
651
661
|
if (!isMobile && program.browser === 'chrome' && isBadVersion) {
|
|
652
|
-
|
|
662
|
+
throw new ArgError('The minimum chrome supported version is 50.0');
|
|
653
663
|
}
|
|
654
664
|
|
|
655
665
|
program.saucelabs = Object.assign({}, program.saucelabs, sOptions);
|
|
656
666
|
} catch (err) {
|
|
657
|
-
|
|
667
|
+
throw new ArgError(`Failed to parse saucelabs options file error: ${err.message}`);
|
|
658
668
|
}
|
|
659
669
|
}
|
|
660
670
|
|
|
@@ -672,6 +682,7 @@ module.exports = {
|
|
|
672
682
|
|
|
673
683
|
if (program.browserstackOptions) {
|
|
674
684
|
try {
|
|
685
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
675
686
|
const bsOptions = require(path.join(process.cwd(), program.browserstackOptions));
|
|
676
687
|
const isMobile = bsOptions.platform && ['mac', 'android'].includes(bsOptions.platform.toLowerCase());
|
|
677
688
|
if (bsOptions.browserName) {
|
|
@@ -683,12 +694,12 @@ module.exports = {
|
|
|
683
694
|
}
|
|
684
695
|
|
|
685
696
|
if (!isMobile && parseFloat(bsOptions.browser_version) < 50 && program.browser === 'chrome') {
|
|
686
|
-
|
|
697
|
+
throw new ArgError('The minimum chrome supported version is 50.0');
|
|
687
698
|
}
|
|
688
699
|
|
|
689
700
|
program.browserstack = Object.assign({}, program.browserstack, bsOptions);
|
|
690
701
|
} catch (err) {
|
|
691
|
-
|
|
702
|
+
throw new ArgError(`Failed to parse browserstack options file error: ${err.message}`);
|
|
692
703
|
}
|
|
693
704
|
}
|
|
694
705
|
|
|
@@ -700,11 +711,12 @@ module.exports = {
|
|
|
700
711
|
|
|
701
712
|
if (program.perfectoOptions) {
|
|
702
713
|
try {
|
|
714
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
703
715
|
const perfectoOptions = require(path.join(process.cwd(), program.perfectoOptions));
|
|
704
716
|
const DEFAULTS = { location: 'US East', securityToken: program.perfectoToken };
|
|
705
717
|
program.perfecto = Object.assign({}, DEFAULTS, perfectoOptions);
|
|
706
718
|
} catch (err) {
|
|
707
|
-
|
|
719
|
+
throw new ArgError(`Failed to parse perfecto options file error: ${err.message}`);
|
|
708
720
|
}
|
|
709
721
|
}
|
|
710
722
|
|
|
@@ -716,11 +728,12 @@ module.exports = {
|
|
|
716
728
|
|
|
717
729
|
if (program.testobjectOptions) {
|
|
718
730
|
try {
|
|
731
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
719
732
|
const testobjectOptions = require(path.join(process.cwd(), program.testobjectOptions));
|
|
720
733
|
const DEFAULTS = { testobjectApiKey: program.testobjectKey };
|
|
721
734
|
program.testobjectSauce = Object.assign({}, DEFAULTS, testobjectOptions);
|
|
722
735
|
} catch (err) {
|
|
723
|
-
|
|
736
|
+
throw new ArgError(`Failed to parse test object options file error: ${err.message}`);
|
|
724
737
|
}
|
|
725
738
|
}
|
|
726
739
|
|
|
@@ -751,8 +764,8 @@ module.exports = {
|
|
|
751
764
|
}
|
|
752
765
|
|
|
753
766
|
program.retries = !program.retries || typeof program.retries === 'boolean' ? 1 : Number(program.retries) + 1;
|
|
754
|
-
program.browserTimeout = !program.browserTimeout || typeof program.browserTimeout === 'boolean' ? 60 * 1000 :
|
|
755
|
-
program.newBrowserWaitTimeout = !program.newBrowserWaitTimeout || typeof program.newBrowserWaitTimeout === 'boolean' ? 10 * 60 * 1000 :
|
|
767
|
+
program.browserTimeout = !program.browserTimeout || typeof program.browserTimeout === 'boolean' ? 60 * 1000 : program.browserTimeout;
|
|
768
|
+
program.newBrowserWaitTimeout = !program.newBrowserWaitTimeout || typeof program.newBrowserWaitTimeout === 'boolean' ? 10 * 60 * 1000 : program.newBrowserWaitTimeout * 60 * 1000;
|
|
756
769
|
|
|
757
770
|
if (!program.getBrowserTimeout) {
|
|
758
771
|
program.getBrowserTimeout = program.browserTimeout;
|
|
@@ -764,7 +777,7 @@ module.exports = {
|
|
|
764
777
|
program.driverRequestTimeout = program.browserTimeout < program.driverRequestTimeout ? program.driverRequestTimeout : program.browserTimeout;
|
|
765
778
|
|
|
766
779
|
const timeoutWasGiven = Boolean(program.timeout);
|
|
767
|
-
program.timeout = !program.timeout || typeof program.timeout === 'boolean' ? 10 * 60 * 1000 :
|
|
780
|
+
program.timeout = !program.timeout || typeof program.timeout === 'boolean' ? 10 * 60 * 1000 : program.timeout;
|
|
768
781
|
program.beforeParallel = !program.beforeParallel || typeof program.beforeParallel === 'boolean' ? 1 : Number(program.beforeParallel);
|
|
769
782
|
program.parallel = !program.parallel || typeof program.parallel === 'boolean' ? 1 : Number(program.parallel);
|
|
770
783
|
program.afterParallel = !program.afterParallel || typeof program.afterParallel === 'boolean' ? 1 : Number(program.afterParallel);
|
|
@@ -901,7 +914,7 @@ module.exports = {
|
|
|
901
914
|
throw new ArgError('please define exactly one of --grid or --grid-id or --host');
|
|
902
915
|
}
|
|
903
916
|
|
|
904
|
-
if (program.host
|
|
917
|
+
if (program.host?.includes('/')) {
|
|
905
918
|
if (!/^(f|ht)tps?:\/\//i.test(program.host)) {
|
|
906
919
|
program.host = `http://${program.host}`;
|
|
907
920
|
}
|
|
@@ -1009,7 +1022,7 @@ module.exports = {
|
|
|
1009
1022
|
const fileContent = fs.readFileSync(program.tmsFieldFile);
|
|
1010
1023
|
program.tmsCustomFields = JSON.parse(fileContent);
|
|
1011
1024
|
} catch (err) {
|
|
1012
|
-
|
|
1025
|
+
throw new ArgError(`failed to parse field file error: ${err.message}`);
|
|
1013
1026
|
}
|
|
1014
1027
|
}
|
|
1015
1028
|
|
|
@@ -1046,7 +1059,7 @@ module.exports = {
|
|
|
1046
1059
|
const lightweightModeOptions = typeof program.lightweightMode === 'string' ? JSON.parse(program.lightweightMode) : {};
|
|
1047
1060
|
program.lightweightMode = Object.assign({}, DEFAULTS, lightweightModeOptions);
|
|
1048
1061
|
} catch (err) {
|
|
1049
|
-
|
|
1062
|
+
throw new ArgError(`failed to parse lightweightMode settings error: ${err.message}`);
|
|
1050
1063
|
}
|
|
1051
1064
|
} else if (program.turboMode && program.mode === CLI_MODE.EXTENSION) {
|
|
1052
1065
|
program.lightweightMode = {
|
|
@@ -1179,6 +1192,8 @@ module.exports = {
|
|
|
1179
1192
|
driverRequestTimeout: program.driverRequestTimeout,
|
|
1180
1193
|
driverRequestRetries: program.driverRequestRetries,
|
|
1181
1194
|
|
|
1195
|
+
testStartTimeout: program.testStartTimeout,
|
|
1196
|
+
|
|
1182
1197
|
testConfigNames: program.testConfig,
|
|
1183
1198
|
testConfigIds: program.testConfigId,
|
|
1184
1199
|
|