@testim/testim-cli 3.289.0 → 3.290.0-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.
Files changed (217) hide show
  1. package/cli.js +22390 -122
  2. package/cli.js.map +1 -0
  3. package/npm-shrinkwrap.json +8 -29129
  4. package/package.json +16 -10
  5. package/OverrideTestDataBuilder.js +0 -117
  6. package/agent/routers/cliJsCode/index.js +0 -13
  7. package/agent/routers/cliJsCode/router.js +0 -63
  8. package/agent/routers/cliJsCode/service.js +0 -705
  9. package/agent/routers/codim/router.js +0 -69
  10. package/agent/routers/codim/router.test.js +0 -60
  11. package/agent/routers/codim/service.js +0 -193
  12. package/agent/routers/general/index.js +0 -36
  13. package/agent/routers/hybrid/registerRoutes.js +0 -81
  14. package/agent/routers/index.js +0 -56
  15. package/agent/routers/playground/router.js +0 -77
  16. package/agent/routers/playground/service.js +0 -96
  17. package/agent/routers/standalone-browser/registerRoutes.js +0 -47
  18. package/agent/server.js +0 -150
  19. package/cdpTestRunner.js +0 -86
  20. package/chromiumInstaller.js +0 -91
  21. package/cli/isCiRun.js +0 -10
  22. package/cli/onExit.js +0 -65
  23. package/cli/writeStackTrace.js +0 -27
  24. package/cliAgentMode.js +0 -384
  25. package/codim/codim-cli.js +0 -91
  26. package/codim/codim-npm-package/index.ts +0 -427
  27. package/codim/codim-npm-package/package-lock.json +0 -14
  28. package/codim/codim-npm-package/package.json +0 -14
  29. package/codim/hybrid-utils.js +0 -28
  30. package/codim/measure-perf.js +0 -41
  31. package/codim/template.js/.idea/workspace.xml +0 -57
  32. package/codim/template.js/.vscode/launch.json +0 -53
  33. package/codim/template.ts/.idea/workspace.xml +0 -57
  34. package/codim/template.ts/.vscode/launch.json +0 -55
  35. package/commons/AbortError.js +0 -12
  36. package/commons/SeleniumPerfStats.js +0 -58
  37. package/commons/chrome-launcher.js +0 -15
  38. package/commons/chromedriverWrapper.js +0 -70
  39. package/commons/config.js +0 -39
  40. package/commons/constants.js +0 -67
  41. package/commons/detectDebugger.js +0 -19
  42. package/commons/featureAvailabilityService.js +0 -26
  43. package/commons/featureFlags.js +0 -132
  44. package/commons/getSessionPlayerRequire.js +0 -28
  45. package/commons/httpRequest.js +0 -261
  46. package/commons/httpRequestCounters.js +0 -98
  47. package/commons/httpRequestCounters.test.js +0 -38
  48. package/commons/initializeUserWithAuth.js +0 -55
  49. package/commons/lazyRequire.js +0 -105
  50. package/commons/logUtils.js +0 -15
  51. package/commons/logUtils.test.js +0 -21
  52. package/commons/logger.js +0 -178
  53. package/commons/mockNetworkRuleFileSchema.json +0 -140
  54. package/commons/npmWrapper.js +0 -174
  55. package/commons/npmWrapper.test.js +0 -374
  56. package/commons/performance-logger.js +0 -71
  57. package/commons/preloadTests.js +0 -29
  58. package/commons/prepareRunner.js +0 -85
  59. package/commons/prepareRunner.test.js +0 -144
  60. package/commons/prepareRunnerAndTestimStartUtils.js +0 -198
  61. package/commons/prepareRunnerAndTestimStartUtils.test.js +0 -73
  62. package/commons/requireWithFallback.js +0 -25
  63. package/commons/runnerFileCache.js +0 -204
  64. package/commons/socket/baseSocketServiceSocketIO.js +0 -197
  65. package/commons/socket/realDataService.js +0 -59
  66. package/commons/socket/realDataServiceSocketIO.js +0 -33
  67. package/commons/socket/remoteStepService.js +0 -55
  68. package/commons/socket/remoteStepServiceSocketIO.js +0 -61
  69. package/commons/socket/socketService.js +0 -175
  70. package/commons/socket/testResultService.js +0 -62
  71. package/commons/socket/testResultServiceSocketIO.js +0 -64
  72. package/commons/testimAnalytics.js +0 -40
  73. package/commons/testimCloudflare.js +0 -83
  74. package/commons/testimCloudflare.test.js +0 -185
  75. package/commons/testimCustomToken.js +0 -124
  76. package/commons/testimDesiredCapabilitiesBuilder.js +0 -647
  77. package/commons/testimNgrok.js +0 -90
  78. package/commons/testimNgrok.test.js +0 -140
  79. package/commons/testimServicesApi.js +0 -631
  80. package/commons/testimTunnel.js +0 -73
  81. package/commons/testimTunnel.test.js +0 -172
  82. package/commons/xhr2.js +0 -897
  83. package/coverage/SummaryToObjectReport.js +0 -19
  84. package/coverage/jsCoverage.js +0 -252
  85. package/credentialsManager.js +0 -142
  86. package/errors.js +0 -161
  87. package/executionQueue.js +0 -37
  88. package/fixLocalBuild.js +0 -24
  89. package/inputFileUtils.js +0 -103
  90. package/lib/coralogix-winston.transport.js +0 -99
  91. package/player/SeleniumProtocolError.js +0 -100
  92. package/player/WebDriverHttpRequest.js +0 -177
  93. package/player/WebdriverioWebDriverApi.js +0 -671
  94. package/player/appiumTestPlayer.js +0 -90
  95. package/player/chromeLauncherTestPlayer.js +0 -67
  96. package/player/constants.js +0 -332
  97. package/player/extensionTestPlayer.js +0 -32
  98. package/player/findElementStrategy.js +0 -154
  99. package/player/scripts/isElementDisplayed.js +0 -252
  100. package/player/seleniumTestPlayer.js +0 -140
  101. package/player/services/frameLocator.js +0 -170
  102. package/player/services/mobileFrameLocatorMock.js +0 -32
  103. package/player/services/playbackTimeoutCalculator.js +0 -175
  104. package/player/services/portSelector.js +0 -19
  105. package/player/services/tabService.js +0 -551
  106. package/player/services/tabServiceMock.js +0 -167
  107. package/player/services/windowCreationListener.js +0 -8
  108. package/player/stepActions/RefreshStepAction.js +0 -16
  109. package/player/stepActions/apiStepAction.js +0 -89
  110. package/player/stepActions/baseCliJsStepAction.js +0 -51
  111. package/player/stepActions/baseJsStepAction.js +0 -277
  112. package/player/stepActions/cliConditionStepAction.js +0 -11
  113. package/player/stepActions/cliJsStepAction.js +0 -11
  114. package/player/stepActions/dropFileStepAction.js +0 -34
  115. package/player/stepActions/evaluateExpressionStepAction.js +0 -52
  116. package/player/stepActions/extensionOnlyStepAction.js +0 -12
  117. package/player/stepActions/extractTextStepAction.js +0 -19
  118. package/player/stepActions/hoverStepAction.js +0 -55
  119. package/player/stepActions/inputFileStepAction.js +0 -199
  120. package/player/stepActions/jsCodeStepAction.js +0 -11
  121. package/player/stepActions/jsConditionStepAction.js +0 -11
  122. package/player/stepActions/locateStepAction.js +0 -159
  123. package/player/stepActions/mouseStepAction.js +0 -370
  124. package/player/stepActions/navigationStepAction.js +0 -29
  125. package/player/stepActions/nodePackageStepAction.js +0 -47
  126. package/player/stepActions/pixelValidationStepAction.js +0 -39
  127. package/player/stepActions/scripts/dispatchEvents.js +0 -282
  128. package/player/stepActions/scripts/doClick.js +0 -221
  129. package/player/stepActions/scripts/doDragPath.js +0 -225
  130. package/player/stepActions/scripts/doubleClick.js +0 -119
  131. package/player/stepActions/scripts/dropEvent.js +0 -63
  132. package/player/stepActions/scripts/focusElement.js +0 -46
  133. package/player/stepActions/scripts/html5dragAction.js +0 -56
  134. package/player/stepActions/scripts/html5dragActionV2.js +0 -312
  135. package/player/stepActions/scripts/runCode.js +0 -147
  136. package/player/stepActions/scripts/scroll.js +0 -90
  137. package/player/stepActions/scripts/selectOption.js +0 -51
  138. package/player/stepActions/scripts/setText.js +0 -415
  139. package/player/stepActions/scripts/wheel.js +0 -61
  140. package/player/stepActions/scrollStepAction.js +0 -96
  141. package/player/stepActions/selectOptionStepAction.js +0 -49
  142. package/player/stepActions/sfdcRecordedStepAction.js +0 -24
  143. package/player/stepActions/sfdcStepAction.js +0 -28
  144. package/player/stepActions/sleepStepAction.js +0 -12
  145. package/player/stepActions/specialKeyStepAction.js +0 -52
  146. package/player/stepActions/stepAction.js +0 -73
  147. package/player/stepActions/stepActionRegistrar.js +0 -111
  148. package/player/stepActions/submitStepAction.js +0 -12
  149. package/player/stepActions/tdkHybridStepAction.js +0 -18
  150. package/player/stepActions/textStepAction.js +0 -110
  151. package/player/stepActions/textValidationStepAction.js +0 -64
  152. package/player/stepActions/wheelStepAction.js +0 -41
  153. package/player/utils/cookieUtils.js +0 -39
  154. package/player/utils/eyeSdkService.js +0 -250
  155. package/player/utils/imageCaptureUtils.js +0 -267
  156. package/player/utils/screenshotUtils.js +0 -68
  157. package/player/utils/stepActionUtils.js +0 -90
  158. package/player/utils/windowUtils.js +0 -195
  159. package/player/webDriverUtils.js +0 -40
  160. package/player/webDriverUtils.test.js +0 -116
  161. package/player/webdriver.js +0 -976
  162. package/polyfills/Array.prototype.at.js +0 -13
  163. package/polyfills/index.js +0 -13
  164. package/processHandler.js +0 -79
  165. package/processHandler.test.js +0 -55
  166. package/reports/chromeReporter.js +0 -17
  167. package/reports/consoleReporter.js +0 -190
  168. package/reports/debugReporter.js +0 -82
  169. package/reports/jsonReporter.js +0 -55
  170. package/reports/junitReporter.js +0 -183
  171. package/reports/reporter.js +0 -166
  172. package/reports/reporterUtils.js +0 -54
  173. package/reports/teamCityReporter.js +0 -73
  174. package/runOptions.d.ts +0 -305
  175. package/runOptions.js +0 -1288
  176. package/runOptionsAgentFlow.js +0 -87
  177. package/runOptionsUtils.js +0 -60
  178. package/runner.js +0 -355
  179. package/runners/ParallelWorkerManager.js +0 -284
  180. package/runners/TestPlanRunner.js +0 -419
  181. package/runners/buildCodeTests.js +0 -159
  182. package/runners/runnerUtils.js +0 -81
  183. package/services/analyticsService.js +0 -96
  184. package/services/branchService.js +0 -29
  185. package/services/gridService.js +0 -357
  186. package/services/gridService.test.js +0 -357
  187. package/services/labFeaturesService.js +0 -64
  188. package/services/lambdatestService.js +0 -227
  189. package/services/lambdatestService.test.js +0 -353
  190. package/services/localRCASaver.js +0 -124
  191. package/stepPlayers/cliJsStepPlayback.js +0 -40
  192. package/stepPlayers/hybridStepPlayback.js +0 -140
  193. package/stepPlayers/nodePackageStepPlayback.js +0 -28
  194. package/stepPlayers/playwrightHybridStepPlayback.js +0 -61
  195. package/stepPlayers/puppeteerHybridStepPlayback.js +0 -76
  196. package/stepPlayers/remoteStepPlayback.js +0 -80
  197. package/stepPlayers/seleniumHybridStepPlayback.js +0 -84
  198. package/stepPlayers/tdkHybridStepPlayback.js +0 -112
  199. package/testRunHandler.js +0 -603
  200. package/testRunStatus.js +0 -567
  201. package/testimNpmDriver.js +0 -52
  202. package/utils/argsUtils.js +0 -91
  203. package/utils/argsUtils.test.js +0 -32
  204. package/utils/fsUtils.js +0 -174
  205. package/utils/index.js +0 -197
  206. package/utils/promiseUtils.js +0 -85
  207. package/utils/stringUtils.js +0 -98
  208. package/utils/stringUtils.test.js +0 -22
  209. package/utils/timeUtils.js +0 -25
  210. package/utils/utils.test.js +0 -27
  211. package/workers/BaseWorker.js +0 -498
  212. package/workers/BaseWorker.test.js +0 -186
  213. package/workers/WorkerAppium.js +0 -180
  214. package/workers/WorkerExtension.js +0 -192
  215. package/workers/WorkerExtensionSingleBrowser.js +0 -77
  216. package/workers/WorkerSelenium.js +0 -253
  217. package/workers/workerUtils.js +0 -20
