@testim/testim-cli 3.270.0 → 3.271.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/cliJsCode/service.js +6 -8
- package/agent/server.js +3 -3
- package/cdpTestRunner.js +0 -2
- package/commons/httpRequestCounters.js +6 -5
- package/commons/npmWrapper.js +2 -2
- package/commons/prepareRunner.js +1 -3
- package/commons/runnerFileCache.js +3 -3
- package/commons/socket/baseSocketServiceSocketIO.js +0 -1
- package/commons/socket/remoteStepService.js +3 -4
- package/commons/socket/remoteStepServiceSocketIO.js +0 -1
- package/commons/socket/socketService.js +6 -6
- package/commons/socket/testResultServiceSocketIO.js +0 -1
- package/commons/testimCustomToken.js +1 -1
- package/commons/testimServicesApi.js +2 -3
- package/coverage/jsCoverage.js +0 -1
- package/credentialsManager.js +7 -6
- package/npm-shrinkwrap.json +83 -145
- package/package.json +2 -2
- package/player/WebdriverioWebDriverApi.js +12 -11
- package/player/seleniumTestPlayer.js +0 -1
- package/player/services/frameLocator.js +69 -36
- package/player/services/portSelector.js +0 -2
- package/player/services/tabService.js +4 -2
- package/player/stepActions/RefreshStepAction.js +0 -1
- package/player/stepActions/baseJsStepAction.js +0 -1
- package/player/stepActions/locateStepAction.js +0 -1
- package/player/stepActions/specialKeyStepAction.js +0 -1
- package/player/utils/screenshotUtils.js +0 -1
- package/player/utils/windowUtils.js +0 -1
- package/runners/buildCodeTests.js +0 -1
- package/services/gridService.js +33 -25
- package/testRunHandler.js +5 -1
- package/workers/WorkerSelenium.js +64 -49
- package/workers/workerUtils.js +9 -7
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
'use strict';
|
|
2
4
|
|
|
3
|
-
const Promise = require('bluebird');
|
|
4
5
|
const logger = require('../../commons/logger').getLogger('frame-locator');
|
|
5
6
|
const { locatorBuilderUtils } = require('../../commons/getSessionPlayerRequire');
|
|
6
7
|
const featureFlags = require('../../commons/featureFlags');
|
|
@@ -16,13 +17,23 @@ const _getGuidFromSeleniumElement = (seleniumElement) => {
|
|
|
16
17
|
return seleniumElement[SELENIUM_ELEMENT_KEY] || seleniumElement[SELENIUM_GUID_KEY];
|
|
17
18
|
};
|
|
18
19
|
|
|
20
|
+
/** @typedef {import('clickim/src/background/frameLocator').FrameLocator} FrameLocator */
|
|
21
|
+
/** @typedef {import("clickim/src/locators/dynamicParentUtils").FrameHandler} FrameHandler */
|
|
22
|
+
/** @typedef {import("clickim/src/background/playbackContext").PlaybackContext} PlaybackContext */
|
|
23
|
+
/** @typedef {import("clickim/src/background/frameTree").FrameTree} FrameTree */
|
|
24
|
+
/** @typedef {import("clickim/src/common/models/locateStep").LocateStep} LocateStep */
|
|
25
|
+
/** @typedef {import("clickim/src/common/models/step").Step} Step */
|
|
26
|
+
/** @typedef {FrameLocator['findFrame']} findFrameFn */
|
|
27
|
+
/** @typedef {ConstructorParameters<typeof import('clickim/src/background/frameLocator').FrameLocator>} ClickimFrameLocatorCtorArgs */
|
|
28
|
+
|
|
19
29
|
/** @param {import('../webdriver')} driver*/
|
|
20
30
|
module.exports = function frameLocatorFactory(driver) {
|
|
21
31
|
class FrameLocator {
|
|
22
|
-
/** @type {(...args:
|
|
32
|
+
/** @type {(...args: ClickimFrameLocatorCtorArgs) => this}} */
|
|
23
33
|
constructor(frameManager, locateElementPlayer) {
|
|
24
34
|
this.frameManager = frameManager;
|
|
25
35
|
this.locateElementPlayer = locateElementPlayer;
|
|
36
|
+
/** @type {Record<string, string>} */
|
|
26
37
|
this._cache = {};
|
|
27
38
|
}
|
|
28
39
|
|
|
@@ -43,30 +54,43 @@ module.exports = function frameLocatorFactory(driver) {
|
|
|
43
54
|
}
|
|
44
55
|
}
|
|
45
56
|
|
|
46
|
-
|
|
57
|
+
/**
|
|
58
|
+
* @param {FrameTree} frameTree
|
|
59
|
+
* @param {string | number} testimFrameId
|
|
60
|
+
* @returns {Promise<FrameHandler>}
|
|
61
|
+
*/
|
|
62
|
+
async foundFrameCallback(result, frameTree, testimFrameId) {
|
|
47
63
|
const { frameOffset, locatedElement } = result;
|
|
48
64
|
if (locatorBuilderUtils.isEmptyResult(locatedElement)) {
|
|
49
|
-
|
|
50
|
-
|
|
65
|
+
const errorMsg = 'got empty result in frame result, not rejected from locate element player';
|
|
66
|
+
logger.error(errorMsg);
|
|
67
|
+
throw new Error(errorMsg);
|
|
51
68
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
});
|
|
69
|
+
const el = await driver.switchToLocatedFrame(locatedElement);
|
|
70
|
+
const guid = _getGuidFromSeleniumElement(el.value);
|
|
71
|
+
const frameLocateResultUrl = this.getResultsFromCache(guid);
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
frameId: -1,
|
|
75
|
+
frameOffset,
|
|
76
|
+
tabInfo: frameTree.tabInfo,
|
|
77
|
+
tabId: frameTree.tabId,
|
|
78
|
+
testimFrameId,
|
|
79
|
+
testimFullFrameId: `${this.currentFrameHandler.testimFullFrameId}-${testimFrameId}`,
|
|
80
|
+
// @ts-ignore
|
|
81
|
+
seleniumFrameElement: el.value,
|
|
82
|
+
frameLocateResultUrl,
|
|
83
|
+
};
|
|
68
84
|
}
|
|
69
85
|
|
|
86
|
+
/**
|
|
87
|
+
* @param {LocateStep & { targetId: NonNullable<LocateStep['targetId']>}} frameLocator
|
|
88
|
+
* @param {number} frameDepth
|
|
89
|
+
* @param {FrameHandler & { frameOffset: NonNullable<FrameHandler['frameOffset']> }} currentFrame
|
|
90
|
+
* @param {PlaybackContext} context
|
|
91
|
+
* @param {FrameTree} frameTree
|
|
92
|
+
* @param {Step} stepData
|
|
93
|
+
*/
|
|
70
94
|
locate(frameLocator, frameDepth, currentFrame, context, frameTree, stepData) {
|
|
71
95
|
// eslint-disable-next-line new-cap
|
|
72
96
|
const locateElementPlayer = new this.locateElementPlayer(context);
|
|
@@ -101,7 +125,8 @@ module.exports = function frameLocatorFactory(driver) {
|
|
|
101
125
|
});
|
|
102
126
|
}
|
|
103
127
|
|
|
104
|
-
|
|
128
|
+
/** @type {findFrameFn} */
|
|
129
|
+
async findFrame(stepData, frameLocators, context, frameTree) {
|
|
105
130
|
const allowNoFrameSwitch = featureFlags.flags.enableFrameSwitchOptimization.isEnabled();
|
|
106
131
|
const chronologicalResults = context.playback.resultsHandler.resultsByChronologicOrder;
|
|
107
132
|
const lastResult = chronologicalResults[chronologicalResults.length - 1];
|
|
@@ -111,23 +136,31 @@ module.exports = function frameLocatorFactory(driver) {
|
|
|
111
136
|
const currentFramePos = frameLocators.findIndex(x => x.testimFrameId === this.currentFrameHandler.testimFrameId);
|
|
112
137
|
if (currentFramePos > -1) {
|
|
113
138
|
const shorterPath = frameLocators.slice(currentFramePos + 1);
|
|
114
|
-
|
|
139
|
+
let frameIndex = 0;
|
|
140
|
+
// Changes to the deepest frame
|
|
141
|
+
for (const frameLocator of shorterPath) {
|
|
142
|
+
frameIndex++;
|
|
143
|
+
this.currentFrameHandler = await this.locate(frameLocator, frameIndex, this.currentFrameHandler, context, frameTree, stepData);
|
|
144
|
+
}
|
|
145
|
+
return this.currentFrameHandler;
|
|
115
146
|
}
|
|
116
147
|
}
|
|
117
148
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
149
|
+
const topFrameHandler = await frameTree.getTopFrameHandler();
|
|
150
|
+
topFrameHandler.frameOffset = { top: 0, left: 0 };
|
|
151
|
+
const switchToTop = (allowNoFrameSwitch && this.currentFrameHandler === topFrameHandler) ?
|
|
152
|
+
this.currentFrameHandler :
|
|
153
|
+
driver.switchToTopFrame();
|
|
154
|
+
await switchToTop;
|
|
155
|
+
this.cacheFrameLocateResults(this.currentFrameHandler);
|
|
156
|
+
this.currentFrameHandler = topFrameHandler;
|
|
157
|
+
let frameIndex = 0;
|
|
158
|
+
let currentFrame = topFrameHandler;
|
|
159
|
+
for (const frameLocator of frameLocators) {
|
|
160
|
+
frameIndex++;
|
|
161
|
+
currentFrame = await this.locate(frameLocator, frameIndex, currentFrame, context, frameTree, stepData);
|
|
162
|
+
}
|
|
163
|
+
return currentFrame;
|
|
131
164
|
}
|
|
132
165
|
}
|
|
133
166
|
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
const sessionPlayer = require('../../commons/getSessionPlayerRequire');
|
|
6
6
|
|
|
7
|
-
const Promise = require('bluebird');
|
|
8
7
|
const WindowUtils = require('../utils/windowUtils');
|
|
9
8
|
const ScreenshotUtils = require('../utils/screenshotUtils');
|
|
10
9
|
const ImageCaptureUtils = require('../utils/imageCaptureUtils');
|
|
@@ -158,6 +157,7 @@ class TabService {
|
|
|
158
157
|
}
|
|
159
158
|
|
|
160
159
|
async buildTabInfo(sessionId, tabId, order, openerStepId, options = {}) {
|
|
160
|
+
/** @type {{ title: any; url: any; isMainTab: string; favIconUrl?: any, openerTabId?: any }} */
|
|
161
161
|
const tab = await this.getTabDetails(tabId, sessionId, options);
|
|
162
162
|
const infoId = guid();
|
|
163
163
|
function isMainTab(tabService) {
|
|
@@ -507,7 +507,9 @@ class TabService {
|
|
|
507
507
|
.then(() => {
|
|
508
508
|
let tabId;
|
|
509
509
|
if (tabMatcher) {
|
|
510
|
-
const allTabInfos = this.getAllTabIds(sessionId)
|
|
510
|
+
const allTabInfos = this.getAllTabIds(sessionId)
|
|
511
|
+
.map((tabId) => Object.assign({}, this.getTabInfo(sessionId, tabId), { tabId }))
|
|
512
|
+
.filter((tabInfo) => !tabInfo.isClosed);
|
|
511
513
|
tabId = tabMatcher.matchTabs(step, allTabInfos);
|
|
512
514
|
} else {
|
|
513
515
|
// old session player (clickim) version - remove once enough time passed
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
const StepAction = require('./stepAction');
|
|
6
|
-
const Promise = require('bluebird');
|
|
7
6
|
const sessionPlayer = require('../../commons/getSessionPlayerRequire');
|
|
8
7
|
const featureFlags = require('../../commons/featureFlags');
|
|
9
8
|
const logger = require('../../commons/logger').getLogger('locate-step-action');
|
package/services/gridService.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
'use strict';
|
|
2
4
|
|
|
3
5
|
const _ = require('lodash');
|
|
4
|
-
const Promise = require('bluebird');
|
|
5
6
|
|
|
6
7
|
const { GridError, ArgError } = require('../errors');
|
|
7
8
|
const { hasTestPlanFlag, promiseMap } = require('../utils');
|
|
@@ -9,6 +10,7 @@ const { gridMessages, gridTypes } = require('../commons/constants');
|
|
|
9
10
|
const logger = require('../commons/logger').getLogger('grid-service');
|
|
10
11
|
const servicesApi = require('../commons/testimServicesApi');
|
|
11
12
|
|
|
13
|
+
/** @type {Record<string, { gridId: string; companyId: string; slotId: string; browser: string }>} */
|
|
12
14
|
const gridCache = {};
|
|
13
15
|
const urlExtractRegex = /(^(https?):\/{2})?(.*)/;
|
|
14
16
|
let keepAliveTimer = null;
|
|
@@ -145,37 +147,40 @@ async function getGridDataByGridName(companyId, gridName, allGrids) {
|
|
|
145
147
|
return getSerializableObject(grid);
|
|
146
148
|
}
|
|
147
149
|
|
|
148
|
-
function releaseGridSlot(workerId, projectId) {
|
|
150
|
+
async function releaseGridSlot(workerId, projectId) {
|
|
149
151
|
const gridData = gridCache[workerId];
|
|
150
152
|
if (!gridData) {
|
|
151
|
-
return
|
|
153
|
+
return;
|
|
152
154
|
}
|
|
153
155
|
|
|
154
156
|
const { slotId, gridId, browser, companyId } = gridData;
|
|
155
157
|
delete gridCache[workerId];
|
|
156
158
|
if (!slotId) {
|
|
157
159
|
logger.warn('failed to find grid slot id', { projectId });
|
|
158
|
-
return
|
|
160
|
+
return;
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
logger.info('release slot id', { projectId, companyId, slotId, gridId, browser });
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
try {
|
|
165
|
+
await servicesApi.releaseGridSlot(companyId, projectId, slotId, gridId, browser);
|
|
166
|
+
} catch (err) {
|
|
167
|
+
logger.error('failed to release slot', { projectId, err });
|
|
168
|
+
}
|
|
164
169
|
}
|
|
165
170
|
|
|
166
|
-
function keepAlive(projectId) {
|
|
167
|
-
const slots = Object.
|
|
168
|
-
slots.push(gridCache[workerId]);
|
|
169
|
-
return slots;
|
|
170
|
-
}, []).filter(Boolean);
|
|
171
|
+
async function keepAlive(projectId) {
|
|
172
|
+
const slots = Object.values(gridCache).filter(Boolean);
|
|
171
173
|
|
|
172
|
-
if (
|
|
173
|
-
return
|
|
174
|
+
if (slots.length === 0) {
|
|
175
|
+
return;
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
logger.info('keep alive worker slots', { projectId, slots });
|
|
177
|
-
|
|
178
|
-
|
|
179
|
+
try {
|
|
180
|
+
await servicesApi.keepAliveGrid(projectId, slots);
|
|
181
|
+
} catch (err) {
|
|
182
|
+
logger.error('failed to update grid keep alive', { err, slots, projectId });
|
|
183
|
+
}
|
|
179
184
|
}
|
|
180
185
|
|
|
181
186
|
function startKeepAlive(projectId) {
|
|
@@ -183,21 +188,24 @@ function startKeepAlive(projectId) {
|
|
|
183
188
|
keepAliveTimer = setInterval(keepAlive, KEEP_ALIVE_INTERVAL, projectId);
|
|
184
189
|
}
|
|
185
190
|
|
|
186
|
-
function releaseAllSlots(projectId) {
|
|
191
|
+
async function releaseAllSlots(projectId) {
|
|
187
192
|
const workerIds = Object.keys(gridCache);
|
|
188
193
|
|
|
189
194
|
if (_.isEmpty(workerIds)) {
|
|
190
|
-
return
|
|
195
|
+
return;
|
|
191
196
|
}
|
|
192
197
|
|
|
193
198
|
logger.warn('not all slots released before end runner flow', { projectId });
|
|
194
|
-
|
|
195
|
-
|
|
199
|
+
try {
|
|
200
|
+
await promiseMap(workerIds, workerId => releaseGridSlot(workerId, projectId));
|
|
201
|
+
} catch (err) {
|
|
202
|
+
logger.error('failed to release all slots', { err, projectId });
|
|
203
|
+
}
|
|
196
204
|
}
|
|
197
205
|
|
|
198
|
-
function endKeepAlive(projectId) {
|
|
199
|
-
|
|
200
|
-
|
|
206
|
+
async function endKeepAlive(projectId) {
|
|
207
|
+
await releaseAllSlots(projectId);
|
|
208
|
+
clearInterval(keepAliveTimer);
|
|
201
209
|
}
|
|
202
210
|
|
|
203
211
|
function getVendorKeyFromOptions(type, options) {
|
|
@@ -276,13 +284,13 @@ async function getGridData(options) {
|
|
|
276
284
|
/**
|
|
277
285
|
* @param {string} browser
|
|
278
286
|
* @param {string} executionId
|
|
279
|
-
* @param {import('../runOptions')} options
|
|
287
|
+
* @param {import('../runOptions').RunnerOptions} options
|
|
280
288
|
* @param {number} workerId
|
|
281
289
|
*/
|
|
282
290
|
async function getGridSlot(browser, executionId, options, workerId) {
|
|
283
291
|
const getGridDataFromServer = async () => {
|
|
284
|
-
const { host, project, grid, gridId, useLocalChromeDriver, useChromeLauncher, company
|
|
285
|
-
const companyId = company
|
|
292
|
+
const { host, project, grid, gridId, useLocalChromeDriver, useChromeLauncher, company } = options;
|
|
293
|
+
const companyId = company?.companyId;
|
|
286
294
|
if (useLocalChromeDriver || useChromeLauncher) {
|
|
287
295
|
return { mode: 'local' };
|
|
288
296
|
}
|
package/testRunHandler.js
CHANGED
|
@@ -99,7 +99,11 @@ class TestRun {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
get androidActivityWait() {
|
|
102
|
-
const
|
|
102
|
+
const appData = 'appMetadata' in this._nativeApp ? this._nativeApp.appMetadata : this._nativeApp;
|
|
103
|
+
if (appData.activity.includes(appData.id)) {
|
|
104
|
+
return `${appData.id}.*`;
|
|
105
|
+
}
|
|
106
|
+
const { activity } = appData;
|
|
103
107
|
const lastValue = activity.split('.').pop();
|
|
104
108
|
return activity.replace(lastValue, '*');
|
|
105
109
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const Promise = require('bluebird');
|
|
4
3
|
const BaseWorker = require('./BaseWorker');
|
|
5
4
|
const logger = require('../commons/logger').getLogger('worker-selenium');
|
|
6
5
|
const reporter = require('../reports/reporter');
|
|
@@ -118,7 +117,7 @@ class WorkerSelenium extends BaseWorker {
|
|
|
118
117
|
preloadedTest = preloadedTests[this.testId];
|
|
119
118
|
}
|
|
120
119
|
|
|
121
|
-
async
|
|
120
|
+
const runSeleniumTest = async () => {
|
|
122
121
|
if (testRunHandler.automationMode === 'codeful') {
|
|
123
122
|
// Testim Development Kit test;
|
|
124
123
|
if (!sessionPlayer.callOrderScheduler) { // old session player
|
|
@@ -131,22 +130,32 @@ class WorkerSelenium extends BaseWorker {
|
|
|
131
130
|
);
|
|
132
131
|
}
|
|
133
132
|
perf.log('right before playTestByCode');
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
.
|
|
133
|
+
// TODO: Fix promise constructor anti-pattern
|
|
134
|
+
const playTestByCodePromise = new Promise((resolve, reject) => {
|
|
135
|
+
sessionPlayer.playTestByCode(
|
|
136
|
+
this.testId,
|
|
137
|
+
this.executionId,
|
|
138
|
+
this.testResultId,
|
|
139
|
+
this.baseUrl,
|
|
140
|
+
this.userData,
|
|
141
|
+
version,
|
|
142
|
+
resolve,
|
|
143
|
+
false,
|
|
144
|
+
this.overrideTestConfigId,
|
|
145
|
+
this.branch,
|
|
146
|
+
testRunHandler.code,
|
|
147
|
+
testRunHandler.testName
|
|
148
|
+
).catch(reject);
|
|
149
|
+
});
|
|
150
|
+
return utils
|
|
151
|
+
.promiseTimeout(
|
|
152
|
+
playTestByCodePromise.then((testResult) => {
|
|
153
|
+
perf.log('right after playTestByCode');
|
|
154
|
+
return testResult;
|
|
155
|
+
}),
|
|
156
|
+
this.testRunTimeout,
|
|
157
|
+
timeoutMessages.TEST_COMPLETE_TIMEOUT_MSG
|
|
158
|
+
)
|
|
150
159
|
.catch(err => {
|
|
151
160
|
if (err instanceof utils.TimeoutError) {
|
|
152
161
|
sessionPlayer.stopPlayingOnTestTimeout?.();
|
|
@@ -160,32 +169,37 @@ class WorkerSelenium extends BaseWorker {
|
|
|
160
169
|
}
|
|
161
170
|
const INCOGNITO = false;
|
|
162
171
|
|
|
163
|
-
return
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
172
|
+
return utils.promiseTimeout(
|
|
173
|
+
// TODO: Fix promise constructor anti-pattern
|
|
174
|
+
new Promise((resolve, reject) => {
|
|
175
|
+
sessionPlayer.playByTestId(
|
|
176
|
+
this.testId,
|
|
177
|
+
this.executionId,
|
|
178
|
+
this.testResultId,
|
|
179
|
+
this.baseUrl,
|
|
180
|
+
this.userData,
|
|
181
|
+
version,
|
|
182
|
+
resolve,
|
|
183
|
+
false,
|
|
184
|
+
this.overrideTestConfigId,
|
|
185
|
+
this.branch,
|
|
186
|
+
INCOGNITO,
|
|
187
|
+
testRunHandler.remoteRunId,
|
|
188
|
+
undefined,
|
|
189
|
+
undefined,
|
|
190
|
+
preloadedTest
|
|
191
|
+
).catch(reject);
|
|
192
|
+
}),
|
|
193
|
+
this.testRunTimeout,
|
|
194
|
+
timeoutMessages.TEST_COMPLETE_TIMEOUT_MSG,
|
|
195
|
+
)
|
|
196
|
+
.catch((err) => {
|
|
183
197
|
if (err instanceof utils.TimeoutError) {
|
|
184
198
|
sessionPlayer.stopPlayingOnTestTimeout?.();
|
|
185
199
|
}
|
|
186
200
|
throw err;
|
|
187
201
|
})
|
|
188
|
-
.then(async testResult => {
|
|
202
|
+
.then(async (testResult) => {
|
|
189
203
|
if (sessionPlayerInit.localAssetService) {
|
|
190
204
|
await sessionPlayerInit.localAssetService.drain();
|
|
191
205
|
}
|
|
@@ -203,23 +217,24 @@ class WorkerSelenium extends BaseWorker {
|
|
|
203
217
|
}
|
|
204
218
|
const resultWithStats = { ...testResult, ...testRunHandler.seleniumPerfStats.getStats() };
|
|
205
219
|
if (this.lambdatestService.isLambdatestRun()) {
|
|
206
|
-
await driver.executeJS(`lambda-status=${!resultWithStats.success ? 'failed' : 'passed'}`).catch(() => {
|
|
220
|
+
await driver.executeJS(`lambda-status=${!resultWithStats.success ? 'failed' : 'passed'}`).catch(() => {});
|
|
207
221
|
}
|
|
208
222
|
return resultWithStats;
|
|
209
223
|
});
|
|
210
|
-
}
|
|
224
|
+
};
|
|
211
225
|
|
|
212
226
|
driver.start();
|
|
213
227
|
|
|
214
228
|
perf.log('right before super.runTestOnce in workerSelenium');
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
.
|
|
218
|
-
|
|
219
|
-
.
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
229
|
+
try {
|
|
230
|
+
await super.runTestOnce(testRunHandler, seleniumTestPlayer);
|
|
231
|
+
perf.log('right after super.runTestOnce in workerSelenium');
|
|
232
|
+
await runSeleniumTest();
|
|
233
|
+
perf.log('right after runSeleniumTest');
|
|
234
|
+
} catch (err) {
|
|
235
|
+
logger.error('failed to run test once', { err });
|
|
236
|
+
throw err;
|
|
237
|
+
}
|
|
223
238
|
}
|
|
224
239
|
}
|
|
225
240
|
function setupCliPerformanceMonitoring(sessionPlayer) {
|
package/workers/workerUtils.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
const Promise = require('bluebird');
|
|
2
1
|
const gridService = require('../services/gridService');
|
|
3
2
|
const logger = require('../commons/logger').getLogger('worker-utils');
|
|
4
3
|
|
|
5
|
-
const releaseGridSlot = (workerId, releaseSlotOnTestFinished, projectId) => {
|
|
4
|
+
const releaseGridSlot = async (workerId, releaseSlotOnTestFinished, projectId) => {
|
|
6
5
|
if (!releaseSlotOnTestFinished) {
|
|
7
|
-
return
|
|
6
|
+
return;
|
|
8
7
|
}
|
|
9
|
-
|
|
8
|
+
await gridService.releaseGridSlot(workerId, projectId);
|
|
10
9
|
};
|
|
11
10
|
|
|
12
|
-
const releasePlayer = (workerId, releaseSlotOnTestFinished, projectId, player) => {
|
|
11
|
+
const releasePlayer = async (workerId, releaseSlotOnTestFinished, projectId, player) => {
|
|
13
12
|
logger.info('releasing player', { hasPlayer: Boolean(player) });
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
try {
|
|
14
|
+
await player?.onDone();
|
|
15
|
+
} finally {
|
|
16
|
+
await releaseGridSlot(workerId, releaseSlotOnTestFinished, projectId);
|
|
17
|
+
}
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
module.exports.releasePlayer = releasePlayer;
|