@testim/testim-cli 3.225.0 → 3.228.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/codim/codim-npm-package/package.json +1 -1
- package/codim/template.js/package.json +1 -1
- package/codim/template.ts/package.json +2 -2
- package/commons/testimDesiredCapabilitiesBuilder.js +1 -0
- package/npm-shrinkwrap.json +1111 -1587
- package/package.json +22 -22
- package/services/gridService.js +1 -19
- package/testRunHandler.js +491 -486
- package/testRunStatus.js +5 -3
- package/workers/BaseWorker.js +7 -7
- package/workers/BaseWorker.test.js +37 -3
- package/workers/WorkerExtensionSingleBrowser.js +2 -1
package/testRunHandler.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const _ = require('lodash');
|
|
3
4
|
const testimCustomToken = require('./commons/testimCustomToken');
|
|
4
5
|
const remoteStepService = require('./commons/socket/remoteStepService');
|
|
5
6
|
const testResultService = require('./commons/socket/testResultService');
|
|
@@ -9,7 +10,6 @@ const logger = require('./commons/logger').getLogger('test-run-handler');
|
|
|
9
10
|
const perf = require('./commons/performance-logger');
|
|
10
11
|
const { URL } = require('url');
|
|
11
12
|
const Promise = require('bluebird');
|
|
12
|
-
const _ = require('lodash');
|
|
13
13
|
const remoteStepPlayback = require('./stepPlayers/remoteStepPlayback');
|
|
14
14
|
const utils = require('./utils');
|
|
15
15
|
const config = require('./commons/config');
|
|
@@ -21,555 +21,560 @@ const RETRIES_ON_TIMEOUT = 3;
|
|
|
21
21
|
const MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE = 20 * 1000; // max size, in characters, of stringified run data sent over URL params. Chosen arbitrarily, this value should be changed according to data.
|
|
22
22
|
const canSendRunDataOverUrl = (runData) => JSON.stringify(runData).length < MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE;
|
|
23
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
|
-
|
|
51
|
-
TestRun.prototype.waitForExecutionStartedFinished = function () {
|
|
52
|
-
return this._testRunStatus.waitForExecutionStartedFinished() && this.clearTestResultFinished;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
TestRun.prototype.getTestStatus = function () {
|
|
56
|
-
return this._testStatus;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
TestRun.prototype.getRunMode = function () {
|
|
60
|
-
return this._options.mode;
|
|
61
|
-
};
|
|
62
|
-
TestRun.prototype.getAutomationMode = function () {
|
|
63
|
-
return this._code ? 'codeful' : 'codeless';
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
TestRun.prototype.getCode = function () {
|
|
67
|
-
return this._code;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
TestRun.prototype.getRunConfig = function () {
|
|
71
|
-
return this._runConfig;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
TestRun.prototype.getTestResultId = function () {
|
|
75
|
-
return this._testResultId;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
TestRun.prototype.getBaseUrl = function () {
|
|
79
|
-
return this._baseUrl;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
TestRun.prototype.getExecutionId = function () {
|
|
83
|
-
return this._executionId;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
TestRun.prototype.getExecutionName = function () {
|
|
87
|
-
return this._executionName;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
TestRun.prototype.getNativeAppData = function () {
|
|
91
|
-
if (this._nativeApp && !this._options.baseUrl) {
|
|
92
|
-
return this._nativeApp;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const url = this._options.baseUrl || this.getBaseUrl();
|
|
96
|
-
if (!url) {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const [packageName, activity] = url.split(':');
|
|
101
|
-
return {
|
|
102
|
-
packageName,
|
|
103
|
-
activity,
|
|
104
|
-
};
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
TestRun.prototype.getBranch = function () {
|
|
108
|
-
return this._branch;
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
TestRun.prototype.getRemoteRunId = function () {
|
|
112
|
-
return this._remoteRunId;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
TestRun.prototype.getOverrideTestConfigId = function () {
|
|
116
|
-
return this._overrideTestConfigId;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
TestRun.prototype.markClearBrowser = function () {
|
|
120
|
-
this.clearBrowser = true;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
TestRun.prototype.getRunRequestParams = async function () {
|
|
125
|
-
const customTokenV3 = await testimCustomToken.getCustomTokenV3();
|
|
126
|
-
const runRequestParams = {
|
|
127
|
-
tokenV3: customTokenV3,
|
|
128
|
-
refreshToken: testimCustomToken.getRefreshToken(),
|
|
129
|
-
projectId: this._options.project,
|
|
130
|
-
executionId: this._executionId,
|
|
131
|
-
executionName: this._executionName,
|
|
132
|
-
testId: this._testId,
|
|
133
|
-
resultId: this._testResultId,
|
|
134
|
-
baseUrl: this._baseUrl,
|
|
135
|
-
branch: this._branch,
|
|
136
|
-
servicesUrl: config.EXTENSION_SERVICES_HOST,
|
|
137
|
-
remoteRunId: this.getRemoteRunId(),
|
|
138
|
-
previousTestResultId: this.getPreviousTestResultId(),
|
|
139
|
-
testRetryCount: this.getRetryCount(),
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
if (this._code) {
|
|
143
|
-
runRequestParams.isCodeMode = true;
|
|
144
|
-
runRequestParams.testName = this._testName;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (this._options.shouldMonitorPerformance) {
|
|
148
|
-
runRequestParams.shouldMonitorPerformance = true;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (this._options.company) {
|
|
152
|
-
runRequestParams.companyId = this._options.company.companyId;
|
|
153
|
-
runRequestParams.onprem = this._options.company.onprem;
|
|
154
|
-
runRequestParams.storageBaseUrl = this._options.company.storageBaseUrl;
|
|
155
|
-
runRequestParams.storageType = this._options.company.storageType;
|
|
156
|
-
runRequestParams.planType = this._options.company.planType;
|
|
157
|
-
runRequestParams.isPOC = this._options.company.isPOC;
|
|
158
|
-
runRequestParams.isStartUp = this._options.company.isStartUp;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (this._options.collectCodeCoverage) {
|
|
162
|
-
if (this._options.codeCoverageUrlFilter) {
|
|
163
|
-
runRequestParams.codeCoverageUrlFilter = this._options.codeCoverageUrlFilter;
|
|
164
|
-
} else {
|
|
165
|
-
runRequestParams.codeCoverageUrlFilter = `${this._baseUrl}*`;
|
|
166
|
-
}
|
|
24
|
+
class TestRun {
|
|
25
|
+
constructor(executionId, executionName, test, options, branchToUse, testRunStatus) {
|
|
26
|
+
this._executionId = executionId;
|
|
27
|
+
this._executionName = executionName;
|
|
28
|
+
this._testStatus = test.testStatus;
|
|
29
|
+
this._testId = test.testId;
|
|
30
|
+
this._testName = test.name;
|
|
31
|
+
this._testResultId = test.resultId;
|
|
32
|
+
this._code = test.code;
|
|
33
|
+
this._baseUrl = options.baseUrl || test.baseUrl || test.testConfig.baseUrl;
|
|
34
|
+
this._nativeApp = test.nativeApp;
|
|
35
|
+
this._overrideTestConfigId = test.overrideTestConfig && test.overrideTestConfig.id;
|
|
36
|
+
this._options = options;
|
|
37
|
+
this._branch = branchToUse;
|
|
38
|
+
this._maxRetryCount = options.retries;
|
|
39
|
+
this._remoteRunId = options.remoteRunId;
|
|
40
|
+
this._retryCount = 1;
|
|
41
|
+
this._timeoutRetryCount = 1;
|
|
42
|
+
this._totalRetryCount = 1;
|
|
43
|
+
|
|
44
|
+
this._testRunStatus = testRunStatus;
|
|
45
|
+
const shouldUpdateConfig = !(test.runConfig && test.runConfig.isMobileWeb) && options.browser;
|
|
46
|
+
this._runConfig = shouldUpdateConfig ? utils.getRunConfigByBrowserName(options.browser, options.saucelabs, options.browserstack) : test.runConfig;
|
|
47
|
+
this.clearTestResultFinished = Promise.resolve();
|
|
48
|
+
|
|
49
|
+
this.seleniumPerfStats = new SeleniumPerfStats();
|
|
167
50
|
}
|
|
168
51
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
analytics.trackWithCIUser('user-disable-mock');
|
|
52
|
+
waitForExecutionStartedFinished() {
|
|
53
|
+
return this._testRunStatus.waitForExecutionStartedFinished() && this.clearTestResultFinished;
|
|
172
54
|
}
|
|
173
55
|
|
|
174
|
-
|
|
175
|
-
|
|
56
|
+
getTestStatus() {
|
|
57
|
+
return this._testStatus;
|
|
176
58
|
}
|
|
177
59
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
60
|
+
getRunMode() {
|
|
61
|
+
return this._options.mode;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
getAutomationMode() {
|
|
65
|
+
return this._code ? 'codeful' : 'codeless';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getCode() {
|
|
69
|
+
return this._code;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getRunConfig() {
|
|
73
|
+
return this._runConfig;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getTestResultId() {
|
|
77
|
+
return this._testResultId;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getBaseUrl() {
|
|
81
|
+
return this._baseUrl;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
getExecutionId() {
|
|
85
|
+
return this._executionId;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
getExecutionName() {
|
|
89
|
+
return this._executionName;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
getNativeAppData() {
|
|
93
|
+
if (this._nativeApp && !this._options.baseUrl) {
|
|
94
|
+
return this._nativeApp;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const url = this._options.baseUrl || this.getBaseUrl();
|
|
98
|
+
if (!url) {
|
|
99
|
+
return null;
|
|
187
100
|
}
|
|
188
|
-
|
|
101
|
+
|
|
102
|
+
const [packageName, activity] = url.split(':');
|
|
103
|
+
return {
|
|
104
|
+
packageName,
|
|
105
|
+
activity,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
getBranch() {
|
|
110
|
+
return this._branch;
|
|
189
111
|
}
|
|
190
112
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
runRequestParams.preloadedTest = preloadedTests[runRequestParams.testId];
|
|
113
|
+
getRemoteRunId() {
|
|
114
|
+
return this._remoteRunId;
|
|
194
115
|
}
|
|
195
116
|
|
|
196
|
-
|
|
197
|
-
|
|
117
|
+
getOverrideTestConfigId() {
|
|
118
|
+
return this._overrideTestConfigId;
|
|
198
119
|
}
|
|
199
120
|
|
|
200
|
-
|
|
201
|
-
|
|
121
|
+
markClearBrowser() {
|
|
122
|
+
this.clearBrowser = true;
|
|
202
123
|
}
|
|
203
124
|
|
|
204
|
-
|
|
205
|
-
|
|
125
|
+
async getRunRequestParams() {
|
|
126
|
+
const customTokenV3 = await testimCustomToken.getCustomTokenV3();
|
|
127
|
+
const runRequestParams = {
|
|
128
|
+
tokenV3: customTokenV3,
|
|
129
|
+
refreshToken: testimCustomToken.getRefreshToken(),
|
|
130
|
+
projectId: this._options.project,
|
|
131
|
+
executionId: this._executionId,
|
|
132
|
+
executionName: this._executionName,
|
|
133
|
+
testId: this._testId,
|
|
134
|
+
resultId: this._testResultId,
|
|
135
|
+
baseUrl: this._baseUrl,
|
|
136
|
+
branch: this._branch,
|
|
137
|
+
servicesUrl: config.EXTENSION_SERVICES_HOST,
|
|
138
|
+
remoteRunId: this.getRemoteRunId(),
|
|
139
|
+
previousTestResultId: this.getPreviousTestResultId(),
|
|
140
|
+
testRetryCount: this.getRetryCount(),
|
|
141
|
+
};
|
|
206
142
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return url;
|
|
212
|
-
};
|
|
143
|
+
if (this._code) {
|
|
144
|
+
runRequestParams.isCodeMode = true;
|
|
145
|
+
runRequestParams.testName = this._testName;
|
|
146
|
+
}
|
|
213
147
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
148
|
+
if (this._options.shouldMonitorPerformance) {
|
|
149
|
+
runRequestParams.shouldMonitorPerformance = true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (this._options.company) {
|
|
153
|
+
runRequestParams.companyId = this._options.company.companyId;
|
|
154
|
+
runRequestParams.onprem = this._options.company.onprem;
|
|
155
|
+
runRequestParams.storageBaseUrl = this._options.company.storageBaseUrl;
|
|
156
|
+
runRequestParams.storageType = this._options.company.storageType;
|
|
157
|
+
runRequestParams.planType = this._options.company.planType;
|
|
158
|
+
runRequestParams.isPOC = this._options.company.isPOC;
|
|
159
|
+
runRequestParams.isStartUp = this._options.company.isStartUp;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (this._options.collectCodeCoverage) {
|
|
163
|
+
if (this._options.codeCoverageUrlFilter) {
|
|
164
|
+
runRequestParams.codeCoverageUrlFilter = this._options.codeCoverageUrlFilter;
|
|
165
|
+
} else {
|
|
166
|
+
runRequestParams.codeCoverageUrlFilter = `${this._baseUrl}*`;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
217
169
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
170
|
+
if (this._options.disableMockNetwork) {
|
|
171
|
+
runRequestParams.disableMockNetwork = this._options.disableMockNetwork;
|
|
172
|
+
analytics.trackWithCIUser('user-disable-mock');
|
|
173
|
+
}
|
|
221
174
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
175
|
+
if (this._options.lightweightMode) {
|
|
176
|
+
runRequestParams.lightweightMode = this._options.lightweightMode;
|
|
177
|
+
}
|
|
225
178
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
179
|
+
if (this._options.lightweightMode && this._options.lightweightMode.general) {
|
|
180
|
+
runRequestParams.company = this._options.company;
|
|
181
|
+
const runData = this.getRunData();
|
|
182
|
+
runRequestParams.lightweightMode.isRunDataSentInUrl = canSendRunDataOverUrl(runData);
|
|
183
|
+
if (runRequestParams.lightweightMode.isRunDataSentInUrl) {
|
|
184
|
+
runRequestParams.runData = runData;
|
|
185
|
+
logger.info(`Run data sent as URL param, test id: ${this.getTestId()} run data length: ${JSON.stringify(runData).length}`);
|
|
186
|
+
} else {
|
|
187
|
+
logger.warn(`Run data is too big to be sent as a URL param. Test id: ${this.getTestId()}, run data size: ${JSON.stringify(runData).length} (limit: ${MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE} characters)`);
|
|
188
|
+
}
|
|
189
|
+
runRequestParams.isLocalRun = Boolean(this._options.useLocalChromeDriver || this._options.useChromeLauncher);
|
|
190
|
+
}
|
|
229
191
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
192
|
+
if (this._options.lightweightMode && this._options.lightweightMode.preloadTests && this._options.useChromeLauncher) {
|
|
193
|
+
const preloadedTests = await preloadTests(this._options);
|
|
194
|
+
runRequestParams.preloadedTest = preloadedTests[runRequestParams.testId];
|
|
195
|
+
}
|
|
233
196
|
|
|
197
|
+
if (this.clearBrowser) {
|
|
198
|
+
runRequestParams.clearBrowser = true;
|
|
199
|
+
}
|
|
234
200
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
overrideTestConfigId: this._overrideTestConfigId || null,
|
|
239
|
-
};
|
|
240
|
-
};
|
|
201
|
+
if (this._options.localRCASaver) {
|
|
202
|
+
runRequestParams.localRCASaver = this._options.localRCASaver;
|
|
203
|
+
}
|
|
241
204
|
|
|
242
|
-
|
|
243
|
-
const runData = this.getRunData();
|
|
244
|
-
if (this.getRunMode() === CLI_MODE.EXTENSION) {
|
|
245
|
-
runData.code = this.getCode();
|
|
205
|
+
return runRequestParams;
|
|
246
206
|
}
|
|
247
207
|
|
|
248
|
-
|
|
249
|
-
|
|
208
|
+
async getRunTestUrl() {
|
|
209
|
+
const runRequestParams = await this.getRunRequestParams();
|
|
210
|
+
const url = `https://run.testim.io/?params=${encodeURIComponent(JSON.stringify(runRequestParams))}`;
|
|
211
|
+
logger.info(`Test (${this.getTestId()}) run URL length: ${url.length}`);
|
|
212
|
+
return url;
|
|
250
213
|
}
|
|
251
|
-
const mustClearPreviousStepResults = !this.isAllowReportTestResultRetries() && (this._timeoutRetryCount > 1 || this._retryCount > 1);
|
|
252
214
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
return Promise.resolve();
|
|
215
|
+
setSessionId(sessionId) {
|
|
216
|
+
this._sessionId = sessionId;
|
|
256
217
|
}
|
|
257
218
|
|
|
258
|
-
|
|
259
|
-
.
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
.
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
TestRun.prototype.startNewRetry = function () {
|
|
289
|
-
this._retryCount++;
|
|
290
|
-
this._timeoutRetryCount = 1;
|
|
291
|
-
return this.onRetry();
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
TestRun.prototype.runTestUsingCDP = async function (cdpTestRunner) {
|
|
295
|
-
perf.log('runTestUsingCDP');
|
|
296
|
-
const { targetInfos } = await cdpTestRunner.cdpCommand('Target.getTargets') || { targetInfos: [] };
|
|
297
|
-
const { targetId: extensionTargetId } = targetInfos.find(target => target.type === 'background_page' && target.title === 'Testim Editor') || {};
|
|
298
|
-
const { targetId: AUTTargetId } = targetInfos.find(target => target.type === 'page') || {};
|
|
299
|
-
if (!extensionTargetId) {
|
|
300
|
-
throw new Error('testim extension not found');
|
|
301
|
-
}
|
|
302
|
-
if (!AUTTargetId) {
|
|
303
|
-
throw new Error('AUT target not found');
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
try {
|
|
307
|
-
perf.log('before Target.attachToTarget');
|
|
308
|
-
const [extensionSession, runRequestParams] = await Promise.all([
|
|
309
|
-
cdpTestRunner.cdpCommand('Target.attachToTarget', { targetId: extensionTargetId, flatten: true }),
|
|
310
|
-
this.getRunRequestParams(),
|
|
311
|
-
]);
|
|
312
|
-
const { sessionId: extensionSessionId } = extensionSession || {};
|
|
313
|
-
perf.log('before Runtime.evaluate');
|
|
314
|
-
|
|
315
|
-
await utils.runWithRetries(async () => {
|
|
316
|
-
const { result } = await cdpTestRunner.cdpCommand('Runtime.evaluate', { expression: 'typeof runTestimTest !== \'undefined\'', returnByValue: true }, extensionSessionId);
|
|
317
|
-
if (!result.value) {
|
|
318
|
-
throw new Error('runTestimTest not available on global scope');
|
|
319
|
-
}
|
|
320
|
-
}, 100, 30);
|
|
219
|
+
getSessionId() {
|
|
220
|
+
return this._sessionId;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
getTestId() {
|
|
224
|
+
return this._testId;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
getTestName() {
|
|
228
|
+
return this._testName;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
getRunParams() {
|
|
232
|
+
return this._options.runParams[this._testResultId] || {};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
getRunData() {
|
|
236
|
+
return {
|
|
237
|
+
userParamsData: this.getRunParams(),
|
|
238
|
+
overrideTestConfigId: this._overrideTestConfigId || null,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
clearTestResult() {
|
|
243
|
+
const runData = this.getRunData();
|
|
244
|
+
if (this.getRunMode() === CLI_MODE.EXTENSION) {
|
|
245
|
+
runData.code = this.getCode();
|
|
246
|
+
}
|
|
321
247
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
if (result.subtype === 'error') {
|
|
325
|
-
throw new Error(result.description);
|
|
248
|
+
if (this._options.mockNetworkRules) {
|
|
249
|
+
runData.mockNetworkRules = this._options.mockNetworkRules;
|
|
326
250
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
251
|
+
const mustClearPreviousStepResults = !this.isAllowReportTestResultRetries() && (this._timeoutRetryCount > 1 || this._retryCount > 1);
|
|
252
|
+
|
|
253
|
+
if (this._options.lightweightMode && this._options.lightweightMode.disableResults &&
|
|
254
|
+
!mustClearPreviousStepResults && canSendRunDataOverUrl(runData)) {
|
|
255
|
+
return Promise.resolve();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
this.clearTestResultFinished = testimServicesApi.uploadRunDataArtifact(this._options.project, this._testId, this._testResultId, runData)
|
|
259
|
+
.catch(err => {
|
|
260
|
+
logger.error('failed to upload run data artifact (runner)', { err });
|
|
261
|
+
return '';
|
|
262
|
+
})
|
|
263
|
+
.then(async (runDataUrl) => {
|
|
264
|
+
// make sure the execution is created by now
|
|
265
|
+
await this._testRunStatus.waitForExecutionStartedFinished();
|
|
266
|
+
// we probably can save this backend call by initializing the execution
|
|
267
|
+
return testimServicesApi.clearTestResult(this._options.project, this._testResultId, this._testId, {
|
|
268
|
+
name: this._testName,
|
|
269
|
+
resultId: this._testResultId,
|
|
270
|
+
status: 'pending',
|
|
271
|
+
retryCount: this._retryCount,
|
|
272
|
+
runDataUrl, // links the run data url to the test.
|
|
273
|
+
runData: runDataUrl ? undefined : runData, // put runData in mongo if we fail to upload to S3.
|
|
274
|
+
testRetryKey: this.getRetryKey(),
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
return this.clearTestResultFinished;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
hasMoreRetries() {
|
|
281
|
+
return this._retryCount < this._maxRetryCount;
|
|
332
282
|
}
|
|
333
|
-
};
|
|
334
283
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
284
|
+
getRetryKey() {
|
|
285
|
+
return `${this._retryCount}:${this._timeoutRetryCount}`;
|
|
286
|
+
}
|
|
338
287
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
288
|
+
startNewRetry() {
|
|
289
|
+
this._retryCount++;
|
|
290
|
+
this._timeoutRetryCount = 1;
|
|
291
|
+
return this.onRetry();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async runTestUsingCDP(cdpTestRunner) {
|
|
295
|
+
perf.log('runTestUsingCDP');
|
|
296
|
+
const { targetInfos } = await cdpTestRunner.cdpCommand('Target.getTargets') || { targetInfos: [] };
|
|
297
|
+
const { targetId: extensionTargetId } = targetInfos.find(target => target.type === 'background_page' && target.title === 'Testim Editor') || {};
|
|
298
|
+
const { targetId: AUTTargetId } = targetInfos.find(target => target.type === 'page') || {};
|
|
299
|
+
if (!extensionTargetId) {
|
|
300
|
+
throw new Error('testim extension not found');
|
|
301
|
+
}
|
|
302
|
+
if (!AUTTargetId) {
|
|
303
|
+
throw new Error('AUT target not found');
|
|
304
|
+
}
|
|
342
305
|
|
|
343
|
-
if (baseUrl && browserValue === 'safari') {
|
|
344
|
-
let parsedUrl;
|
|
345
306
|
try {
|
|
346
|
-
|
|
307
|
+
perf.log('before Target.attachToTarget');
|
|
308
|
+
const [extensionSession, runRequestParams] = await Promise.all([
|
|
309
|
+
cdpTestRunner.cdpCommand('Target.attachToTarget', { targetId: extensionTargetId, flatten: true }),
|
|
310
|
+
this.getRunRequestParams(),
|
|
311
|
+
]);
|
|
312
|
+
const { sessionId: extensionSessionId } = extensionSession || {};
|
|
313
|
+
perf.log('before Runtime.evaluate');
|
|
314
|
+
|
|
315
|
+
await utils.runWithRetries(async () => {
|
|
316
|
+
const { result } = await cdpTestRunner.cdpCommand('Runtime.evaluate', { expression: 'typeof runTestimTest !== \'undefined\'', returnByValue: true }, extensionSessionId);
|
|
317
|
+
if (!result.value) {
|
|
318
|
+
throw new Error('runTestimTest not available on global scope');
|
|
319
|
+
}
|
|
320
|
+
}, 100, 30);
|
|
321
|
+
|
|
322
|
+
perf.log('after wait for runTestimTest function');
|
|
323
|
+
const { result } = await cdpTestRunner.cdpCommand(
|
|
324
|
+
'Runtime.evaluate',
|
|
325
|
+
{ expression: `runTestimTest(${JSON.stringify(runRequestParams)})`, awaitPromise: true, returnByValue: true },
|
|
326
|
+
extensionSessionId,
|
|
327
|
+
);
|
|
328
|
+
if (result.subtype === 'error') {
|
|
329
|
+
throw new Error(result.description);
|
|
330
|
+
}
|
|
331
|
+
perf.log('after Runtime.evaluate');
|
|
332
|
+
return result.value;
|
|
347
333
|
} catch (err) {
|
|
348
|
-
|
|
349
|
-
|
|
334
|
+
logger.error('error running test using CDP', { err });
|
|
335
|
+
throw new Error('Error running test using CDP');
|
|
350
336
|
}
|
|
351
|
-
|
|
337
|
+
}
|
|
352
338
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
339
|
+
isRetryKeyMismatch(testResult) {
|
|
340
|
+
return testResult.testRetryKey && (testResult.testRetryKey !== this.getRetryKey());
|
|
356
341
|
}
|
|
357
|
-
};
|
|
358
342
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
logger.warn(`ignoring result update for on started due to retry key mismatch, got ${testResult.testRetryKey}, current is ${this.getRetryKey()}`, {
|
|
370
|
-
resultId: this.getTestResultId(),
|
|
371
|
-
testId: this.getTestId(),
|
|
372
|
-
});
|
|
343
|
+
validateRunConfig() {
|
|
344
|
+
const baseUrl = this.getBaseUrl();
|
|
345
|
+
const { browserValue } = this.getRunConfig();
|
|
346
|
+
|
|
347
|
+
if (baseUrl && browserValue === 'safari') {
|
|
348
|
+
let parsedUrl;
|
|
349
|
+
try {
|
|
350
|
+
parsedUrl = new URL(baseUrl);
|
|
351
|
+
} catch (err) {
|
|
352
|
+
// ignore invalid URLs (missing http:// or https:// prefix)
|
|
373
353
|
return;
|
|
374
354
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
testResult,
|
|
380
|
-
resultId: this.getTestResultId(),
|
|
381
|
-
testId: this.getTestId(),
|
|
382
|
-
testRetryKey: this.getRetryKey(),
|
|
383
|
-
});
|
|
384
|
-
this._wasCompletedOnStartedCheck = testResult;
|
|
385
|
-
}
|
|
386
|
-
reportedStart = true;
|
|
387
|
-
resolve(testResult);
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
if (this._options.disableSockets) {
|
|
391
|
-
const timeLimit = Date.now() + startTimeout;
|
|
392
|
-
const checkIfDone = () => {
|
|
393
|
-
if (Date.now() > timeLimit) {
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
const testId = this._testId;
|
|
397
|
-
const resultId = this._testResultId;
|
|
398
|
-
const projectId = this._options.project;
|
|
399
|
-
const branch = this.getBranch();
|
|
400
|
-
|
|
401
|
-
testimServicesApi.getTestResults(testId, resultId, projectId, branch).then(restResult => {
|
|
402
|
-
resolveResult(restResult);
|
|
403
|
-
if (!reportedStart) {
|
|
404
|
-
setTimeout(checkIfDone, 3000);
|
|
405
|
-
}
|
|
406
|
-
}).catch((err) => {
|
|
407
|
-
logger.error('failed to check if done', { err });
|
|
408
|
-
setTimeout(checkIfDone, 3000);
|
|
409
|
-
});
|
|
410
|
-
};
|
|
411
|
-
setTimeout(checkIfDone, 3000);
|
|
412
|
-
} else {
|
|
413
|
-
testResultService.listenToTestResult(this._testResultId, this._testId, resolveResult);
|
|
414
|
-
}
|
|
415
|
-
});
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
TestRun.prototype.checkViaRestAPIIfTestStarted = function () {
|
|
419
|
-
const testId = this._testId;
|
|
420
|
-
const resultId = this._testResultId;
|
|
421
|
-
const projectId = this._options.project;
|
|
422
|
-
const branch = this.getBranch();
|
|
423
|
-
return testimServicesApi.getTestResults(testId, resultId, projectId, branch)
|
|
424
|
-
.then(testResult => {
|
|
425
|
-
const expectedStatuses = ['running', 'completed'];
|
|
426
|
-
if (expectedStatuses.includes(testResult.status)) {
|
|
427
|
-
logger.info(`get status: ${testResult.status} after not get test started status`, { testId, resultId, branch });
|
|
428
|
-
return testResult;
|
|
355
|
+
const { username, password } = parsedUrl;
|
|
356
|
+
|
|
357
|
+
if (username || password) {
|
|
358
|
+
throw new Error('Basic authentication in URL is not supported in Safari');
|
|
429
359
|
}
|
|
430
|
-
logger.error(`test not start test status: ${testResult.status} (expected [${expectedStatuses.join(', ')}])`, { testId, resultId, branch });
|
|
431
|
-
throw new Error(timeoutMessages.TEST_START_TIMEOUT_MSG);
|
|
432
|
-
})
|
|
433
|
-
.catch(err => {
|
|
434
|
-
logger.error('failed to get test result after test start timeout', { err, testId, resultId, branch });
|
|
435
|
-
throw new Error(timeoutMessages.TEST_START_TIMEOUT_MSG);
|
|
436
|
-
});
|
|
437
|
-
};
|
|
438
|
-
|
|
439
|
-
TestRun.prototype.onCompletedCleanup = function () {
|
|
440
|
-
if (!this._options.disableSockets) {
|
|
441
|
-
return Promise.resolve(testResultService.leaveTestResult(this._testResultId, this._testId));
|
|
442
|
-
}
|
|
443
|
-
return Promise.resolve();
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
TestRun.prototype.onCompleted = function () {
|
|
447
|
-
let onConnected;
|
|
448
|
-
return new Promise(resolve => {
|
|
449
|
-
if (this._wasCompletedOnStartedCheck && !this.isRetryKeyMismatch(this._wasCompletedOnStartedCheck)) {
|
|
450
|
-
logger.info('test was already completed in on started check', {
|
|
451
|
-
resultId: this.getTestResultId(),
|
|
452
|
-
testId: this.getTestId(),
|
|
453
|
-
});
|
|
454
|
-
resolve(this._wasCompletedOnStartedCheck);
|
|
455
|
-
return;
|
|
456
360
|
}
|
|
361
|
+
}
|
|
457
362
|
|
|
458
|
-
|
|
459
|
-
|
|
363
|
+
onStarted(startTimeout) {
|
|
364
|
+
return new Promise(resolve => {
|
|
365
|
+
// We can't leave the test result as it may remove other listeners as well
|
|
366
|
+
// We need to implement an .off(resultId, listener) method
|
|
367
|
+
let reportedStart = false;
|
|
368
|
+
const resolveResult = testResult => {
|
|
369
|
+
if (reportedStart) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
460
372
|
if (this.isRetryKeyMismatch(testResult)) {
|
|
461
|
-
logger.warn(`ignoring result update for on
|
|
373
|
+
logger.warn(`ignoring result update for on started due to retry key mismatch, got ${testResult.testRetryKey}, current is ${this.getRetryKey()}`, {
|
|
462
374
|
resultId: this.getTestResultId(),
|
|
463
375
|
testId: this.getTestId(),
|
|
464
376
|
});
|
|
465
377
|
return;
|
|
466
378
|
}
|
|
467
|
-
if (
|
|
379
|
+
if (['running', 'completed'].includes(testResult.status)) {
|
|
468
380
|
testResult.resultId = this._testResultId;
|
|
381
|
+
if (testResult.status === 'completed') {
|
|
382
|
+
logger.info('setting _wasCompletedOnStartedCheck to true', {
|
|
383
|
+
testResult,
|
|
384
|
+
resultId: this.getTestResultId(),
|
|
385
|
+
testId: this.getTestId(),
|
|
386
|
+
testRetryKey: this.getRetryKey(),
|
|
387
|
+
});
|
|
388
|
+
this._wasCompletedOnStartedCheck = testResult;
|
|
389
|
+
}
|
|
390
|
+
reportedStart = true;
|
|
469
391
|
resolve(testResult);
|
|
470
392
|
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
393
|
+
};
|
|
394
|
+
if (this._options.disableSockets) {
|
|
395
|
+
const timeLimit = Date.now() + startTimeout;
|
|
396
|
+
const checkIfDone = () => {
|
|
397
|
+
if (Date.now() > timeLimit) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
const testId = this._testId;
|
|
401
|
+
const resultId = this._testResultId;
|
|
402
|
+
const projectId = this._options.project;
|
|
403
|
+
const branch = this.getBranch();
|
|
404
|
+
|
|
405
|
+
testimServicesApi.getTestResults(testId, resultId, projectId, branch).then(restResult => {
|
|
406
|
+
resolveResult(restResult);
|
|
407
|
+
if (!reportedStart) {
|
|
408
|
+
setTimeout(checkIfDone, 3000);
|
|
409
|
+
}
|
|
410
|
+
}).catch((err) => {
|
|
411
|
+
logger.error('failed to check if done', { err });
|
|
412
|
+
setTimeout(checkIfDone, 3000);
|
|
481
413
|
});
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
414
|
+
};
|
|
415
|
+
setTimeout(checkIfDone, 3000);
|
|
416
|
+
} else {
|
|
417
|
+
testResultService.listenToTestResult(this._testResultId, this._testId, resolveResult);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
checkViaRestAPIIfTestStarted() {
|
|
423
|
+
const testId = this._testId;
|
|
424
|
+
const resultId = this._testResultId;
|
|
425
|
+
const projectId = this._options.project;
|
|
426
|
+
const branch = this.getBranch();
|
|
427
|
+
return testimServicesApi.getTestResults(testId, resultId, projectId, branch)
|
|
428
|
+
.then(testResult => {
|
|
429
|
+
const expectedStatuses = ['running', 'completed'];
|
|
430
|
+
if (expectedStatuses.includes(testResult.status)) {
|
|
431
|
+
logger.info(`get status: ${testResult.status} after not get test started status`, { testId, resultId, branch });
|
|
432
|
+
return testResult;
|
|
489
433
|
}
|
|
490
|
-
|
|
434
|
+
logger.error(`test not start test status: ${testResult.status} (expected [${expectedStatuses.join(', ')}])`, { testId, resultId, branch });
|
|
435
|
+
throw new Error(timeoutMessages.TEST_START_TIMEOUT_MSG);
|
|
491
436
|
})
|
|
492
|
-
.catch(err =>
|
|
437
|
+
.catch(err => {
|
|
438
|
+
logger.error('failed to get test result after test start timeout', { err, testId, resultId, branch });
|
|
439
|
+
throw new Error(timeoutMessages.TEST_START_TIMEOUT_MSG);
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
onCompletedCleanup() {
|
|
493
444
|
if (!this._options.disableSockets) {
|
|
494
|
-
testResultService.
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
445
|
+
return Promise.resolve(testResultService.leaveTestResult(this._testResultId, this._testId));
|
|
446
|
+
}
|
|
447
|
+
return Promise.resolve();
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
onCompleted() {
|
|
451
|
+
let onConnected;
|
|
452
|
+
return new Promise(resolve => {
|
|
453
|
+
if (this._wasCompletedOnStartedCheck && !this.isRetryKeyMismatch(this._wasCompletedOnStartedCheck)) {
|
|
454
|
+
logger.info('test was already completed in on started check', {
|
|
455
|
+
resultId: this.getTestResultId(),
|
|
456
|
+
testId: this.getTestId(),
|
|
457
|
+
});
|
|
458
|
+
resolve(this._wasCompletedOnStartedCheck);
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (!this._options.disableSockets) {
|
|
463
|
+
testResultService.listenToTestResult(this._testResultId, this._testId, testResult => {
|
|
464
|
+
if (this.isRetryKeyMismatch(testResult)) {
|
|
465
|
+
logger.warn(`ignoring result update for on completed due to retry key mismatch, got ${testResult.testRetryKey}, current is ${this.getRetryKey()}`, {
|
|
466
|
+
resultId: this.getTestResultId(),
|
|
467
|
+
testId: this.getTestId(),
|
|
468
|
+
});
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (testResult.status === 'completed') {
|
|
472
|
+
testResult.resultId = this._testResultId;
|
|
473
|
+
resolve(testResult);
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
const debounceDelay = this._options.disableSockets ? 0 : Math.floor(10000 + (Math.random() * 5000));
|
|
478
|
+
const maxWait = this._options.disableSockets ? 0 : Math.floor(60000 + (Math.random() * 15000));
|
|
479
|
+
onConnected = _.debounce(() => testimServicesApi.getTestResults(this._testId, this._testResultId, this._options.project, this.getBranch())
|
|
480
|
+
.then(testResult => {
|
|
481
|
+
if (this.isRetryKeyMismatch(testResult)) {
|
|
482
|
+
logger.warn(`ignoring result update for on completed (in reconnect) due to retry key mismatch, got ${testResult.testRetryKey}, current is ${this.getRetryKey()}`, {
|
|
483
|
+
resultId: this.getTestResultId(),
|
|
484
|
+
testId: this.getTestId(),
|
|
485
|
+
});
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
if (testResult && testResult.status === 'completed') {
|
|
489
|
+
logger.info('Socket reconnected - Test complete', { testId: this._testId, resultId: this._testResultId, projectId: this._options.project });
|
|
490
|
+
testResult.resultId = this._testResultId;
|
|
491
|
+
resolve(testResult);
|
|
492
|
+
return true;
|
|
493
|
+
}
|
|
494
|
+
return false;
|
|
495
|
+
})
|
|
496
|
+
.catch(err => logger.warn('Error while trying to check status on socket connect', err)), debounceDelay, { maxWait });
|
|
497
|
+
if (!this._options.disableSockets) {
|
|
498
|
+
testResultService.on('socket-connected', onConnected);
|
|
499
|
+
} else {
|
|
500
|
+
const waitForTestEnd = () => {
|
|
501
|
+
setTimeout(async () => {
|
|
502
|
+
try {
|
|
503
|
+
const { isComplete } = await testimServicesApi.isTestResultCompleted(this._testResultId, this._options.project, this.getRetryKey());
|
|
504
|
+
if (isComplete) {
|
|
505
|
+
const isDone = await onConnected();
|
|
506
|
+
if (!isDone) {
|
|
507
|
+
logger.warn('onConnected returned false even though isComplete was true');
|
|
508
|
+
waitForTestEnd();
|
|
509
|
+
}
|
|
510
|
+
} else {
|
|
504
511
|
waitForTestEnd();
|
|
505
512
|
}
|
|
506
|
-
}
|
|
513
|
+
} catch (err) {
|
|
514
|
+
logger.error('failed to check is complete', { err });
|
|
507
515
|
waitForTestEnd();
|
|
508
516
|
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
517
|
+
}, 3000);
|
|
518
|
+
};
|
|
519
|
+
waitForTestEnd();
|
|
520
|
+
}
|
|
521
|
+
})
|
|
522
|
+
.tap(() => this.onCompletedCleanup())
|
|
523
|
+
.finally(() => onConnected && !this._options.disableSockets && testResultService.off('socket-connected', onConnected));
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
listenToRemoteStep(browser) {
|
|
527
|
+
remoteStepService.listenToRemoteStep(this._testResultId, step => {
|
|
528
|
+
remoteStepPlayback.executeStep(this._options, browser, step, this._testResultId);
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
hasMoreTimeoutRetries() {
|
|
533
|
+
const maxRetryCount = this._options.disableTimeoutRetry ? 1 : RETRIES_ON_TIMEOUT;
|
|
534
|
+
return this._timeoutRetryCount < maxRetryCount;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
startNewTimeoutRetry() {
|
|
538
|
+
this._timeoutRetryCount++;
|
|
539
|
+
return this.onRetry();
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
getRetryCount() {
|
|
543
|
+
return this._retryCount;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
getPreviousTestResultId() {
|
|
547
|
+
return this._previousTestResultId;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
isAllowReportTestResultRetries() {
|
|
551
|
+
return Boolean(_(this._options).get('company.activePlan.premiumFeatures.allowReportTestResultRetries'));
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
async onRetry() {
|
|
555
|
+
this._previousTestResultId = this._testResultId;
|
|
556
|
+
|
|
557
|
+
if (!this.isAllowReportTestResultRetries()) {
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
this._totalRetryCount++;
|
|
562
|
+
this._originalTestResultId = this._originalTestResultId || this._previousTestResultId;
|
|
563
|
+
this._testResultId = utils.guid();
|
|
564
|
+
|
|
565
|
+
if (this._options.lightweightMode && this._options.lightweightMode.onlyTestIdsNoSuite) {
|
|
566
|
+
return;
|
|
516
567
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
TestRun.prototype.hasMoreTimeoutRetries = function () {
|
|
529
|
-
const maxRetryCount = this._options.disableTimeoutRetry ? 1 : RETRIES_ON_TIMEOUT;
|
|
530
|
-
return this._timeoutRetryCount < maxRetryCount;
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
TestRun.prototype.startNewTimeoutRetry = function () {
|
|
534
|
-
this._timeoutRetryCount++;
|
|
535
|
-
return this.onRetry();
|
|
536
|
-
};
|
|
537
|
-
|
|
538
|
-
TestRun.prototype.getRetryCount = function () {
|
|
539
|
-
return this._retryCount;
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
TestRun.prototype.getPreviousTestResultId = function () {
|
|
543
|
-
return this._previousTestResultId;
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
TestRun.prototype.isAllowReportTestResultRetries = function () {
|
|
547
|
-
return Boolean(_(this._options).get('company.activePlan.premiumFeatures.allowReportTestResultRetries'));
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
TestRun.prototype.onRetry = async function () {
|
|
551
|
-
this._previousTestResultId = this._testResultId;
|
|
552
|
-
|
|
553
|
-
if (!this.isAllowReportTestResultRetries()) {
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
this._totalRetryCount++;
|
|
558
|
-
this._originalTestResultId = this._originalTestResultId || this._previousTestResultId;
|
|
559
|
-
this._testResultId = utils.guid();
|
|
560
|
-
|
|
561
|
-
if (this._options.lightweightMode && this._options.lightweightMode.onlyTestIdsNoSuite) {
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
await this._testRunStatus.addRetryTestResult({
|
|
566
|
-
retryCount: this._totalRetryCount,
|
|
567
|
-
executionId: this._executionId,
|
|
568
|
-
projectId: this._options.project,
|
|
569
|
-
newResultId: this._testResultId,
|
|
570
|
-
originalTestResultId: this._originalTestResultId,
|
|
571
|
-
previousTestResultId: this._previousTestResultId,
|
|
572
|
-
});
|
|
573
|
-
};
|
|
568
|
+
|
|
569
|
+
await this._testRunStatus.addRetryTestResult({
|
|
570
|
+
retryCount: this._totalRetryCount,
|
|
571
|
+
executionId: this._executionId,
|
|
572
|
+
projectId: this._options.project,
|
|
573
|
+
newResultId: this._testResultId,
|
|
574
|
+
originalTestResultId: this._originalTestResultId,
|
|
575
|
+
previousTestResultId: this._previousTestResultId,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
}
|
|
574
579
|
|
|
575
580
|
module.exports = TestRun;
|