@@ -1,647 +0,0 @@
1
- /* eslint-disable camelcase */
2
-
3
- 'use strict';
4
-
5
- const crypto = require('crypto');
6
- const _ = require('lodash');
7
- const fs = require('fs');
8
- const path = require('path');
9
-
10
- const featureFlags = require('./featureFlags');
11
- const { CLI_MODE, mobileWeb, gridTypes } = require('./constants');
12
- const config = require('./config');
13
- const utils = require('../utils');
14
- const LambdatestService = require('../services/lambdatestService');
15
- const logger = require('./logger').getLogger('testim-desired-capabilities-builder');
16
-
17
- const LOG_LEVEL = config.WEBDRIVER_DEBUG ? 'verbose' : 'silent';
18
- const CONTENT_SETTING = {
19
- CONTENT_SETTING_DEFAULT: 0,
20
- CONTENT_SETTING_ALLOW: 1,
21
- CONTENT_SETTING_BLOCK: 2,
22
- CONTENT_SETTING_ASK: 3,
23
- };
24
- const DEFAULT_CHROME_OPTIONS_ARGS = [
25
- '--disable-popup-blocking',
26
- '--ignore-gpu-blacklist',
27
- '--auto-select-desktop-capture-source=Entire screen',
28
- '--ignore-certificate-errors',
29
- // Disable built-in Google Translate service
30
- '--disable-features=TranslateUI',
31
- // Disable various background network services, including extension updating,
32
- // safe browsing service, upgrade detector, translate, UMA
33
- '--disable-background-networking',
34
- // Disable syncing to a Google account
35
- '--disable-sync',
36
- // Disable reporting to UMA, but allows for collection
37
- '--metrics-recording-only',
38
- // Disable installation of default apps on first run
39
- '--disable-default-apps',
40
- // Mute any audio
41
- '--mute-audio',
42
- // Skip first run wizards
43
- '--no-first-run',
44
- '--disable-back-forward-cache',
45
- ];
46
-
47
- const getHash = (...str) => crypto.createHash('sha256').update(str.join('')).digest('hex');
48
-
49
- const isDFGrid = (gridInfo) => gridInfo.type === gridTypes.DEVICE_FARM || (gridInfo.type === gridTypes.HYBRID && gridInfo.provider === 'devicefarm');
50
-
51
- const convertToNewCapabilitiesFormat = (desiredCapabilities) => {
52
- if (desiredCapabilities.hasOwnProperty('version')) {
53
- desiredCapabilities.browserVersion = desiredCapabilities.version;
54
- delete desiredCapabilities.version;
55
- }
56
- if (desiredCapabilities.hasOwnProperty('platform')) {
57
- desiredCapabilities.platformName = desiredCapabilities.platform;
58
- delete desiredCapabilities.platform;
59
- }
60
- if (desiredCapabilities.hasOwnProperty('acceptSslCerts')) {
61
- desiredCapabilities.acceptInsecurecerts = desiredCapabilities.acceptSslCerts;
62
- delete desiredCapabilities.acceptSslCerts;
63
- }
64
- if (desiredCapabilities.hasOwnProperty('unexpectedAlertBehaviour')) {
65
- desiredCapabilities.unhandledPromptBehavior = desiredCapabilities.unexpectedAlertBehaviour;
66
- delete desiredCapabilities.unexpectedAlertBehaviour;
67
- }
68
- };
69
-
70
- function buildSafariOptions(opts, browserName) {
71
- const safariOptions = { browserName: 'safari' };
72
-
73
- if (browserName === 'safari technology preview') {
74
- safariOptions['safari.options'] = { technologyPreview: true };
75
- }
76
-
77
- Object.assign(opts.desiredCapabilities, safariOptions);
78
- return opts;
79
- }
80
-
81
- function readFileToBase64(fileLocation) {
82
- return fs.readFileSync(fileLocation, { encoding: 'base64' });
83
- }
84
-
85
- function setCustomExtension(customExtensionLocalLocation, extensions, lambdatestService) {
86
- if (lambdatestService?.isLambdatestRun() && utils.isURL(customExtensionLocalLocation)) {
87
- return;
88
- }
89
-
90
- if (customExtensionLocalLocation) {
91
- const extStr = readFileToBase64(customExtensionLocalLocation);
92
- // for debugging purpose should be removed in the future
93
- logger.info(`adding extension: custom, path: ${customExtensionLocalLocation} length: ${extStr.length} hash: ${getHash(extStr)} current extension count: ${extensions.length}`);
94
- extensions.push(extStr);
95
- }
96
- }
97
-
98
- function setTestimExtension(browserOptions, extensions, args, predefinedTestimExtension, lambdatestService) {
99
- if (lambdatestService?.isLambdatestRun()) {
100
- return;
101
- }
102
-
103
- if (browserOptions.ext || predefinedTestimExtension) {
104
- const extFromOptions = typeof (browserOptions.ext) === 'string' ? browserOptions.ext : (`${__dirname}/..`);
105
- const ext = predefinedTestimExtension || extFromOptions;
106
- const loadExt = `--load-extension=${ext}`;
107
- logger.info(`adding extension: testim unpacked , path: ${ext}`);
108
- args.push(loadExt);
109
- return;
110
- }
111
-
112
- const zipFileSuffix = browserOptions.canary ? '-master.zip' : '.zip';
113
- const filePath = path.join(process.cwd(), `testim-headless${zipFileSuffix}`);
114
- const extStr = readFileToBase64(filePath);
115
- // for debugging purpose should be removed in the future
116
- logger.info(`adding extension: testim zipped, path: ${filePath} length: ${extStr.length} hash: ${getHash(extStr)} current extension count: ${extensions.length}`);
117
- extensions.push(extStr);
118
- }
119
-
120
- function _buildChromiumOptions(opts, browserOptions, testRunConfig, customExtensionLocalLocation, gridInfo, predefinedTestimExtension, lambdatestService) {
121
- // * Make sure to add any referenced attributes of the function arguments to the hash created in buildChromiumOptions * //
122
-
123
- const browserName = testRunConfig.seleniumName || testRunConfig.browserValue;
124
- const extensions = [];
125
- const args = [...DEFAULT_CHROME_OPTIONS_ARGS];
126
- if (browserOptions.headless) {
127
- args.push('--headless');
128
- }
129
- //sauce labs issues - if you set w3c = true sauce search the data in capabilities instead of desiredCapabilities
130
- const isW3CMode = () => browserOptions.mode !== CLI_MODE.EXTENSION;
131
- const chromiumOptions = {
132
- prefs: {
133
- 'profile.default_content_setting_values.popups': CONTENT_SETTING.CONTENT_SETTING_ALLOW,
134
- // allow multiple download files
135
- 'profile.default_content_setting_values.automatic_downloads': CONTENT_SETTING.CONTENT_SETTING_ALLOW,
136
- // disable pdf viewer
137
- 'plugins.always_open_pdf_externally': true,
138
- // unintuitively stops download protection ("Dangerous file blocked")
139
- // if needed in the future, consider adding --safebrowsing-disable-download-protection or --safebrowsing-disable-extension-blacklist to the chrome flags
140
- 'safebrowsing.enabled': true,
141
- 'profile.content_settings.exceptions.clipboard': {
142
- '[*.],*': { last_modified: Date.now(), setting: 1 },
143
- },
144
- 'download.allow_office_viewer_for_download': false,
145
- },
146
- w3c: isW3CMode(),
147
- };
148
-
149
- if (isDFGrid(gridInfo)) {
150
- chromiumOptions.prefs['download.default_directory'] = 'C:\\Users\\testnode';
151
- chromiumOptions.w3c = true;
152
- opts.desiredCapabilities.version = 'latest-1';
153
- opts.desiredCapabilities['aws:maxDurationSecs'] = 2400; // Maximum duration of the session before it is forcibly closed, in seconds. Range: 180 to 2400.
154
- opts.desiredCapabilities['aws:idleTimeoutSecs'] = 60; // Maximum delay between WebDriver commands before the session is forcibly closed. Range: 30 to 900.
155
- }
156
-
157
- if (isDFGrid(gridInfo) && browserName === 'MicrosoftEdge') {
158
- opts.desiredCapabilities['ms:edgeChromium'] = true;
159
- }
160
-
161
- if (browserOptions.chromeExtraPrefs) {
162
- Object.assign(chromiumOptions.prefs, browserOptions.chromeExtraPrefs);
163
- }
164
-
165
- if (browserOptions.chromeExtraArgs) {
166
- browserOptions.chromeExtraArgs.forEach(arg => args.push(`--${arg}`));
167
- }
168
-
169
- if (browserOptions.chromeBlockLocation) {
170
- chromiumOptions.prefs['profile.default_content_setting_values.geolocation'] = CONTENT_SETTING.CONTENT_SETTING_BLOCK;
171
- }
172
-
173
- if (browserOptions.chromeUserDataDir) {
174
- args.push(`--user-data-dir=${browserOptions.chromeUserDataDir}`);
175
- }
176
-
177
- if (browserOptions.projectData?.defaults?.disableChromiumGpu) {
178
- args.push('--disable-gpu');
179
- }
180
-
181
- Object.assign(opts.desiredCapabilities, { browserName });
182
-
183
- function setMobileEmulationSettings() {
184
- if (testRunConfig.mobileEmulation) {
185
- chromiumOptions.mobileEmulation = {
186
- deviceMetrics: {
187
- width: testRunConfig.mobileEmulation.device.width,
188
- height: testRunConfig.mobileEmulation.device.height + mobileWeb.MOBILE_WEB_REMOTE_RUN_HEADER_SPACING,
189
- pixelRatio: testRunConfig.mobileEmulation.device.deviceScaleFactor,
190
- },
191
- userAgent: testRunConfig.mobileEmulation.userAgent,
192
- };
193
- }
194
- }
195
-
196
- setMobileEmulationSettings();
197
-
198
- setCustomExtension(customExtensionLocalLocation, extensions, lambdatestService);
199
- if (browserOptions.mode === CLI_MODE.EXTENSION) {
200
- setTestimExtension(browserOptions, extensions, args, predefinedTestimExtension, lambdatestService);
201
- }
202
- if (extensions.length > 0) {
203
- chromiumOptions.extensions = extensions;
204
- }
205
-
206
- if (browserOptions.disableCookiesSameSiteNoneRequiresSecure) {
207
- chromiumOptions.localState = {
208
- 'browser.enabled_labs_experiments': [
209
- 'cookies-without-same-site-must-be-secure@2',
210
- ],
211
- };
212
- }
213
-
214
- chromiumOptions.args = args;
215
- const optionsKey = { MicrosoftEdge: 'edgeOptions', chrome: 'chromeOptions' }[browserName];
216
- const vendor = { MicrosoftEdge: 'ms', chrome: 'goog' }[browserName];
217
-
218
- if (LambdatestService.isLambdatestGrid(gridInfo)) {
219
- delete chromiumOptions.w3c;
220
- }
221
-
222
- if (browserOptions.oldCapabilities && gridInfo.type !== 'testimEnterprise' && !lambdatestService?.isLambdatestRun()) {
223
- opts.desiredCapabilities[optionsKey] = chromiumOptions;
224
- }
225
-
226
- if (browserOptions.w3cCapabilities || gridInfo.type === 'testimEnterprise') {
227
- opts.desiredCapabilities[`${vendor}:${optionsKey}`] = chromiumOptions;
228
- }
229
-
230
- return opts;
231
- }
232
-
233
- const buildChromiumOptions = _.memoize(_buildChromiumOptions, (opts, browserOptions, testRunConfig, customExtensionLocalLocation, gridInfo, predefinedTestimExtension) => {
234
- // Only hash the attributes which are used in _buildChromiumOptions, some others (which are irrelevant) change and invalidate the hash
235
- const stringOptsDesiredCapabilities = JSON.stringify(opts.desiredCapabilities);
236
- const stringBrowserOptions = JSON.stringify(_.omit(browserOptions, 'runParams'));
237
- const stringTestRunConfig = JSON.stringify(testRunConfig);
238
- const stringGridInfoType = JSON.stringify(gridInfo.type);
239
- return getHash(stringOptsDesiredCapabilities, stringBrowserOptions, stringTestRunConfig, customExtensionLocalLocation, stringGridInfoType, predefinedTestimExtension);
240
- });
241
-
242
-
243
- // list of content type that Firefox browser will not open the download popup and start the download automaticlly into Downloads folder
244
- const FIREFOX_FILE_NEVER_ASK = [
245
- 'application/force-download',
246
- 'application/pdf',
247
- 'application/x-pdf',
248
- 'application/acrobat',
249
- 'applications/vnd.pdf',
250
- 'text/pdf',
251
- 'text/x-pdf',
252
- 'application/vnd.cups-pdf',
253
- ];
254
-
255
- function buildFirefoxOptions(opts, browserOptions, lambdatestService) {
256
- const fireFoxPrefs = {
257
- 'pdfjs.disabled': true, //disable pdf viewer. Otherwise, the pdf viewer takes over when we download a pdf.
258
- };
259
-
260
- if (featureFlags.flags.autoSaveDownloadFileFireFox.isEnabled()) {
261
- Object.assign(fireFoxPrefs, {
262
- 'browser.helperApps.neverAsk.saveToDisk': FIREFOX_FILE_NEVER_ASK.join(','),
263
- 'browser.helperApps.neverAsk.openFile': FIREFOX_FILE_NEVER_ASK.join(','),
264
- 'browser.helperApps.alwaysAsk.force': false,
265
- 'browser.download.manager.useWindow': false, // A boolean value indicating whether or not to use the Downloads window (true) or display download status in the status bar (false) in the browser window.
266
- 'browser.download.manager.focusWhenStarting': false, // A boolean value that indicates whether or not to focus the Download Manager window when a download begins.
267
- 'browser.download.manager.alertOnEXEOpen': false, // A boolean value that indicates whether the UI Should alert the user about the dangers of opening (executing) an EXE. The user may check a "don't ask" box on the UI to toggle this.
268
- 'browser.download.manager.showWhenStarting': false, // A boolean value that indicates whether or not to show the Downloads window when a download begins.
269
- 'browser.download.manager.closeWhenDone': true, // As boolean value indicating whether or not the Downloads window should close automatically when downloads are completed.
270
- 'browser.download.manager.showAlertOnComplete': false, // A boolean value that indicates whether or not an alert should be shown when downloads complete.
271
- });
272
- }
273
-
274
- Object.assign(opts.desiredCapabilities, {
275
- acceptInsecureCerts: true,
276
- browserName: 'firefox',
277
- marionette: true,
278
- 'moz:firefoxOptions': {
279
- prefs: fireFoxPrefs,
280
- },
281
- }, lambdatestService.isLambdatestRun() ? { enableCustomTranslation: true } : {});
282
-
283
- if (browserOptions.disableCookiesSameSiteNoneRequiresSecure) {
284
- opts.desiredCapabilities['moz:firefoxOptions'].prefs['network.cookie.sameSite.noneRequiresSecure'] = false;
285
- }
286
-
287
- if (browserOptions.mode === CLI_MODE.EXTENSION) {
288
- if (browserOptions.ext) {
289
- opts.desiredCapabilities.testim_firefox_profile = browserOptions.ext;
290
- } else {
291
- const zipFileSuffix = browserOptions.canary ? '-master.zip' : '.zip';
292
- const filePath = path.join(process.cwd(), `testim-firefox-profile${zipFileSuffix}`);
293
- opts.desiredCapabilities.firefox_profile = readFileToBase64(filePath);
294
- }
295
- }
296
-
297
-
298
- // more interesting options
299
- // https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode#Debugging_headless_Firefox
300
- if (browserOptions.headless) {
301
- if (!opts.desiredCapabilities['moz:firefoxOptions'].args) {
302
- opts.desiredCapabilities['moz:firefoxOptions'].args = [];
303
- }
304
- opts.desiredCapabilities['moz:firefoxOptions'].args.push('-headless');
305
- }
306
-
307
- return opts;
308
- }
309
-
310
- function buildSaucelabs(browserOptions, testName, testRunConfig) {
311
- const { saucelabs } = browserOptions;
312
- if (saucelabs?.username && saucelabs.accessKey) {
313
- if (testRunConfig) {
314
- testRunConfig.sl.version = testRunConfig.browserValue === 'safari' ? testRunConfig.sl.safari_version : testRunConfig.sl.version;
315
- testRunConfig.sl.appiumVersion = saucelabs.appiumVersion || testRunConfig.sl.appiumVersion;
316
- return Object.assign({}, testRunConfig.sl, saucelabs, { name: testName });
317
- }
318
- return Object.assign({}, saucelabs, { name: testName });
319
- }
320
- return {};
321
- }
322
-
323
- function buildBrowserstack(browserOptions, testName, testRunConfig) {
324
- if (!_.isEmpty(browserOptions.browserstack)) {
325
- if (testRunConfig) {
326
- testRunConfig.bs.browser_version = testRunConfig.browserValue === 'safari' ? testRunConfig.bs.safari_version : testRunConfig.bs.browser_version;
327
- if (testRunConfig.browserValue === 'safari' && testRunConfig.bs.safari_version === '10') {
328
- Object.assign(testRunConfig.bs, { 'safari.options': { technologyPreview: true } });
329
- }
330
- return Object.assign({}, testRunConfig.bs, browserOptions.browserstack, { name: testName });
331
- }
332
- return Object.assign({}, browserOptions.browserstack, { name: testName });
333
- }
334
- return {};
335
- }
336
-
337
- function buildPerfecto(browserOptions) {
338
- if (browserOptions.perfecto) {
339
- return browserOptions.perfecto;
340
- }
341
- return {};
342
- }
343
-
344
- function buildExperitest(browserOptions, browser, sessionTimeoutSec) {
345
- if (browserOptions.experitestToken) {
346
- const isSafari = browser === 'safari';
347
- return {
348
- accessKey: browserOptions.experitestToken,
349
- browserVersion: 'latest',
350
- platformName: isSafari ? 'MAC' : 'WIN10',
351
- //Workaround to Experitest bug in take screenshot in Safari browser
352
- seleniumScreenshot: isSafari,
353
- newSessionWaitTimeout: sessionTimeoutSec,
354
- };
355
- }
356
-
357
- return {};
358
- }
359
-
360
- function buildHeaders(browserOptions, gridInfo = {}) {
361
- const { gridData = {}, gridUsername, gridPassword } = browserOptions;
362
- const username = gridUsername || gridData.user || gridInfo.user;
363
- const password = gridPassword || gridData.key || gridInfo.key;
364
-
365
- const headers = {};
366
- if (username && password) {
367
- headers.Authorization = utils.buildBasicHeader(username, password);
368
- }
369
-
370
- return headers;
371
- }
372
-
373
- function buildSeleniumOptions(browserOptions, testName, testRunConfig, gridInfo, customExtensionLocalLocation, executionId, testResultId, lambdatestService = null) {
374
- if (gridInfo.mode === 'local') {
375
- const extensions = [];
376
- const args = [...DEFAULT_CHROME_OPTIONS_ARGS];
377
- const binaryLocation = {};
378
-
379
- if (browserOptions.headless) {
380
- args.push('--headless');
381
- }
382
-
383
- if (browserOptions.silentDebuggerExtensionApi) {
384
- args.push('--silent-debugger-extension-api');
385
- }
386
-
387
- if (browserOptions.remoteDebuggingPort !== undefined) {
388
- args.push(`--remote-debugging-port=${browserOptions.remoteDebuggingPort}`);
389
- }
390
-
391
- if (browserOptions.chromeExtraArgs) {
392
- browserOptions.chromeExtraArgs.forEach(arg => args.push(`--${arg}`));
393
- }
394
-
395
- if (browserOptions.chromeBinaryLocation) {
396
- binaryLocation.binary = browserOptions.chromeBinaryLocation;
397
- }
398
-
399
- if (browserOptions.mode !== 'selenium') {
400
- setTestimExtension(browserOptions, extensions, args, null, lambdatestService);
401
- }
402
- setCustomExtension(customExtensionLocalLocation, extensions, lambdatestService);
403
-
404
- return {
405
- logLevel: LOG_LEVEL,
406
- desiredCapabilities: {
407
- chromeOptions: {
408
- args,
409
- extensions,
410
- ...binaryLocation,
411
- },
412
- browserName: 'chrome',
413
- },
414
- host: 'localhost',
415
- port: 9515, // default chromedriver port
416
- };
417
- }
418
-
419
- const { driverRequestTimeout, driverRequestRetries } = browserOptions;
420
- let opts = {
421
- host: gridInfo.host,
422
- port: gridInfo.port || 4444,
423
- path: gridInfo.path || '/wd/hub',
424
- protocol: gridInfo.protocol || 'http',
425
- logLevel: LOG_LEVEL,
426
- connectionRetryTimeout: driverRequestTimeout,
427
- connectionRetryCount: driverRequestRetries,
428
- getSessionTimeout: Math.max(lambdatestService.getSessionTimeout, browserOptions.getSessionTimeout),
429
- getSessionRetries: lambdatestService.getSessionRetries || browserOptions.getSessionRetries,
430
- deprecationWarnings: false,
431
- desiredCapabilities: {
432
- javascriptEnabled: true,
433
- locationContextEnabled: true,
434
- handlesAlerts: true,
435
- rotatable: true,
436
- acceptSslCerts: true,
437
- unexpectedAlertBehaviour: 'accept', // What the browser should do with an unhandled alert before throwing out the UnhandledAlertException - automatically click on accept
438
- nativeEvents: true,
439
- testName,
440
- },
441
- };
442
-
443
- const headers = buildHeaders(browserOptions, gridInfo);
444
- if (!_.isEmpty(headers)) {
445
- opts.headers = headers;
446
- }
447
-
448
- if (isDFGrid(gridInfo)) {
449
- browserOptions.oldCapabilities = false;
450
- browserOptions.w3cCapabilities = true;
451
- opts.desiredCapabilities = {
452
- unexpectedAlertBehaviour: 'accept',
453
- };
454
- }
455
-
456
- if (browserOptions.proxyForGrid) {
457
- opts.agent = new global.ProxyAgent(global.proxyUri);
458
- }
459
-
460
- if (browserOptions.disableNativeEvents) {
461
- opts.desiredCapabilities.nativeEvents = false;
462
- }
463
-
464
- if (gridInfo.user && gridInfo.key) {
465
- if (gridInfo.type === 'saucelabs') {
466
- browserOptions.saucelabs = browserOptions.saucelabs || {};
467
- browserOptions.saucelabs.username = browserOptions.saucelabs.username || gridInfo.user;
468
- browserOptions.saucelabs.accessKey = browserOptions.saucelabs.accessKey || gridInfo.key;
469
- }
470
-
471
- if (gridInfo.type === 'browserstack') {
472
- browserOptions.browserstack = browserOptions.browserstack || {};
473
- browserOptions.browserstack['browserstack.user'] = browserOptions.browserstack['browserstack.user'] || gridInfo.user;
474
- browserOptions.browserstack['browserstack.key'] = browserOptions.browserstack['browserstack.key'] || gridInfo.key;
475
- }
476
- }
477
-
478
- if (gridInfo.key && gridInfo.type === 'perfecto') {
479
- browserOptions.perfecto.securityToken = gridInfo.key;
480
- }
481
-
482
- const browserTimeoutSec = Number(browserOptions.browserTimeout / 1000);
483
- const browser = browserOptions.browser || testRunConfig?.browserValue;
484
-
485
- _.merge(
486
- opts.desiredCapabilities,
487
- buildSaucelabs(browserOptions, testName, testRunConfig),
488
- buildBrowserstack(browserOptions, testName, testRunConfig),
489
- buildPerfecto(browserOptions, testName, testRunConfig),
490
- buildExperitest(browserOptions, browser, browserTimeoutSec),
491
- lambdatestService?.getCapabilities(browserOptions, browser, executionId, testResultId, testName),
492
- );
493
-
494
- let predefinedTestimExtension = null;
495
- if (!browserOptions.ext && !browserOptions.extensionPath && gridInfo.host?.endsWith('.testim.io') && !browserOptions.canary && browserOptions.mode === CLI_MODE.EXTENSION) {
496
- if (browser === 'chrome') {
497
- predefinedTestimExtension = '/opt/testim-headless';
498
- } else if (browser === 'edge-chromium') {
499
- predefinedTestimExtension = 'C:/selenium/testim-headless';
500
- }
501
- }
502
-
503
- if (gridInfo.host?.endsWith('.testim.io') && browser === 'edge-chromium') {
504
- opts.desiredCapabilities.version = '83'; // Need to match GGR filter
505
- }
506
-
507
- switch (browser) {
508
- case 'chrome':
509
- case 'edge-chromium':
510
- opts = buildChromiumOptions(opts, browserOptions, testRunConfig, customExtensionLocalLocation, gridInfo, predefinedTestimExtension, lambdatestService);
511
- break;
512
- case 'firefox':
513
- opts = buildFirefoxOptions(opts, browserOptions, lambdatestService);
514
- break;
515
- case 'safari':
516
- case 'safari technology preview':
517
- opts = buildSafariOptions(opts, browser);
518
- break;
519
- default:
520
- break;
521
- }
522
-
523
- _.merge(opts.desiredCapabilities, browserOptions.seleniumCapsFileContent);
524
-
525
- try {
526
- /**
527
- * Targeted custom capabilities can be added to the desired capabilities object via the addCustomCapabilities FF.
528
- * No targeting: { selenium_version: '3.141.59' }
529
- * One level targeting (either grid provider, host, browser name or browser version): { "devicefarm": { selenium_version: '3.141.59' } }
530
- * Two level targeting: { "internet explorer": { "11": { selenium_version: '3.141.59' } } }
531
- */
532
- const hostToProvider = {
533
- 'hub.lambdatest.com': 'lambdatest',
534
- [featureFlags.flags.publicGridURL.getValue()]: 'testim',
535
- 'testgrid-devicefarm.us-west-2.amazonaws.com': 'devicefarm',
536
- };
537
- const byGrid = (capabilities) => capabilities[gridInfo.provider] || capabilities[opts.host] || capabilities[hostToProvider[opts.host]];
538
- const getTargetingGroup = capabilities =>
539
- byGrid(capabilities) ||
540
- capabilities[opts.desiredCapabilities?.browserName] ||
541
- capabilities[opts.desiredCapabilities?.version] ||
542
- capabilities ||
543
- {};
544
- const capabilities = JSON.parse(featureFlags.flags.addCustomCapabilities.getValue() || '{}');
545
- const customCapabilities = getTargetingGroup(getTargetingGroup(capabilities));
546
-
547
- if (Object.keys(customCapabilities).length) {
548
- logger.info(`Adding custom capabilities: ${JSON.stringify(customCapabilities)}`);
549
- Object.assign(opts.desiredCapabilities, customCapabilities);
550
- }
551
- } catch (error) {
552
- logger.error('Failed to load custom capabilities', {
553
- error,
554
- customCapabilities: featureFlags.flags.addCustomCapabilities.getValue(),
555
- });
556
- }
557
-
558
- if (isDFGrid(gridInfo) && opts.desiredCapabilities && !opts.capabilities) {
559
- convertToNewCapabilitiesFormat(opts.desiredCapabilities);
560
- opts.capabilities = { alwaysMatch: opts.desiredCapabilities, firstMatch: [{}] };
561
- delete opts.desiredCapabilities;
562
- }
563
-
564
- return opts;
565
- }
566
-
567
- //testRunConfig not in used for now
568
- function buildAppiumOptions({ projectType, gridInfo, testRunConfig, nativeApp, options, appPath, androidActivityWait }) {
569
- const { deviceModel, osVersion, deviceUdid } = options;
570
- const headspinSelector = {};
571
-
572
- if (!nativeApp && !appPath) {
573
- throw Error('missing mobile app!');
574
- }
575
- if (gridInfo.type !== gridTypes.TESTIM_HEADSPIN) {
576
- throw Error('unsupported grid was detected please make sure to select supported mobile grid');
577
- }
578
- const connection = {
579
- protocol: gridInfo.protocol || 'https',
580
- hostname: gridInfo.host,
581
- port: gridInfo.port,
582
- path: `/v0/${gridInfo.accessToken}/wd/hub`,
583
- logLevel: options.appiumLogLevel,
584
- // connectionRetryTimeout: 900000, -- not used for now
585
- };
586
- //TODO: check if more caps should be defined as default
587
- let appCaps = {
588
- 'headspin:capture': true,
589
- 'appium:autoAcceptAlerts': true,
590
- 'appium:noReset': true,
591
- };
592
- switch (projectType) {
593
- case 'ios':
594
- appCaps = {
595
- ...appCaps,
596
- platformName: 'iOS',
597
- 'appium:automationName': 'XCUITest',
598
- ...(nativeApp && { 'appium:bundleId': nativeApp.id }),
599
- ...(appPath && {
600
- 'appium:app': appPath,
601
- }),
602
- };
603
- break;
604
- case 'android':
605
- appCaps = {
606
- ...appCaps,
607
- platformName: 'Android',
608
- 'appium:automationName': 'UiAutomator2',
609
- 'appium:appWaitActivity': androidActivityWait,
610
- ...(nativeApp && {
611
- 'appium:appPackage': nativeApp.id || nativeApp.packageName,
612
- 'appium:appActivity': nativeApp.activity,
613
- }),
614
- ...(appPath && {
615
- 'appium:app': appPath,
616
- }),
617
- };
618
- break;
619
- default:
620
- throw Error(`unsupported mobile project ${projectType}`);
621
- }
622
- if (deviceModel) {
623
- headspinSelector.model = deviceModel;
624
- }
625
- if (osVersion) {
626
- headspinSelector.os_version = osVersion;
627
- }
628
- if (deviceUdid) {
629
- headspinSelector.device_id = deviceUdid;
630
- delete headspinSelector.model;
631
- delete headspinSelector.os_version;
632
- }
633
- if (!_.isEmpty(headspinSelector)) {
634
- appCaps['headspin:selector'] = headspinSelector;
635
- }
636
- return {
637
- ...connection,
638
- desiredCapabilities: appCaps,
639
- capabilities: appCaps,
640
- };
641
- }
642
-
643
- module.exports = {
644
- buildSeleniumOptions,
645
- buildAppiumOptions,
646
-
647
- };