@testim/testim-cli 3.252.0 → 3.254.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/OverrideTestDataBuilder.js +1 -1
  2. package/agent/routers/cliJsCode/index.js +4 -4
  3. package/agent/routers/cliJsCode/router.js +46 -42
  4. package/agent/routers/cliJsCode/service.js +18 -13
  5. package/agent/routers/codim/router.js +14 -17
  6. package/agent/routers/codim/router.test.js +15 -14
  7. package/agent/routers/codim/service.js +1 -1
  8. package/agent/routers/general/index.js +4 -8
  9. package/agent/routers/hybrid/registerRoutes.js +18 -18
  10. package/agent/routers/index.js +9 -8
  11. package/agent/routers/playground/router.js +12 -11
  12. package/agent/routers/playground/service.js +19 -18
  13. package/agent/routers/standalone-browser/registerRoutes.js +10 -10
  14. package/cdpTestRunner.js +4 -3
  15. package/chromiumInstaller.js +4 -5
  16. package/cli/onExit.js +2 -2
  17. package/cli.js +7 -6
  18. package/cliAgentMode.js +4 -5
  19. package/codim/codim-cli.js +11 -10
  20. package/codim/hybrid-utils.js +1 -1
  21. package/codim/measure-perf.js +9 -6
  22. package/codim/template.js/tests/examples/01-simple-text-validation.test.js +6 -6
  23. package/codim/template.js/tests/examples/02-using-locators.test.js +13 -15
  24. package/codim/template.js/tests/examples/03-using-hooks.test.js +17 -19
  25. package/codim/template.js/tests/examples/04-skip-and-only.test.js +16 -17
  26. package/codim/template.js/tests/examples/05-multiple-windows.test.js +16 -17
  27. package/codim/template.js/webpack.config.js +1 -1
  28. package/codim/template.ts/webpack.config.js +3 -3
  29. package/commons/AbortError.js +4 -4
  30. package/commons/chrome-launcher.js +6 -6
  31. package/commons/constants.js +2 -0
  32. package/commons/detectDebugger.js +4 -2
  33. package/commons/getSessionPlayerRequire.js +2 -20
  34. package/commons/initializeUserWithAuth.js +2 -2
  35. package/commons/lazyRequire.js +10 -9
  36. package/commons/logger.js +4 -4
  37. package/commons/performance-logger.js +14 -8
  38. package/commons/prepareRunnerAndTestimStartUtils.js +6 -7
  39. package/commons/socket/baseSocketServiceSocketIO.js +32 -34
  40. package/commons/socket/realDataService.js +6 -5
  41. package/commons/socket/realDataServiceSocketIO.js +4 -4
  42. package/commons/socket/remoteStepService.js +4 -3
  43. package/commons/socket/remoteStepServiceSocketIO.js +11 -12
  44. package/commons/socket/socketService.js +50 -52
  45. package/commons/socket/testResultServiceSocketIO.js +11 -11
  46. package/commons/testimDesiredCapabilitiesBuilder.js +44 -0
  47. package/commons/testimNgrok.js +2 -2
  48. package/commons/testimNgrok.test.js +1 -1
  49. package/commons/testimServicesApi.js +37 -21
  50. package/commons/xhr2.js +97 -100
  51. package/credentialsManager.js +17 -20
  52. package/errors.js +5 -0
  53. package/fixLocalBuild.js +2 -0
  54. package/npm-shrinkwrap.json +4455 -1576
  55. package/package.json +9 -7
  56. package/player/WebdriverioWebDriverApi.js +7 -2
  57. package/player/appiumTestPlayer.js +102 -0
  58. package/player/chromeLauncherTestPlayer.js +0 -1
  59. package/player/seleniumTestPlayer.js +3 -2
  60. package/player/services/frameLocator.js +2 -1
  61. package/player/services/mobileFrameLocatorMock.js +32 -0
  62. package/player/services/playbackTimeoutCalculator.js +1 -0
  63. package/player/services/portSelector.js +10 -8
  64. package/player/services/tabService.js +29 -0
  65. package/player/services/tabServiceMock.js +166 -0
  66. package/player/stepActions/navigationStepAction.js +11 -10
  67. package/player/stepActions/sleepStepAction.js +4 -5
  68. package/player/stepActions/stepAction.js +15 -1
  69. package/player/stepActions/textStepAction.js +4 -11
  70. package/player/utils/stepActionUtils.js +4 -2
  71. package/player/utils/windowUtils.js +139 -125
  72. package/player/webdriver.js +40 -26
  73. package/processHandler.js +3 -3
  74. package/processHandler.test.js +1 -1
  75. package/reports/consoleReporter.js +3 -2
  76. package/reports/debugReporter.js +41 -39
  77. package/reports/jsonReporter.js +53 -50
  78. package/reports/junitReporter.js +1 -2
  79. package/reports/reporter.js +135 -136
  80. package/runOptions.js +8 -7
  81. package/runner.js +13 -0
  82. package/runners/ParallelWorkerManager.js +2 -0
  83. package/runners/TestPlanRunner.js +142 -74
  84. package/runners/buildCodeTests.js +38 -37
  85. package/runners/runnerUtils.js +3 -3
  86. package/services/lambdatestService.js +3 -5
  87. package/stepPlayers/cliJsStepPlayback.js +22 -17
  88. package/testRunHandler.js +8 -0
  89. package/testRunStatus.js +458 -460
  90. package/{utils.js → utils/index.js} +25 -117
  91. package/utils/promiseUtils.js +78 -0
  92. package/utils/stringUtils.js +96 -0
  93. package/{utils.test.js → utils/utils.test.js} +2 -2
  94. package/workers/BaseWorker.js +29 -20
  95. package/workers/WorkerAppium.js +123 -0
  96. package/workers/WorkerExtensionSingleBrowser.js +4 -4
  97. package/workers/WorkerSelenium.js +5 -2
