@testim/testim-cli 3.289.0 → 3.290.1-beta
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/cli.js +22390 -122
- package/cli.js.map +1 -0
- package/npm-shrinkwrap.json +1169 -12846
- package/package.json +16 -10
- package/OverrideTestDataBuilder.js +0 -117
- package/agent/routers/cliJsCode/index.js +0 -13
- package/agent/routers/cliJsCode/router.js +0 -63
- package/agent/routers/cliJsCode/service.js +0 -705
- package/agent/routers/codim/router.js +0 -69
- package/agent/routers/codim/router.test.js +0 -60
- package/agent/routers/codim/service.js +0 -193
- package/agent/routers/general/index.js +0 -36
- package/agent/routers/hybrid/registerRoutes.js +0 -81
- package/agent/routers/index.js +0 -56
- package/agent/routers/playground/router.js +0 -77
- package/agent/routers/playground/service.js +0 -96
- package/agent/routers/standalone-browser/registerRoutes.js +0 -47
- package/agent/server.js +0 -150
- package/cdpTestRunner.js +0 -86
- package/chromiumInstaller.js +0 -91
- package/cli/isCiRun.js +0 -10
- package/cli/onExit.js +0 -65
- package/cli/writeStackTrace.js +0 -27
- package/cliAgentMode.js +0 -384
- package/codim/codim-cli.js +0 -91
- package/codim/codim-npm-package/index.ts +0 -427
- package/codim/codim-npm-package/package-lock.json +0 -14
- package/codim/codim-npm-package/package.json +0 -14
- package/codim/hybrid-utils.js +0 -28
- package/codim/measure-perf.js +0 -41
- package/codim/template.js/.idea/workspace.xml +0 -57
- package/codim/template.js/.vscode/launch.json +0 -53
- package/codim/template.ts/.idea/workspace.xml +0 -57
- package/codim/template.ts/.vscode/launch.json +0 -55
- package/commons/AbortError.js +0 -12
- package/commons/SeleniumPerfStats.js +0 -58
- package/commons/chrome-launcher.js +0 -15
- package/commons/chromedriverWrapper.js +0 -70
- package/commons/config.js +0 -39
- package/commons/constants.js +0 -67
- package/commons/detectDebugger.js +0 -19
- package/commons/featureAvailabilityService.js +0 -26
- package/commons/featureFlags.js +0 -132
- package/commons/getSessionPlayerRequire.js +0 -28
- package/commons/httpRequest.js +0 -261
- package/commons/httpRequestCounters.js +0 -98
- package/commons/httpRequestCounters.test.js +0 -38
- package/commons/initializeUserWithAuth.js +0 -55
- package/commons/lazyRequire.js +0 -105
- package/commons/logUtils.js +0 -15
- package/commons/logUtils.test.js +0 -21
- package/commons/logger.js +0 -178
- package/commons/mockNetworkRuleFileSchema.json +0 -140
- package/commons/npmWrapper.js +0 -174
- package/commons/npmWrapper.test.js +0 -374
- package/commons/performance-logger.js +0 -71
- package/commons/preloadTests.js +0 -29
- package/commons/prepareRunner.js +0 -85
- package/commons/prepareRunner.test.js +0 -144
- package/commons/prepareRunnerAndTestimStartUtils.js +0 -198
- package/commons/prepareRunnerAndTestimStartUtils.test.js +0 -73
- package/commons/requireWithFallback.js +0 -25
- package/commons/runnerFileCache.js +0 -204
- package/commons/socket/baseSocketServiceSocketIO.js +0 -197
- package/commons/socket/realDataService.js +0 -59
- package/commons/socket/realDataServiceSocketIO.js +0 -33
- package/commons/socket/remoteStepService.js +0 -55
- package/commons/socket/remoteStepServiceSocketIO.js +0 -61
- package/commons/socket/socketService.js +0 -175
- package/commons/socket/testResultService.js +0 -62
- package/commons/socket/testResultServiceSocketIO.js +0 -64
- package/commons/testimAnalytics.js +0 -40
- package/commons/testimCloudflare.js +0 -83
- package/commons/testimCloudflare.test.js +0 -185
- package/commons/testimCustomToken.js +0 -124
- package/commons/testimDesiredCapabilitiesBuilder.js +0 -647
- package/commons/testimNgrok.js +0 -90
- package/commons/testimNgrok.test.js +0 -140
- package/commons/testimServicesApi.js +0 -631
- package/commons/testimTunnel.js +0 -73
- package/commons/testimTunnel.test.js +0 -172
- package/commons/xhr2.js +0 -897
- package/coverage/SummaryToObjectReport.js +0 -19
- package/coverage/jsCoverage.js +0 -252
- package/credentialsManager.js +0 -142
- package/errors.js +0 -161
- package/executionQueue.js +0 -37
- package/fixLocalBuild.js +0 -24
- package/inputFileUtils.js +0 -103
- package/lib/coralogix-winston.transport.js +0 -99
- package/player/SeleniumProtocolError.js +0 -100
- package/player/WebDriverHttpRequest.js +0 -177
- package/player/WebdriverioWebDriverApi.js +0 -671
- package/player/appiumTestPlayer.js +0 -90
- package/player/chromeLauncherTestPlayer.js +0 -67
- package/player/constants.js +0 -332
- package/player/extensionTestPlayer.js +0 -32
- package/player/findElementStrategy.js +0 -154
- package/player/scripts/isElementDisplayed.js +0 -252
- package/player/seleniumTestPlayer.js +0 -140
- package/player/services/frameLocator.js +0 -170
- package/player/services/mobileFrameLocatorMock.js +0 -32
- package/player/services/playbackTimeoutCalculator.js +0 -175
- package/player/services/portSelector.js +0 -19
- package/player/services/tabService.js +0 -551
- package/player/services/tabServiceMock.js +0 -167
- package/player/services/windowCreationListener.js +0 -8
- package/player/stepActions/RefreshStepAction.js +0 -16
- package/player/stepActions/apiStepAction.js +0 -89
- package/player/stepActions/baseCliJsStepAction.js +0 -51
- package/player/stepActions/baseJsStepAction.js +0 -277
- package/player/stepActions/cliConditionStepAction.js +0 -11
- package/player/stepActions/cliJsStepAction.js +0 -11
- package/player/stepActions/dropFileStepAction.js +0 -34
- package/player/stepActions/evaluateExpressionStepAction.js +0 -52
- package/player/stepActions/extensionOnlyStepAction.js +0 -12
- package/player/stepActions/extractTextStepAction.js +0 -19
- package/player/stepActions/hoverStepAction.js +0 -55
- package/player/stepActions/inputFileStepAction.js +0 -199
- package/player/stepActions/jsCodeStepAction.js +0 -11
- package/player/stepActions/jsConditionStepAction.js +0 -11
- package/player/stepActions/locateStepAction.js +0 -159
- package/player/stepActions/mouseStepAction.js +0 -370
- package/player/stepActions/navigationStepAction.js +0 -29
- package/player/stepActions/nodePackageStepAction.js +0 -47
- package/player/stepActions/pixelValidationStepAction.js +0 -39
- package/player/stepActions/scripts/dispatchEvents.js +0 -282
- package/player/stepActions/scripts/doClick.js +0 -221
- package/player/stepActions/scripts/doDragPath.js +0 -225
- package/player/stepActions/scripts/doubleClick.js +0 -119
- package/player/stepActions/scripts/dropEvent.js +0 -63
- package/player/stepActions/scripts/focusElement.js +0 -46
- package/player/stepActions/scripts/html5dragAction.js +0 -56
- package/player/stepActions/scripts/html5dragActionV2.js +0 -312
- package/player/stepActions/scripts/runCode.js +0 -147
- package/player/stepActions/scripts/scroll.js +0 -90
- package/player/stepActions/scripts/selectOption.js +0 -51
- package/player/stepActions/scripts/setText.js +0 -415
- package/player/stepActions/scripts/wheel.js +0 -61
- package/player/stepActions/scrollStepAction.js +0 -96
- package/player/stepActions/selectOptionStepAction.js +0 -49
- package/player/stepActions/sfdcRecordedStepAction.js +0 -24
- package/player/stepActions/sfdcStepAction.js +0 -28
- package/player/stepActions/sleepStepAction.js +0 -12
- package/player/stepActions/specialKeyStepAction.js +0 -52
- package/player/stepActions/stepAction.js +0 -73
- package/player/stepActions/stepActionRegistrar.js +0 -111
- package/player/stepActions/submitStepAction.js +0 -12
- package/player/stepActions/tdkHybridStepAction.js +0 -18
- package/player/stepActions/textStepAction.js +0 -110
- package/player/stepActions/textValidationStepAction.js +0 -64
- package/player/stepActions/wheelStepAction.js +0 -41
- package/player/utils/cookieUtils.js +0 -39
- package/player/utils/eyeSdkService.js +0 -250
- package/player/utils/imageCaptureUtils.js +0 -267
- package/player/utils/screenshotUtils.js +0 -68
- package/player/utils/stepActionUtils.js +0 -90
- package/player/utils/windowUtils.js +0 -195
- package/player/webDriverUtils.js +0 -40
- package/player/webDriverUtils.test.js +0 -116
- package/player/webdriver.js +0 -976
- package/polyfills/Array.prototype.at.js +0 -13
- package/polyfills/index.js +0 -13
- package/processHandler.js +0 -79
- package/processHandler.test.js +0 -55
- package/reports/chromeReporter.js +0 -17
- package/reports/consoleReporter.js +0 -190
- package/reports/debugReporter.js +0 -82
- package/reports/jsonReporter.js +0 -55
- package/reports/junitReporter.js +0 -183
- package/reports/reporter.js +0 -166
- package/reports/reporterUtils.js +0 -54
- package/reports/teamCityReporter.js +0 -73
- package/runOptions.d.ts +0 -305
- package/runOptions.js +0 -1288
- package/runOptionsAgentFlow.js +0 -87
- package/runOptionsUtils.js +0 -60
- package/runner.js +0 -355
- package/runners/ParallelWorkerManager.js +0 -284
- package/runners/TestPlanRunner.js +0 -419
- package/runners/buildCodeTests.js +0 -159
- package/runners/runnerUtils.js +0 -81
- package/services/analyticsService.js +0 -96
- package/services/branchService.js +0 -29
- package/services/gridService.js +0 -357
- package/services/gridService.test.js +0 -357
- package/services/labFeaturesService.js +0 -64
- package/services/lambdatestService.js +0 -227
- package/services/lambdatestService.test.js +0 -353
- package/services/localRCASaver.js +0 -124
- package/stepPlayers/cliJsStepPlayback.js +0 -40
- package/stepPlayers/hybridStepPlayback.js +0 -140
- package/stepPlayers/nodePackageStepPlayback.js +0 -28
- package/stepPlayers/playwrightHybridStepPlayback.js +0 -61
- package/stepPlayers/puppeteerHybridStepPlayback.js +0 -76
- package/stepPlayers/remoteStepPlayback.js +0 -80
- package/stepPlayers/seleniumHybridStepPlayback.js +0 -84
- package/stepPlayers/tdkHybridStepPlayback.js +0 -112
- package/testRunHandler.js +0 -603
- package/testRunStatus.js +0 -567
- package/testimNpmDriver.js +0 -52
- package/utils/argsUtils.js +0 -91
- package/utils/argsUtils.test.js +0 -32
- package/utils/fsUtils.js +0 -174
- package/utils/index.js +0 -197
- package/utils/promiseUtils.js +0 -85
- package/utils/stringUtils.js +0 -98
- package/utils/stringUtils.test.js +0 -22
- package/utils/timeUtils.js +0 -25
- package/utils/utils.test.js +0 -27
- package/workers/BaseWorker.js +0 -498
- package/workers/BaseWorker.test.js +0 -186
- package/workers/WorkerAppium.js +0 -180
- package/workers/WorkerExtension.js +0 -192
- package/workers/WorkerExtensionSingleBrowser.js +0 -77
- package/workers/WorkerSelenium.js +0 -253
- package/workers/workerUtils.js +0 -20
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const pRetry = require('p-retry');
|
|
4
|
-
const io = require('socket.io-client');
|
|
5
|
-
const config = require('../config');
|
|
6
|
-
const utils = require('../../utils');
|
|
7
|
-
|
|
8
|
-
const MAX_SOCKET_RECONNECT_ATTEMPT = 50;
|
|
9
|
-
const MAX_RECONNECT_ATTEMPT_BEFORE_SWITCH = 10;
|
|
10
|
-
const EMIT_PROMISE_TIMEOUT = 5000;
|
|
11
|
-
const POLLING_TRANSPORT_TIMEOUT_MS = 10 * 1000;
|
|
12
|
-
|
|
13
|
-
const logger = require('../logger').getLogger('base socket service');
|
|
14
|
-
|
|
15
|
-
class BaseSocketServiceSocketIO {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.attempts = 0;
|
|
18
|
-
/** @type {{ [testResultId: string]: testId }} */
|
|
19
|
-
this.rooms = {};
|
|
20
|
-
/** @type {undefined | Promise<void>} */
|
|
21
|
-
this.emitPromiseQueue = undefined;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
joinToMultipleResults() {
|
|
25
|
-
const testResultIds = Object.keys(this.rooms);
|
|
26
|
-
logger.info('re-join all existing rooms', { testResultIds });
|
|
27
|
-
testResultIds.forEach(resultId => {
|
|
28
|
-
const testId = this.rooms[resultId];
|
|
29
|
-
this.emitJoinRoom?.(resultId, testId);
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @param {string} resultId
|
|
35
|
-
* @param {string} testId
|
|
36
|
-
*/
|
|
37
|
-
joinRoom(resultId, testId) {
|
|
38
|
-
this.rooms[resultId] = testId;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @param {string} resultId
|
|
43
|
-
* @param {string} testId
|
|
44
|
-
*/
|
|
45
|
-
leaveRoom(resultId) {
|
|
46
|
-
delete this.rooms[resultId];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
addSocketHandlers() {
|
|
50
|
-
const socketError = (method, err) => {
|
|
51
|
-
let transport = 'websocket';
|
|
52
|
-
try {
|
|
53
|
-
transport = this._socket.io.engine.transport.name;
|
|
54
|
-
} catch (e) {
|
|
55
|
-
/* empty */
|
|
56
|
-
}
|
|
57
|
-
logger.error(`Error in SocketService websocket _${method}_ socket ${this._socket.id} ` +
|
|
58
|
-
`is ${this.url} over ${transport}. Reconnect attempts ${this.attempts}. Error is: ${err?.message}`);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
this._socket.on('reconnect_attempt', (attempt) => {
|
|
62
|
-
socketError('reconnect_attempt', { message: 'reconnect attempt', attempt });
|
|
63
|
-
this.attempts++;
|
|
64
|
-
if (this.attempts === MAX_RECONNECT_ATTEMPT_BEFORE_SWITCH && !this.isAllowedWS) {
|
|
65
|
-
this._socket.io.opts.transports = ['polling'];
|
|
66
|
-
this._socket.io.opts.upgrade = false;
|
|
67
|
-
}
|
|
68
|
-
if (this.attempts >= MAX_SOCKET_RECONNECT_ATTEMPT) {
|
|
69
|
-
throw new Error('Can\'t connect to Testim Servers.\n' +
|
|
70
|
-
`Action required: Please allow opening a websockets connection to ${config.SERVICES_HOST} in your firewall/proxy`);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
this._socket.on('connect_error', (err) => {
|
|
75
|
-
socketError('connect_error', err);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
this._socket.on('connect_timeout', (err) => {
|
|
79
|
-
socketError('connect_timeout', err);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
this._socket.on('error', err => {
|
|
83
|
-
socketError('error', err);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
this._socket.on('reconnect_error', err => {
|
|
87
|
-
if (this.prevErr && this.prevErr.type === err.type) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
this.prevErr = err;
|
|
91
|
-
socketError('reconnect_error', err);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
this._socket.on('reconnect', () => {
|
|
95
|
-
logger.info('reconnect to socket and re-join to rooms');
|
|
96
|
-
this.joinToMultipleResults();
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
this._socket.on('connect', () => {
|
|
100
|
-
this.attempts = 0;
|
|
101
|
-
if (this.isAllowedWS === undefined) {
|
|
102
|
-
this.isAllowedWS = this._socket.io.engine.transport && this._socket.io.engine.transport.name === 'websocket';
|
|
103
|
-
}
|
|
104
|
-
if (this.onConnect) {
|
|
105
|
-
this.onConnect();
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* @param {string} projectId
|
|
112
|
-
* @param {string} ns
|
|
113
|
-
*/
|
|
114
|
-
initNewSocket(projectId, ns) {
|
|
115
|
-
const opts = {
|
|
116
|
-
query: { projectId },
|
|
117
|
-
requestTimeout: POLLING_TRANSPORT_TIMEOUT_MS,
|
|
118
|
-
transports: ['websocket'],
|
|
119
|
-
upgrade: false,
|
|
120
|
-
forceNew: true,
|
|
121
|
-
rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0',
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
if (global.caFileContent) {
|
|
125
|
-
opts.ca = global.caFileContent;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (global.proxyUri) {
|
|
129
|
-
opts.agent = new global.ProxyAgent(global.proxyUri);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return new Promise(resolve => {
|
|
133
|
-
this.url = `${config.SERVICES_HOST}/${ns}`;
|
|
134
|
-
this._socket = io.connect(this.url, opts);
|
|
135
|
-
this.addSocketHandlers();
|
|
136
|
-
this._socket.on('connect', resolve);
|
|
137
|
-
this._socket.open();
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* @param {string} projectId
|
|
143
|
-
* @param {string} ns
|
|
144
|
-
*/
|
|
145
|
-
init(projectId, ns) {
|
|
146
|
-
const opts = {
|
|
147
|
-
query: { projectId },
|
|
148
|
-
requestTimeout: POLLING_TRANSPORT_TIMEOUT_MS,
|
|
149
|
-
transports: ['websocket'],
|
|
150
|
-
upgrade: false,
|
|
151
|
-
rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0',
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
if (global.caFileContent) {
|
|
155
|
-
opts.ca = global.caFileContent;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (global.proxyUri) {
|
|
159
|
-
opts.agent = new global.ProxyAgent(global.proxyUri);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
this.url = `${config.SERVICES_HOST}/${ns}`;
|
|
163
|
-
this._socket = io.connect(this.url, opts);
|
|
164
|
-
this.addSocketHandlers();
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* @param {string} eventName
|
|
169
|
-
* @param {*} eventData
|
|
170
|
-
*/
|
|
171
|
-
emitPromise(eventName, eventData) {
|
|
172
|
-
const errorneousEvents = {};
|
|
173
|
-
|
|
174
|
-
const emitAndWait = () => new Promise((resolve, reject) => {
|
|
175
|
-
this._socket.emit(eventName, eventData, data => {
|
|
176
|
-
if (data?.success) {
|
|
177
|
-
return resolve();
|
|
178
|
-
}
|
|
179
|
-
errorneousEvents[eventName] = eventData;
|
|
180
|
-
|
|
181
|
-
return reject(new Error('bad ack'));
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
this.emitPromiseQueue = (this.emitPromiseQueue || Promise.resolve())
|
|
186
|
-
.then(() => pRetry(() => utils.promiseTimeout(emitAndWait(), EMIT_PROMISE_TIMEOUT), { retries: 200, minTimeout: 3000, factor: 1 }))
|
|
187
|
-
.finally(() => {
|
|
188
|
-
if (Object.keys(errorneousEvents).length > 0) {
|
|
189
|
-
logger.error('Bad acknowledge from socket emit', { errorneousEvents });
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
return this.emitPromiseQueue;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
module.exports = BaseSocketServiceSocketIO;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const RealDataServiceSocketIO = require('./realDataServiceSocketIO');
|
|
4
|
-
const socketService = require('./socketService');
|
|
5
|
-
|
|
6
|
-
const { socketEventTypes } = require('../constants');
|
|
7
|
-
const featureFlags = require('../featureFlags');
|
|
8
|
-
|
|
9
|
-
const { TEST_RESULT_CREATED, TEST_RESULT_UPDATED } = socketEventTypes;
|
|
10
|
-
|
|
11
|
-
class RealDataService {
|
|
12
|
-
constructor() {
|
|
13
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
this.realDataServiceSocketIO = new RealDataServiceSocketIO();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
init(projectId) {
|
|
20
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
21
|
-
return Promise.resolve();
|
|
22
|
-
}
|
|
23
|
-
return this.realDataServiceSocketIO.init(projectId);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
joinToTestResultsByRunId(runId, projectId) {
|
|
27
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
28
|
-
return socketService.addFilter(runId, { runId }, [
|
|
29
|
-
TEST_RESULT_UPDATED,
|
|
30
|
-
TEST_RESULT_CREATED,
|
|
31
|
-
], true);
|
|
32
|
-
}
|
|
33
|
-
this.realDataServiceSocketIO.joinToTestResultsByRunId(runId, projectId);
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
stopListenToTestResultsByRunId(runId) {
|
|
38
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
39
|
-
socketService.removeFilter(runId, [TEST_RESULT_UPDATED, TEST_RESULT_CREATED]);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
this.realDataServiceSocketIO.stopListenToTestResultsByRunId(runId);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
listenToTestResultsByRunId(runId, cb) {
|
|
46
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
47
|
-
socketService.listenTo(
|
|
48
|
-
runId,
|
|
49
|
-
[TEST_RESULT_UPDATED, TEST_RESULT_CREATED],
|
|
50
|
-
data => data.runId === runId,
|
|
51
|
-
data => cb(data)
|
|
52
|
-
);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
this.realDataServiceSocketIO.listenToTestResultsByRunId(cb);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
module.exports = RealDataService;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const BaseSocketService = require('./baseSocketServiceSocketIO');
|
|
4
|
-
|
|
5
|
-
class RealDataServiceSocketIO extends BaseSocketService {
|
|
6
|
-
init(projectId) {
|
|
7
|
-
return super.initNewSocket(projectId, 'real-data');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
emitJoinRoom(runId, projectId) {
|
|
11
|
-
this._socket.emit('testResult:listen', { query: `projectId=${projectId}&runId=${runId}` });
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
joinToTestResultsByRunId(runId, projectId) {
|
|
15
|
-
this.joinRoom(runId, projectId);
|
|
16
|
-
this.emitJoinRoom(runId, projectId);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
stopListenToTestResultsByRunId(runId) {
|
|
20
|
-
this.leaveRoom(runId);
|
|
21
|
-
this._socket.emit('testResult:listen:stop', {});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
listenToTestResultsByRunId(cb) {
|
|
25
|
-
function onDone(data) {
|
|
26
|
-
cb(data.data);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
this._socket.on('testResult:changes', onDone.bind(this));
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
module.exports = RealDataServiceSocketIO;
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
const socketService = require('./socketService');
|
|
2
|
-
const { socketEventTypes } = require('../constants');
|
|
3
|
-
const featureFlags = require('../featureFlags');
|
|
4
|
-
|
|
5
|
-
const { REMOTE_STEP_SAVED } = socketEventTypes;
|
|
6
|
-
|
|
7
|
-
let remoteStepServiceSocketIO; // required lazily since it takes 150ms to load
|
|
8
|
-
|
|
9
|
-
class RemoteStepService {
|
|
10
|
-
init(projectId) {
|
|
11
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
remoteStepServiceSocketIO = require('./remoteStepServiceSocketIO');
|
|
15
|
-
remoteStepServiceSocketIO.init(projectId);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
joinToRemoteStep(resultId) {
|
|
19
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
20
|
-
return socketService.addFilter(`${resultId}:remoteStep`, { resultId }, [REMOTE_STEP_SAVED]);
|
|
21
|
-
}
|
|
22
|
-
return remoteStepServiceSocketIO.joinToRemoteStep(resultId);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
//TODO remove after migrate to save result via RestAPI
|
|
26
|
-
saveRemoteStep(resultId, stepId, remoteStep) {
|
|
27
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
28
|
-
return Promise.resolve();
|
|
29
|
-
}
|
|
30
|
-
return remoteStepServiceSocketIO.saveRemoteStep(resultId, stepId, remoteStep);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
listenToRemoteStep(resultId, onRemoteStep) {
|
|
34
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
35
|
-
socketService.listenTo(
|
|
36
|
-
`${resultId}:remoteStep`,
|
|
37
|
-
[REMOTE_STEP_SAVED],
|
|
38
|
-
data => data.resultId === resultId && data.remoteStep && data.remoteStep.status === 'pending',
|
|
39
|
-
data => onRemoteStep(data.remoteStep)
|
|
40
|
-
);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
remoteStepServiceSocketIO.listenToRemoteStep(resultId, onRemoteStep);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
unlistenToRemoteStep(resultId) {
|
|
47
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
48
|
-
socketService.removeFilter(`${resultId}:remoteStep`, [REMOTE_STEP_SAVED]);
|
|
49
|
-
return Promise.resolve();
|
|
50
|
-
}
|
|
51
|
-
return remoteStepServiceSocketIO.unlistenToRemoteStep(resultId);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
module.exports = new RemoteStepService();
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const BaseSocketService = require('./baseSocketServiceSocketIO');
|
|
4
|
-
|
|
5
|
-
class RemoteStepServiceSocketIO extends BaseSocketService {
|
|
6
|
-
init(projectId) {
|
|
7
|
-
super.init(projectId, 'remoteStep');
|
|
8
|
-
this.listerers = {};
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
emitJoinRoom(resultId) {
|
|
12
|
-
return this.emitPromise('remoteStep:join', { resultId });
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
emitLeaveRoom(resultId) {
|
|
16
|
-
return this.emitPromise('remoteStep:leave', { resultId });
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
joinToRemoteStep(resultId) {
|
|
20
|
-
if (this.rooms[resultId]) {
|
|
21
|
-
return Promise.resolve();
|
|
22
|
-
}
|
|
23
|
-
this.joinRoom(resultId);
|
|
24
|
-
return this.emitJoinRoom(resultId);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
saveRemoteStep(resultId, stepId, remoteStep) {
|
|
28
|
-
return this.emitPromise('remoteStep:save', {
|
|
29
|
-
resultId,
|
|
30
|
-
stepId,
|
|
31
|
-
remoteStep,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
listenToRemoteStep(resultId, onRemoteStep) {
|
|
36
|
-
if (this.listerers[resultId]) {
|
|
37
|
-
this._socket.off('remoteStep:saved', this.listerers[resultId]);
|
|
38
|
-
delete this.listerers[resultId];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
this.listerers[resultId] = data => {
|
|
42
|
-
if (data.resultId === resultId && data.remoteStep && data.remoteStep.status === 'pending') {
|
|
43
|
-
onRemoteStep(data.remoteStep);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
this._socket.on('remoteStep:saved', this.listerers[resultId]);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
unlistenToRemoteStep(resultId) {
|
|
50
|
-
if (!this.listerers[resultId]) {
|
|
51
|
-
return Promise.resolve();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
this.leaveRoom(resultId);
|
|
55
|
-
this._socket.off('remoteStep:saved', this.listerers[resultId]);
|
|
56
|
-
delete this.listerers[resultId];
|
|
57
|
-
return this.emitLeaveRoom(resultId);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
module.exports = new RemoteStepServiceSocketIO();
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const WebSocket = require('ws');
|
|
4
|
-
const _ = require('lodash');
|
|
5
|
-
const { WEBSOCKET_HOST } = require('../config');
|
|
6
|
-
const utils = require('../../utils');
|
|
7
|
-
const logger = require('../logger').getLogger('socket-ng-service');
|
|
8
|
-
const { EventEmitter } = require('events');
|
|
9
|
-
const testimCustomToken = require('../testimCustomToken');
|
|
10
|
-
|
|
11
|
-
const WAIT_BETWEEN_RECONNECT_MS = 5000;
|
|
12
|
-
|
|
13
|
-
class SocketService extends EventEmitter {
|
|
14
|
-
constructor() {
|
|
15
|
-
super();
|
|
16
|
-
this.clientId = utils.guid();
|
|
17
|
-
this.ws = null;
|
|
18
|
-
this.filterMap = {};
|
|
19
|
-
this.listeners = {};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
onReconnect(projectId) {
|
|
23
|
-
logger.info('test result websocket re-connect');
|
|
24
|
-
setTimeout(() => this.connect(projectId), WAIT_BETWEEN_RECONNECT_MS);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/** @param {string} url */
|
|
28
|
-
formatUrl(url) {
|
|
29
|
-
if (url.startsWith('http://')) {
|
|
30
|
-
return url.replace('http://', 'ws://');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (url.startsWith('https://')) {
|
|
34
|
-
return url.replace('https://', 'wss://');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return url;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
parseEvent(event) {
|
|
41
|
-
try {
|
|
42
|
-
return JSON.parse(event);
|
|
43
|
-
} catch (err) {
|
|
44
|
-
logger.error('failed to parse or trigger event', { err });
|
|
45
|
-
}
|
|
46
|
-
return undefined;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
connect(projectId) {
|
|
50
|
-
const wsBaseUrl = this.formatUrl(WEBSOCKET_HOST);
|
|
51
|
-
return testimCustomToken.getCustomTokenV3()
|
|
52
|
-
.then(token => new Promise((resolve) => {
|
|
53
|
-
const options = {};
|
|
54
|
-
if (global.proxyUri) {
|
|
55
|
-
options.agent = new global.ProxyAgent(global.proxyUri);
|
|
56
|
-
}
|
|
57
|
-
this.ws = new WebSocket(`${wsBaseUrl}?projectId=${projectId}&clientId=${this.clientId}&token=${token}`, options);
|
|
58
|
-
|
|
59
|
-
this.ws.on('open', () => {
|
|
60
|
-
logger.info('websocket opened');
|
|
61
|
-
this.reSendAllExistingFilters();
|
|
62
|
-
if (this.onConnect) {
|
|
63
|
-
this.onConnect();
|
|
64
|
-
}
|
|
65
|
-
return resolve();
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
this.ws.on('close', (event) => {
|
|
69
|
-
logger.info('websocket closed', { event });
|
|
70
|
-
if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {
|
|
71
|
-
this.onReconnect(projectId, token, wsBaseUrl);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
this.ws.on('error', (event) => {
|
|
76
|
-
logger.info('websocket error', { event });
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
this.ws.on('message', (event) => {
|
|
80
|
-
const evObject = this.parseEvent(event);
|
|
81
|
-
if (evObject?.type) {
|
|
82
|
-
this.emit(evObject.type, evObject.data);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
}));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// this is private because our sockets are supposed to be read-only to
|
|
89
|
-
// external consumers and writes need to happen through the REST API
|
|
90
|
-
// this is important since recovery of messages is the case of reconnects is
|
|
91
|
-
// done in the code calling sendMessage and not in sendMessage itself
|
|
92
|
-
sendMessage(msg) {
|
|
93
|
-
if (!this.ws) {
|
|
94
|
-
logger.warn('tried to send error when websocket was disconnected');
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
try {
|
|
98
|
-
this.ws.send(JSON.stringify(msg));
|
|
99
|
-
} catch (err) {
|
|
100
|
-
logger.error('failed to stringify message for sending', { err });
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
listenOnce(eventName, eventMatcher, listener) {
|
|
105
|
-
const onEvent = (data) => {
|
|
106
|
-
if (eventMatcher(data)) {
|
|
107
|
-
listener(data);
|
|
108
|
-
this.removeListener(eventName, onEvent);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
this.on(eventName, onEvent);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
listenTo(key, eventName, eventMatcher, listener) {
|
|
116
|
-
//TODO - Consider doing key:value event name subscriptions here, routing inside the .on('message' into an event name based on the key and removing the listeners array.
|
|
117
|
-
function fireIfSameMatchEventMatcher(data) {
|
|
118
|
-
if (eventMatcher(data)) {
|
|
119
|
-
listener(data);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const eventNameArray = Array.isArray(eventName) ? eventName : [eventName];
|
|
124
|
-
eventNameArray.forEach(name => {
|
|
125
|
-
this.listeners[`${key}:${name}`] = this.listeners[`${key}:${name}`] || [];
|
|
126
|
-
const _listener = fireIfSameMatchEventMatcher.bind(this);
|
|
127
|
-
this.listeners[`${key}:${name}`].push(_listener);
|
|
128
|
-
this.on(name, _listener);
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
reSendAllExistingFilters() {
|
|
133
|
-
Object.keys(this.filterMap).forEach(key => {
|
|
134
|
-
const filter = this.filterMap[key];
|
|
135
|
-
this.sendMessage({ type: 'add-filter', filter });
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
addFilter(key, query, type, returnFullDocument = false) {
|
|
140
|
-
return new Promise(resolve => {
|
|
141
|
-
const filterId = utils.guid();
|
|
142
|
-
const filter = { query, id: filterId, type, fullDocument: returnFullDocument };
|
|
143
|
-
this.listenOnce('add-filter:done', data => data.id === filterId, resolve);
|
|
144
|
-
this.sendMessage({ type: 'add-filter', filter });
|
|
145
|
-
this.filterMap[key] = filter;
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
removeListeners(key, typeArray) {
|
|
150
|
-
if (Object.keys(this.listeners).length === 0) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
typeArray.forEach(name => {
|
|
154
|
-
const listeners = this.listeners[`${key}:${name}`];
|
|
155
|
-
if (listeners) {
|
|
156
|
-
delete this.listeners[`${key}:${name}`];
|
|
157
|
-
listeners.forEach(listener => this.removeListener(name, listener));
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
removeFilter(key, type) {
|
|
163
|
-
const filter = this.filterMap[key];
|
|
164
|
-
if (!filter) {
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const typeArray = Array.isArray(type) ? type : [type];
|
|
169
|
-
this.removeListeners(key, typeArray);
|
|
170
|
-
delete this.filterMap[key];
|
|
171
|
-
this.sendMessage({ type: 'remove-filter', filter });
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
module.exports = new SocketService();
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
const testResultServiceSocketIO = require('./testResultServiceSocketIO');
|
|
2
|
-
const socketService = require('./socketService');
|
|
3
|
-
|
|
4
|
-
const { EventEmitter } = require('events');
|
|
5
|
-
const featureFlags = require('../featureFlags');
|
|
6
|
-
|
|
7
|
-
const { socketEventTypes } = require('../constants');
|
|
8
|
-
|
|
9
|
-
class TestResultService extends EventEmitter {
|
|
10
|
-
init(projectId) {
|
|
11
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
12
|
-
socketService.onConnect = () => this.emit('socket-connected');
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
testResultServiceSocketIO.init(projectId);
|
|
16
|
-
testResultServiceSocketIO.onConnect = () => this.emit('socket-connected');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
joinToTestResult(resultId, testId) {
|
|
20
|
-
//TODO - Consider unifying the joinToTestResult and listenToTestResult flows
|
|
21
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
22
|
-
return socketService.addFilter(`${resultId}:testResult`, { resultId, testId }, [
|
|
23
|
-
socketEventTypes.TEST_RESULT_UPDATED,
|
|
24
|
-
socketEventTypes.TEST_RESULT_CREATED,
|
|
25
|
-
]);
|
|
26
|
-
}
|
|
27
|
-
testResultServiceSocketIO.joinRoom(resultId, testId);
|
|
28
|
-
return testResultServiceSocketIO.emitJoinRoom(resultId, testId);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
leaveTestResult(resultId, testId) {
|
|
32
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
33
|
-
socketService.removeFilter(`${resultId}:testResult`, [socketEventTypes.TEST_RESULT_UPDATED, socketEventTypes.TEST_RESULT_CREATED]);
|
|
34
|
-
return Promise.resolve();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return testResultServiceSocketIO.leaveTestResult(resultId, testId);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
listenToTestResult(resultId, testId, onTestResultStatus) {
|
|
41
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
42
|
-
socketService.listenTo(
|
|
43
|
-
`${resultId}:testResult`,
|
|
44
|
-
[socketEventTypes.TEST_RESULT_UPDATED, socketEventTypes.TEST_RESULT_CREATED],
|
|
45
|
-
data => data.resultId === resultId && data.testId === testId,
|
|
46
|
-
data => onTestResultStatus(data)
|
|
47
|
-
);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
testResultServiceSocketIO.listenToTestResult(resultId, testId, onTestResultStatus);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
getSocket() {
|
|
55
|
-
if (featureFlags.flags.useNewWSCLI.isEnabled()) {
|
|
56
|
-
return undefined;
|
|
57
|
-
}
|
|
58
|
-
return testResultServiceSocketIO.getSocket();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
module.exports = new TestResultService();
|