@@ -1,16 +1,18 @@
1
1
  'use strict';
2
2
 
3
+ const os = require('os');
4
+ const _ = require('lodash');
5
+ const path = require('path');
3
6
  const moment = require('moment');
4
7
  const pRetry = require('p-retry');
5
- const _ = require('lodash');
6
8
  const Promise = require('bluebird');
7
- const fs = Promise.promisifyAll(require('fs'));
8
- const { W3C_ELEMENT_ID } = require('./player/constants');
9
- const { sessionType, testStatus: testStatusConst } = require('./commons/constants');
10
- const path = require('path');
11
- const httpRequest = require('./commons/httpRequest');
12
9
  const decompress = require('decompress');
13
- const os = require('os');
10
+ const fs = Promise.promisifyAll(require('fs'));
11
+ const stringUtils = require('./stringUtils');
12
+ const promiseUtils = require('./promiseUtils');
13
+ const httpRequest = require('../commons/httpRequest');
14
+ const { W3C_ELEMENT_ID } = require('../player/constants');
15
+ const { sessionType, testStatus: testStatusConst } = require('../commons/constants');
14
16
 
15
17
  const HOMEDIR = os.homedir();
16
18
  const TESTIM_BROWSER_DIR = path.join(HOMEDIR, '.testim-browser-profile');
@@ -43,6 +45,7 @@ const BROWSERS = [
43
45
  { browserName: 'Firefox', bs: { browser: 'Firefox', browser_version: '89' }, sl: { browserName: 'firefox', version: '89.0' }, browserValue: 'firefox' },
44
46
  { browserName: 'Safari', bs: { browser: 'Safari' }, sl: { browserName: 'safari' }, browserValue: 'safari' },
45
47
  { browserName: 'Edge', bs: { browser: 'Edge', browser_version: '18' }, sl: { browserName: 'MicrosoftEdge', version: '18.17763' }, browserValue: 'edge' },
48
+ // eslint-disable-next-line max-len
46
49
  { browserName: 'Edge Chromium', bs: { browser: 'Edge', browser_version: '94' }, sl: { browserName: 'MicrosoftEdge', version: '94' }, synonyms: ['edge-chromium'], browserValue: 'edge-chromium', seleniumName: 'MicrosoftEdge' },
47
50
  { browserName: 'Internet Explorer 11', bs: { browser: 'IE', browser_version: '11' }, sl: { browserName: 'internet explorer', version: '11.0' }, synonyms: ['ie11'], browserValue: 'ie11' },
48
51
  { browserName: 'Browser', bs: {}, sl: { browserName: 'Browser' }, browserValue: 'browser' },
@@ -53,7 +56,7 @@ const BROWSERS = [
53
56
 
54
57
  function getRunConfigByBrowserName(browser, saucelabs, browserstack) {
55
58
  browser = browser.toLowerCase();
56
- const selectedBrowser = BROWSERS.find(b => b.browserName.toLowerCase() === browser || browser.indexOf(b.synonyms) > -1) || BROWSERS[0];
59
+ const selectedBrowser = BROWSERS.find(b => b.browserName.toLowerCase() === browser || browser.includes(b.synonyms)) || BROWSERS[0];
57
60
 
58
61
  // BS and SL do not support Linux for newer browser, so use Windows instead.
59
62
  let selectedOS = OSS.find(x => x.osName === 'Windows 10');
@@ -75,22 +78,6 @@ function getRunConfigByBrowserName(browser, saucelabs, browserstack) {
75
78
  return _.merge(selectedBrowser, selectedOS);
76
79
  }
77
80
 
78
- function getTestUrl(editorUrl, projectId, testId, resultId, branch) {
79
- let testUrl = '';
80
- branch = branch ? encodeURIComponent(branch) : 'master';
81
- if (projectId && testId) {
82
- testUrl = `${editorUrl}/#/project/${projectId}/branch/${branch}/test/${testId}`;
83
- if (resultId) {
84
- testUrl += `?result-id=${resultId}`;
85
- }
86
- }
87
- return testUrl;
88
- }
89
-
90
- function isPromise(obj) {
91
- return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function' && typeof obj.catch === 'function';
92
- }
93
-
94
81
  function getDuration(ms) {
95
82
  const duration = moment.duration(ms);
96
83
  return `${duration.hours()}:${duration.minutes()}:${duration.seconds()}.${duration.milliseconds()}`;
@@ -102,7 +89,8 @@ function getDurationSec(ms) {
102
89
 
103
90
  function getRunnerVersion() {
104
91
  try {
105
- const pack = require(`${__dirname}/package.json`);
92
+ /** @type {import('../../package.json')} */
93
+ const pack = require(`${__dirname}/../package.json`); // eslint-disable-line import/no-dynamic-require
106
94
  return pack.version;
107
95
  } catch (err) {
108
96
  return '';
@@ -111,7 +99,8 @@ function getRunnerVersion() {
111
99
 
112
100
  function getEnginesVersion() {
113
101
  try {
114
- const pack = require(`${__dirname}/package.json`);
102
+ /** @type {import('../../package.json')} */
103
+ const pack = require(`${__dirname}/../package.json`); // eslint-disable-line import/no-dynamic-require
115
104
  return pack.engines.node;
116
105
  } catch (err) {
117
106
  return '';
@@ -120,7 +109,8 @@ function getEnginesVersion() {
120
109
 
121
110
  async function getEnginesVersionAsync() {
122
111
  try {
123
- const pack = JSON.parse(await fs.readFileAsync(`${__dirname}/package.json`));
112
+ /** @type {import('../../package.json')} */
113
+ const pack = JSON.parse(await fs.readFileAsync(`${__dirname}/../package.json`));
124
114
  return pack.engines.node;
125
115
  } catch (err) {
126
116
  return '';
@@ -138,19 +128,6 @@ function getUniqBrowsers(options, testList) {
138
128
  return [options.browser.toLowerCase()];
139
129
  }
140
130
 
141
- function randomString(length) {
142
- const a = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890';
143
- const index = (Math.random() * (a.length - 1)).toFixed(0);
144
- return length > 0 ? a[index] + randomString(length - 1) : '';
145
- }
146
-
147
- function blueBirdify(fn) {
148
- return new Promise((resolve, reject) =>
149
- fn()
150
- .then(x => resolve(x))
151
- .catch(y => reject(y)));
152
- }
153
-
154
131
  function removePropertyFromObject(obj, propName, cmpFunction) {
155
132
  for (const prop in obj) {
156
133
  if (obj.hasOwnProperty(prop)) {
@@ -169,72 +146,18 @@ function getCliLocation() {
169
146
  return process.cwd(); // fall back on the current working directory
170
147
  }
171
148
  if (require.main.filename.includes('/src') || require.main.filename.includes('\\src') || process.env.IS_UNIT_TEST) {
172
- cliLocation = path.resolve(__dirname, '../');
149
+ cliLocation = path.resolve(__dirname, '../../');
173
150
  } else {
174
- cliLocation = __dirname;
151
+ cliLocation = path.resolve(__dirname, '../');
175
152
  }
176
153
 
177
154
  return cliLocation;
178
155
  }
179
156
 
180
- function buildBasicHeader(userName, password) {
181
- const userAndPasswordBase64 = Buffer.from(`${userName}:${password}`).toString('base64');
182
- return `Basic ${userAndPasswordBase64}`;
183
- }
184
-
185
157
  function extractElementId(element) {
186
158
  return element.ELEMENT || element[W3C_ELEMENT_ID];
187
159
  }
188
160
 
189
- function isURL(path) {
190
- const legacyPattern = /^(https?:\/\/)/i;
191
-
192
- // https://gist.github.com/dperini/729294 (validator.js based on).
193
- const pattern = new RegExp(
194
- '^' +
195
- // protocol identifier (optional)
196
- // short syntax // still required
197
- '(?:(?:(?:https?|ftp):)?\\/\\/)' +
198
- // user:pass BasicAuth (optional)
199
- '(?:\\S+(?::\\S*)?@)?' +
200
- '(?:' +
201
- // IP address exclusion
202
- // private & local networks
203
- '(?!(?:10|127)(?:\\.\\d{1,3}){3})' +
204
- '(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})' +
205
- '(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})' +
206
- // IP address dotted notation octets
207
- // excludes loopback network 0.0.0.0
208
- // excludes reserved space >= 224.0.0.0
209
- // excludes network & broadcast addresses
210
- // (first & last IP address of each class)
211
- '(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])' +
212
- '(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}' +
213
- '(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))' +
214
- '|' +
215
- // host & domain names, may end with dot
216
- // can be replaced by a shortest alternative
217
- // (?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.)+
218
- '(?:' +
219
- '(?:' +
220
- '[a-z0-9\\u00a1-\\uffff]' +
221
- '[a-z0-9\\u00a1-\\uffff_-]{0,62}' +
222
- ')?' +
223
- '[a-z0-9\\u00a1-\\uffff]\\.' +
224
- ')+' +
225
- // TLD identifier name, may end with dot
226
- '(?:[a-z\\u00a1-\\uffff]{2,}\\.?)' +
227
- ')' +
228
- // port number (optional)
229
- '(?::\\d{2,5})?' +
230
- // resource path (optional)
231
- '(?:[/?#]\\S*)?' +
232
- '$', 'i'
233
- );
234
-
235
- return legacyPattern.test(path) || pattern.test(path);
236
- }
237
-
238
161
  const DOWNLOAD_RETRY = 3;
239
162
  const download = async (url) => pRetry(() => httpRequest.download(url), { retries: DOWNLOAD_RETRY });
240
163
 
@@ -255,7 +178,7 @@ const copy = async (readFile, destFile) => new Promise((resolve, reject) => {
255
178
  }
256
179
  });
257
180
  function getSourcePath(location, fileName) {
258
- if (isURL(location)) {
181
+ if (stringUtils.isURL(location)) {
259
182
  return fileName || path.join(process.cwd(), location.replace(/^.*[\\\/]/, ''));
260
183
  }
261
184
 
@@ -264,7 +187,7 @@ function getSourcePath(location, fileName) {
264
187
 
265
188
  const getSource = async (location, fileName) => {
266
189
  const destFile = getSourcePath(location, fileName);
267
- if (isURL(location)) {
190
+ if (stringUtils.isURL(location)) {
268
191
  return downloadAndSave(location, destFile);
269
192
  }
270
193
 
@@ -272,7 +195,7 @@ const getSource = async (location, fileName) => {
272
195
  };
273
196
 
274
197
  const getSourceAsBuffer = async (location) => {
275
- if (isURL(location)) {
198
+ if (stringUtils.isURL(location)) {
276
199
  return download(location);
277
200
  }
278
201
  return fs.readFileAsync(location);
@@ -304,16 +227,6 @@ function getPlanType(plan) {
304
227
  return 'free';
305
228
  }
306
229
 
307
- /**
308
- * @param time {number} in ms
309
- * @returns {Promise}
310
- */
311
- function delay(time) {
312
- return new Promise(((resolve) => {
313
- setTimeout(resolve, time);
314
- }));
315
- }
316
-
317
230
  const calcPercentile = (arr, percentile) => {
318
231
  if (arr.length === 0) return 0;
319
232
  if (typeof percentile !== 'number') throw new TypeError('p must be a number');
@@ -327,7 +240,7 @@ const calcPercentile = (arr, percentile) => {
327
240
  return arr[index];
328
241
  };
329
242
 
330
- const hasTestPlanFlag = (options) => (options.testPlan && options.testPlan.length) || (options.testPlanIds && options.testPlanIds.length);
243
+ const hasTestPlanFlag = (options) => Boolean(options.testPlan?.length || options.testPlanIds?.length);
331
244
 
332
245
  const isRemoteRun = (options) => options.resultId && options.source === 'remote-run';
333
246
 
@@ -396,22 +309,16 @@ function getArgsOnRemoteRunFailure() {
396
309
  module.exports = {
397
310
  TESTIM_BROWSER_DIR,
398
311
  removePropertyFromObject,
399
- getTestUrl,
400
312
  getDuration,
401
313
  getDurationSec,
402
314
  getRunnerVersion,
403
315
  getEnginesVersion,
404
316
  getEnginesVersionAsync,
405
- isPromise,
406
317
  getEnvironmentGitBranch,
407
318
  getUniqBrowsers,
408
- guid: (n = 16) => randomString(n),
409
319
  getRunConfigByBrowserName,
410
- blueBirdify,
411
- buildBasicHeader,
412
320
  extractElementId,
413
321
  getCliLocation,
414
- isURL,
415
322
  download,
416
323
  downloadAndSave,
417
324
  copy,
@@ -427,7 +334,8 @@ module.exports = {
427
334
  isQuarantineAndNotRemoteRun,
428
335
  groupTestsByRetries,
429
336
  getPlanType,
430
- delay,
431
337
  getCdpAddressForHost,
432
338
  getArgsOnRemoteRunFailure,
339
+ ...promiseUtils,
340
+ ...stringUtils,
433
341
  };
@@ -0,0 +1,78 @@
1
+ // @ts-check
2
+
3
+ const Bluebird = require('bluebird');
4
+ const { TimeoutError } = require('../errors');
5
+
6
+ function isPromise(obj) {
7
+ return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function' && typeof obj.catch === 'function';
8
+ }
9
+
10
+ /**
11
+ * @deprecated This is horrifying. Please stop what you are doing and think about what you just considered!
12
+ * @template T
13
+ * @param {() => Promise<T>} fn
14
+ * @returns {Bluebird<T>}
15
+ */
16
+ function blueBirdify(fn) {
17
+ return new Bluebird((resolve, reject) =>
18
+ fn()
19
+ .then(x => resolve(x))
20
+ .catch(y => reject(y)));
21
+ }
22
+
23
+ /**
24
+ * @param time {number} in ms
25
+ * @returns {Promise}
26
+ */
27
+ function delay(time) {
28
+ return new Promise(((resolve) => {
29
+ setTimeout(resolve, time);
30
+ }));
31
+ }
32
+
33
+ /**
34
+ * @template T
35
+ * @param {Promise<T> | undefined} promise
36
+ * @param {number} timeout
37
+ * @param {string=} errMsg
38
+ */
39
+ function promiseTimeout(promise, timeout, errMsg = 'Timeout Error') {
40
+ return Promise.race([
41
+ promise,
42
+ delay(timeout).then(() => { throw new TimeoutError(errMsg); }),
43
+ ]);
44
+ }
45
+
46
+ /**
47
+ * @template T, U
48
+ * @param {ArrayLike<T> | Iterable<T>} arr
49
+ * @param {(item: T, index: number) => PromiseLike<U>} handler
50
+ */
51
+ function promiseMap(arr, handler) {
52
+ return Promise.all(Array.from(arr, handler));
53
+ }
54
+
55
+ /**
56
+ * @template ErrT, T
57
+ * @param {(callback: (err: ErrT, result: T) => void) => void} resolver
58
+ * @returns {Promise<T>}
59
+ */
60
+ function promiseFromCallback(resolver) {
61
+ return new Promise((resolve, reject) => {
62
+ resolver((err, result) => {
63
+ if (err) {
64
+ return reject(err);
65
+ }
66
+ return resolve(result);
67
+ });
68
+ });
69
+ }
70
+
71
+ module.exports = {
72
+ isPromise,
73
+ blueBirdify,
74
+ delay,
75
+ promiseTimeout,
76
+ promiseMap,
77
+ promiseFromCallback,
78
+ };
@@ -0,0 +1,96 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @param {number} length
5
+ * @returns {string}
6
+ */
7
+ function randomString(length) {
8
+ const a = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890';
9
+ const index = (Math.random() * (a.length - 1)).toFixed(0);
10
+ return length > 0 ? a[index] + randomString(length - 1) : '';
11
+ }
12
+
13
+ /**
14
+ * @param {string} editorUrl
15
+ * @param {string} projectId
16
+ * @param {string} testId
17
+ * @param {string | undefined} resultId
18
+ * @param {string} branch
19
+ */
20
+ function getTestUrl(editorUrl, projectId, testId, resultId, branch) {
21
+ let testUrl = '';
22
+ branch = branch ? encodeURIComponent(branch) : 'master';
23
+ if (projectId && testId) {
24
+ testUrl = `${editorUrl}/#/project/${projectId}/branch/${branch}/test/${testId}`;
25
+ if (resultId) {
26
+ testUrl += `?result-id=${resultId}`;
27
+ }
28
+ }
29
+ return testUrl;
30
+ }
31
+
32
+ /**
33
+ * @param {string} userName
34
+ * @param {string} password
35
+ */
36
+ function buildBasicHeader(userName, password) {
37
+ const userAndPasswordBase64 = Buffer.from(`${userName}:${password}`).toString('base64');
38
+ return `Basic ${userAndPasswordBase64}`;
39
+ }
40
+
41
+ /** @param {string} path */
42
+ function isURL(path) {
43
+ const legacyPattern = /^(https?:\/\/)/i;
44
+
45
+ // https://gist.github.com/dperini/729294 (validator.js based on).
46
+ const pattern = new RegExp(
47
+ '^' +
48
+ // protocol identifier (optional)
49
+ // short syntax // still required
50
+ '(?:(?:(?:https?|ftp):)?\\/\\/)' +
51
+ // user:pass BasicAuth (optional)
52
+ '(?:\\S+(?::\\S*)?@)?' +
53
+ '(?:' +
54
+ // IP address exclusion
55
+ // private & local networks
56
+ '(?!(?:10|127)(?:\\.\\d{1,3}){3})' +
57
+ '(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})' +
58
+ '(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})' +
59
+ // IP address dotted notation octets
60
+ // excludes loopback network 0.0.0.0
61
+ // excludes reserved space >= 224.0.0.0
62
+ // excludes network & broadcast addresses
63
+ // (first & last IP address of each class)
64
+ '(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])' +
65
+ '(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}' +
66
+ '(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))' +
67
+ '|' +
68
+ // host & domain names, may end with dot
69
+ // can be replaced by a shortest alternative
70
+ // (?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.)+
71
+ '(?:' +
72
+ '(?:' +
73
+ '[a-z0-9\\u00a1-\\uffff]' +
74
+ '[a-z0-9\\u00a1-\\uffff_-]{0,62}' +
75
+ ')?' +
76
+ '[a-z0-9\\u00a1-\\uffff]\\.' +
77
+ ')+' +
78
+ // TLD identifier name, may end with dot
79
+ '(?:[a-z\\u00a1-\\uffff]{2,}\\.?)' +
80
+ ')' +
81
+ // port number (optional)
82
+ '(?::\\d{2,5})?' +
83
+ // resource path (optional)
84
+ '(?:[/?#]\\S*)?' +
85
+ '$', 'i'
86
+ );
87
+
88
+ return legacyPattern.test(path) || pattern.test(path);
89
+ }
90
+
91
+ module.exports = {
92
+ isURL,
93
+ getTestUrl,
94
+ buildBasicHeader,
95
+ guid: (n = 16) => randomString(n),
96
+ };
@@ -1,5 +1,5 @@
1
- const chai = require('chai');
2
- const utils = require('./utils');
1
+ const chai = require('chai'); // eslint-disable-line import/no-extraneous-dependencies
2
+ const utils = require('./index');
3
3
 
4
4
  const expect = chai.expect;
5
5
 
@@ -1,11 +1,10 @@
1
1
  'use strict';
2
2
 
3
- const Bluebird = require('bluebird');
4
3
  const moment = require('moment');
5
4
  const pRetry = require('p-retry');
6
5
  const ms = require('ms');
7
6
 
8
- const { timeoutMessages, testRunStatus, stepResult, runnerTestStatus } = require('../commons/constants');
7
+ const { timeoutMessages, testRunStatus, stepResult, runnerTestStatus, CLI_MODE } = require('../commons/constants');
9
8
  const logger = require('../commons/logger').getLogger('base-worker');
10
9
  const testResultService = require('../commons/socket/testResultService');
11
10
  const remoteStepService = require('../commons/socket/remoteStepService');
@@ -110,8 +109,15 @@ class BaseWorker {
110
109
  return undefined;
111
110
  }
112
111
 
112
+ setSessionTimeout() {
113
+ if (this.options.mode === CLI_MODE.APPIUM) {
114
+ return Math.max(ms('180s'), this.options.getSessionTimeout);
115
+ }
116
+ return Math.max(this.lambdatestService.getSessionTimeout, this.options.getSessionTimeout);
117
+ }
118
+
113
119
  async getTestPlayer(testRunHandler, customExtensionLocalLocation) {
114
- const projectId = this.userData && this.userData.projectId;
120
+ const projectId = this.userData?.projectId;
115
121
  let testPlayer;
116
122
 
117
123
  try {
@@ -121,8 +127,7 @@ class BaseWorker {
121
127
  let gridInfo = await pRetry(async () => {
122
128
  const startTime = Date.now();
123
129
  try {
124
- return await Bluebird.resolve(this.getSlotOnce(testRunHandler))
125
- .timeout(this.options.getBrowserTimeout, timeoutMessages.GET_BROWSER_TIMEOUT_MSG);
130
+ return await utils.promiseTimeout(this.getSlotOnce(testRunHandler), this.options.getBrowserTimeout, timeoutMessages.GET_BROWSER_TIMEOUT_MSG);
126
131
  } catch (error) {
127
132
  logger.error('error getting grid slot', { error, testId: this.testId, testResultId: this.testResultId, executionId: this.executionId });
128
133
  failedGetSlotAttempts++;
@@ -148,12 +153,14 @@ class BaseWorker {
148
153
  this.options.gridData.provider = gridInfo.provider;
149
154
  this.options.gridData.host = gridInfo.host;
150
155
  this.options.gridData.failedGetBrowserAttempts = failedGetBrowserAttempts;
151
- const getSessionTimeout = Math.max(this.lambdatestService.getSessionTimeout, this.options.getSessionTimeout);
152
- const getBrowserRes = await Bluebird.resolve()
153
- .log('before getBrowserOnce')
154
- .then(() => this.getBrowserOnce(testRunHandler, customExtensionLocalLocation, player, gridInfo))
155
- .log('after getBrowserOnce')
156
- .timeout(getSessionTimeout, timeoutMessages.GET_BROWSER_TIMEOUT_MSG);
156
+ const getSessionTimeout = this.setSessionTimeout();
157
+ perf.log('before getBrowserOnce');
158
+ const getBrowserRes = await utils.promiseTimeout(
159
+ this.getBrowserOnce(testRunHandler, customExtensionLocalLocation, player, gridInfo),
160
+ getSessionTimeout,
161
+ timeoutMessages.GET_BROWSER_TIMEOUT_MSG,
162
+ );
163
+ perf.log('after getBrowserOnce');
157
164
  reporter.onGetBrowserSuccess(this.id, projectId);
158
165
  return player || getBrowserRes;
159
166
  } catch (error) {
@@ -186,7 +193,7 @@ class BaseWorker {
186
193
 
187
194
  async runTest(testRunHandler, customExtensionLocalLocation, shouldRerun) {
188
195
  perf.log('inside runTest');
189
- const projectId = this.userData && this.userData.projectId;
196
+ const projectId = this.userData?.projectId;
190
197
  const quarantineResult = this.handleQuarantine(testRunHandler);
191
198
  if (quarantineResult) {
192
199
  return quarantineResult;
@@ -236,7 +243,7 @@ class BaseWorker {
236
243
  const testRetryKey = testRunHandler.getRetryKey();
237
244
  testResult.testRetryKey = testRetryKey;
238
245
  await this.onTestCompleted(this.id, this.testId, testResult, sessionId, shouldRerun);
239
- if (this.executionQueue.hasMoreTests() && !(this.options.lightweightMode && this.options.lightweightMode.general)) {
246
+ if (this.executionQueue.hasMoreTests() && !this.options.lightweightMode?.general) {
240
247
  await utils.delay(DELAY_BETWEEN_TESTS);
241
248
  }
242
249
  await this.runTestCleanup();
@@ -257,11 +264,11 @@ class BaseWorker {
257
264
  return await runTestAndCalcResult(testRunHandler, shouldRerun);
258
265
  }
259
266
  return await runNextTest();
260
- } catch (err) {
261
- if (err instanceof StopRunOnError) {
267
+ } catch (error) {
268
+ if (error instanceof StopRunOnError) {
262
269
  return undefined;
263
270
  }
264
- logger.error('failed to process test result', { err });
271
+ logger.error('failed to process test result', { error });
265
272
  runNextTest();
266
273
  return undefined;
267
274
  }
@@ -335,7 +342,7 @@ class BaseWorker {
335
342
  }
336
343
  logger.warn('error on run', { err });
337
344
 
338
- const projectId = this.userData && this.userData.projectId;
345
+ const projectId = this.userData?.projectId;
339
346
  const { errorType, reason } = buildError(err, wasNetworkHealthy);
340
347
  testimServicesApi.updateTestResult(projectId, this.testResultId, this.testId, {
341
348
  status: testRunStatus.COMPLETED,
@@ -351,7 +358,7 @@ class BaseWorker {
351
358
  const recoverTestResults = async (runError, testRunHandler) => {
352
359
  const testId = this.testId;
353
360
  const resultId = this.testResultId;
354
- const projectId = this.userData && this.userData.projectId;
361
+ const projectId = this.userData?.projectId;
355
362
  const branch = this.branch;
356
363
  if (!testId || !resultId || !projectId || !branch) {
357
364
  // Not enough data to call the API
@@ -380,8 +387,8 @@ class BaseWorker {
380
387
  }
381
388
  };
382
389
 
383
- const disableResults = this.options.disableSockets || (this.options.lightweightMode && this.options.lightweightMode.disableResults && (this.options.useChromeLauncher || this.options.mode !== 'extension'));
384
- const disableRemoteStep = this.options.disableSockets || (this.options.lightweightMode && this.options.lightweightMode.disableRemoteStep);
390
+ const disableResults = this.options.disableSockets || (this.options.lightweightMode?.disableResults && (this.options.useChromeLauncher || this.options.mode !== 'extension'));
391
+ const disableRemoteStep = this.options.disableSockets || (this.options.lightweightMode?.disableRemoteStep);
385
392
 
386
393
  const runTestAndCalcResult = (testRunHandler, shouldRerun) => Promise.all([
387
394
  !disableRemoteStep && remoteStepService.joinToRemoteStep(this.testResultId),
@@ -402,6 +409,7 @@ class BaseWorker {
402
409
  });
403
410
 
404
411
  const testRunHandler = this.executionQueue.getNext();
412
+
405
413
  if (!testRunHandler) { // no more tests to run
406
414
  return this.onQueueCompleted();
407
415
  }
@@ -411,6 +419,7 @@ class BaseWorker {
411
419
  this.overrideTestConfigId = testRunHandler.getOverrideTestConfigId();
412
420
  this.testRunConfig = testRunHandler.getRunConfig();
413
421
  this.branch = testRunHandler.getBranch();
422
+
414
423
  return runTestAndCalcResult(testRunHandler);
415
424
  }
416
425
  }