@wdio/browserstack-service 8.45.0 → 8.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -11
- package/build/Percy/Percy-Handler.d.ts.map +1 -1
- package/build/Percy/Percy-Handler.js +4 -1
- package/build/Percy/Percy.d.ts.map +1 -1
- package/build/Percy/Percy.js +2 -1
- package/build/accessibility-handler.d.ts +9 -3
- package/build/accessibility-handler.d.ts.map +1 -1
- package/build/accessibility-handler.js +52 -11
- package/build/cleanup.js +3 -3
- package/build/cli/apiUtils.d.ts +14 -0
- package/build/cli/apiUtils.d.ts.map +1 -0
- package/build/cli/apiUtils.js +24 -0
- package/build/cli/cliLogger.d.ts +16 -0
- package/build/cli/cliLogger.d.ts.map +1 -0
- package/build/cli/cliLogger.js +70 -0
- package/build/cli/cliUtils.d.ts +46 -0
- package/build/cli/cliUtils.d.ts.map +1 -0
- package/build/cli/cliUtils.js +430 -0
- package/build/cli/eventDispatcher.d.ts +28 -0
- package/build/cli/eventDispatcher.d.ts.map +1 -0
- package/build/cli/eventDispatcher.js +48 -0
- package/build/cli/frameworks/automationFramework.d.ts +89 -0
- package/build/cli/frameworks/automationFramework.d.ts.map +1 -0
- package/build/cli/frameworks/automationFramework.js +131 -0
- package/build/cli/frameworks/constants/automationFrameworkConstants.d.ts +18 -0
- package/build/cli/frameworks/constants/automationFrameworkConstants.d.ts.map +1 -0
- package/build/cli/frameworks/constants/automationFrameworkConstants.js +17 -0
- package/build/cli/frameworks/constants/testFrameworkConstants.d.ts +43 -0
- package/build/cli/frameworks/constants/testFrameworkConstants.d.ts.map +1 -0
- package/build/cli/frameworks/constants/testFrameworkConstants.js +42 -0
- package/build/cli/frameworks/testFramework.d.ts +89 -0
- package/build/cli/frameworks/testFramework.d.ts.map +1 -0
- package/build/cli/frameworks/testFramework.js +125 -0
- package/build/cli/frameworks/wdioAutomationFramework.d.ts +28 -0
- package/build/cli/frameworks/wdioAutomationFramework.d.ts.map +1 -0
- package/build/cli/frameworks/wdioAutomationFramework.js +66 -0
- package/build/cli/frameworks/wdioMochaTestFramework.d.ts +82 -0
- package/build/cli/frameworks/wdioMochaTestFramework.d.ts.map +1 -0
- package/build/cli/frameworks/wdioMochaTestFramework.js +319 -0
- package/build/cli/grpcClient.d.ts +70 -0
- package/build/cli/grpcClient.d.ts.map +1 -0
- package/build/cli/grpcClient.js +419 -0
- package/build/cli/index.d.ts +148 -0
- package/build/cli/index.d.ts.map +1 -0
- package/build/cli/index.js +415 -0
- package/build/cli/instances/automationFrameworkInstance.d.ts +33 -0
- package/build/cli/instances/automationFrameworkInstance.d.ts.map +1 -0
- package/build/cli/instances/automationFrameworkInstance.js +44 -0
- package/build/cli/instances/testFrameworkInstance.d.ts +62 -0
- package/build/cli/instances/testFrameworkInstance.d.ts.map +1 -0
- package/build/cli/instances/testFrameworkInstance.js +96 -0
- package/build/cli/instances/trackedContext.d.ts +32 -0
- package/build/cli/instances/trackedContext.d.ts.map +1 -0
- package/build/cli/instances/trackedContext.js +47 -0
- package/build/cli/instances/trackedInstance.d.ts +40 -0
- package/build/cli/instances/trackedInstance.d.ts.map +1 -0
- package/build/cli/instances/trackedInstance.js +63 -0
- package/build/cli/modules/accessibilityModule.d.ts +33 -0
- package/build/cli/modules/accessibilityModule.d.ts.map +1 -0
- package/build/cli/modules/accessibilityModule.js +347 -0
- package/build/cli/modules/automateModule.d.ts +26 -0
- package/build/cli/modules/automateModule.d.ts.map +1 -0
- package/build/cli/modules/automateModule.js +222 -0
- package/build/cli/modules/baseModule.d.ts +33 -0
- package/build/cli/modules/baseModule.d.ts.map +1 -0
- package/build/cli/modules/baseModule.js +51 -0
- package/build/cli/modules/observabilityModule.d.ts +22 -0
- package/build/cli/modules/observabilityModule.d.ts.map +1 -0
- package/build/cli/modules/observabilityModule.js +45 -0
- package/build/cli/modules/percyModule.d.ts +19 -0
- package/build/cli/modules/percyModule.d.ts.map +1 -0
- package/build/cli/modules/percyModule.js +77 -0
- package/build/cli/modules/testHubModule.d.ts +30 -0
- package/build/cli/modules/testHubModule.d.ts.map +1 -0
- package/build/cli/modules/testHubModule.js +232 -0
- package/build/cli/modules/webdriverIOModule.d.ts +29 -0
- package/build/cli/modules/webdriverIOModule.d.ts.map +1 -0
- package/build/cli/modules/webdriverIOModule.js +128 -0
- package/build/cli/states/automationFrameworkState.d.ts +65 -0
- package/build/cli/states/automationFrameworkState.d.ts.map +1 -0
- package/build/cli/states/automationFrameworkState.js +61 -0
- package/build/cli/states/hookState.d.ts +45 -0
- package/build/cli/states/hookState.d.ts.map +1 -0
- package/build/cli/states/hookState.js +43 -0
- package/build/cli/states/testFrameworkState.d.ts +125 -0
- package/build/cli/states/testFrameworkState.d.ts.map +1 -0
- package/build/cli/states/testFrameworkState.js +115 -0
- package/build/constants.d.ts +13 -0
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +21 -1
- package/build/crash-reporter.d.ts.map +1 -1
- package/build/crash-reporter.js +4 -3
- package/build/exitHandler.d.ts.map +1 -1
- package/build/exitHandler.js +47 -5
- package/build/insights-handler.d.ts +8 -0
- package/build/insights-handler.d.ts.map +1 -1
- package/build/insights-handler.js +57 -1
- package/build/instrumentation/funnelInstrumentation.d.ts.map +1 -1
- package/build/instrumentation/funnelInstrumentation.js +5 -4
- package/build/instrumentation/performance/constants.d.ts +8 -0
- package/build/instrumentation/performance/constants.d.ts.map +1 -1
- package/build/instrumentation/performance/constants.js +9 -1
- package/build/instrumentation/performance/performance-tester.d.ts.map +1 -1
- package/build/instrumentation/performance/performance-tester.js +5 -3
- package/build/launcher.d.ts.map +1 -1
- package/build/launcher.js +94 -51
- package/build/request-handler.js +1 -1
- package/build/service.d.ts +3 -1
- package/build/service.d.ts.map +1 -1
- package/build/service.js +244 -69
- package/build/testOps/requestUtils.js +3 -2
- package/build/types.d.ts +36 -3
- package/build/types.d.ts.map +1 -1
- package/build/util.d.ts +13 -1
- package/build/util.d.ts.map +1 -1
- package/build/util.js +173 -27
- package/package.json +7 -4
- package/tsconfig.prod.tsbuildinfo +1 -1
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import util from 'node:util';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { CLIUtils } from './cliUtils.js';
|
|
4
|
+
import PerformanceTester from '../instrumentation/performance/performance-tester.js';
|
|
5
|
+
import { EVENTS as PerformanceEvents } from '../instrumentation/performance/constants.js';
|
|
6
|
+
import { BStackLogger } from './cliLogger.js';
|
|
7
|
+
import { GrpcClient } from './grpcClient.js';
|
|
8
|
+
import AutomateModule from './modules/automateModule.js';
|
|
9
|
+
import TestHubModule from './modules/testHubModule.js';
|
|
10
|
+
import { BROWSERSTACK_ACCESSIBILITY, BROWSERSTACK_OBSERVABILITY, BROWSERSTACK_TESTHUB_JWT, BROWSERSTACK_TESTHUB_UUID, CLI_STOP_TIMEOUT, TESTOPS_BUILD_COMPLETED_ENV, TESTOPS_SCREENSHOT_ENV } from '../constants.js';
|
|
11
|
+
import TestOpsConfig from '../testOps/testOpsConfig.js';
|
|
12
|
+
import WdioMochaTestFramework from './frameworks/wdioMochaTestFramework.js';
|
|
13
|
+
import WdioAutomationFramework from './frameworks/wdioAutomationFramework.js';
|
|
14
|
+
import WebdriverIOModule from './modules/webdriverIOModule.js';
|
|
15
|
+
import AccessibilityModule from './modules/accessibilityModule.js';
|
|
16
|
+
import { isTurboScale, processAccessibilityResponse, shouldAddServiceVersion } from '../util.js';
|
|
17
|
+
import ObservabilityModule from './modules/observabilityModule.js';
|
|
18
|
+
import PercyModule from './modules/percyModule.js';
|
|
19
|
+
import APIUtils from './apiUtils.js';
|
|
20
|
+
/**
|
|
21
|
+
* BrowserstackCLI - Singleton class for managing CLI operations
|
|
22
|
+
*
|
|
23
|
+
* This class uses the singleton pattern to ensure only one instance exists
|
|
24
|
+
* throughout the application lifecycle.
|
|
25
|
+
*/
|
|
26
|
+
export class BrowserstackCLI {
|
|
27
|
+
static #instance = null;
|
|
28
|
+
static enabled = false;
|
|
29
|
+
initialized;
|
|
30
|
+
config;
|
|
31
|
+
wdioConfig;
|
|
32
|
+
cliArgs;
|
|
33
|
+
browserstackConfig;
|
|
34
|
+
process = null;
|
|
35
|
+
isMainConnected = false;
|
|
36
|
+
isChildConnected = false;
|
|
37
|
+
binSessionId = null;
|
|
38
|
+
modules = {};
|
|
39
|
+
testFramework = null;
|
|
40
|
+
cliParams = null;
|
|
41
|
+
automationFramework = null;
|
|
42
|
+
SDK_CLI_BIN_PATH = null;
|
|
43
|
+
logger = BStackLogger;
|
|
44
|
+
options;
|
|
45
|
+
constructor() {
|
|
46
|
+
this.initialized = false;
|
|
47
|
+
this.config = {};
|
|
48
|
+
this.cliArgs = {};
|
|
49
|
+
this.browserstackConfig = {};
|
|
50
|
+
this.wdioConfig = '';
|
|
51
|
+
this.options = {};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get the singleton instance of BrowserstackCLI
|
|
55
|
+
* @returns {BrowserstackCLI} The singleton instance
|
|
56
|
+
*/
|
|
57
|
+
static getInstance() {
|
|
58
|
+
if (!BrowserstackCLI.#instance) {
|
|
59
|
+
BrowserstackCLI.#instance = new BrowserstackCLI();
|
|
60
|
+
}
|
|
61
|
+
return BrowserstackCLI.#instance;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Bootstrap the CLI
|
|
65
|
+
* Initializes and starts the CLI based on environment settings
|
|
66
|
+
* @returns {Promise<void>}
|
|
67
|
+
*/
|
|
68
|
+
async bootstrap(options, config, wdioConfig = '') {
|
|
69
|
+
PerformanceTester.start(PerformanceEvents.SDK_CLI_ON_BOOTSTRAP);
|
|
70
|
+
BrowserstackCLI.enabled = true;
|
|
71
|
+
this.options = options;
|
|
72
|
+
if (config) {
|
|
73
|
+
BrowserstackCLI.getInstance().setBrowserstackConfig(config);
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const binSessionId = process.env.BROWSERSTACK_CLI_BIN_SESSION_ID || null;
|
|
77
|
+
if (binSessionId) {
|
|
78
|
+
await this.startChild(binSessionId);
|
|
79
|
+
PerformanceTester.end(PerformanceEvents.SDK_CLI_ON_BOOTSTRAP);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
this.wdioConfig = wdioConfig;
|
|
83
|
+
await this.startMain();
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
const errorMessage = error instanceof Error ? error.stack || error.message : String(error);
|
|
87
|
+
this.logger.error(`bootstrap: failed to bootstrap ${errorMessage}`);
|
|
88
|
+
await this.stop();
|
|
89
|
+
PerformanceTester.end(PerformanceEvents.SDK_CLI_ON_BOOTSTRAP, false, util.format(error));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Start as a main process
|
|
94
|
+
* @returns {Promise<void>}
|
|
95
|
+
*/
|
|
96
|
+
async startMain() {
|
|
97
|
+
this.logger.info('startMain: Starting main process');
|
|
98
|
+
await this.start();
|
|
99
|
+
this.logger.debug('startMain: main-process started');
|
|
100
|
+
const response = await GrpcClient.getInstance().startBinSession(this.wdioConfig);
|
|
101
|
+
BStackLogger.debug(`start: startBinSession response=${JSON.stringify(response)}`);
|
|
102
|
+
this.loadModules(response);
|
|
103
|
+
this.isMainConnected = true;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Load modules
|
|
107
|
+
* @param {Object} startBinResponse - StartBinSession response
|
|
108
|
+
*/
|
|
109
|
+
loadModules(startBinResponse) {
|
|
110
|
+
// Defer imports to avoid circular dependencies
|
|
111
|
+
this.binSessionId = startBinResponse.binSessionId;
|
|
112
|
+
this.logger.info(`loadModules: binSessionId=${this.binSessionId}`);
|
|
113
|
+
this.setConfig(startBinResponse);
|
|
114
|
+
APIUtils.updateURLSForGRR(this.config.apis);
|
|
115
|
+
this.setupTestFramework();
|
|
116
|
+
this.setupAutomationFramework();
|
|
117
|
+
this.modules[WebdriverIOModule.MODULE_NAME] = new WebdriverIOModule();
|
|
118
|
+
this.modules[AutomateModule.MODULE_NAME] = new AutomateModule(this.browserstackConfig);
|
|
119
|
+
if (startBinResponse.testhub) {
|
|
120
|
+
process.env[TESTOPS_BUILD_COMPLETED_ENV] = 'true';
|
|
121
|
+
if (startBinResponse.testhub.jwt) {
|
|
122
|
+
process.env[BROWSERSTACK_TESTHUB_JWT] = startBinResponse.testhub.jwt;
|
|
123
|
+
}
|
|
124
|
+
if (startBinResponse.testhub.buildHashedId) {
|
|
125
|
+
process.env[BROWSERSTACK_TESTHUB_UUID] = startBinResponse.testhub.buildHashedId;
|
|
126
|
+
TestOpsConfig.getInstance().buildHashedId = startBinResponse.testhub.buildHashedId;
|
|
127
|
+
}
|
|
128
|
+
if (startBinResponse.observability?.success) {
|
|
129
|
+
process.env[BROWSERSTACK_OBSERVABILITY] = 'true';
|
|
130
|
+
if (startBinResponse.observability.options?.allowScreenshots) {
|
|
131
|
+
process.env[TESTOPS_SCREENSHOT_ENV] = startBinResponse.observability.options.allowScreenshots.toString();
|
|
132
|
+
}
|
|
133
|
+
this.modules[ObservabilityModule.MODULE_NAME] = new ObservabilityModule(startBinResponse.observability);
|
|
134
|
+
}
|
|
135
|
+
this.modules[TestHubModule.MODULE_NAME] = new TestHubModule(startBinResponse.testhub);
|
|
136
|
+
if (startBinResponse.accessibility?.success) {
|
|
137
|
+
process.env[BROWSERSTACK_ACCESSIBILITY] = 'true';
|
|
138
|
+
const options = this.options;
|
|
139
|
+
const isNonBstackA11y = isTurboScale(options) || !shouldAddServiceVersion(this.browserstackConfig, options.testObservability);
|
|
140
|
+
processAccessibilityResponse(startBinResponse, this.options);
|
|
141
|
+
this.modules[AccessibilityModule.MODULE_NAME] = new AccessibilityModule(startBinResponse.accessibility, isNonBstackA11y);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (startBinResponse.percy?.success) {
|
|
145
|
+
this.modules[PercyModule.MODULE_NAME] = new PercyModule(startBinResponse.percy);
|
|
146
|
+
}
|
|
147
|
+
this.configureModules();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Configure modules
|
|
151
|
+
* @returns {Promise<void>}
|
|
152
|
+
*/
|
|
153
|
+
async configureModules() {
|
|
154
|
+
this.logger.debug('configureModules: Configuring modules');
|
|
155
|
+
for (const moduleName in this.modules) {
|
|
156
|
+
const module = this.modules[moduleName];
|
|
157
|
+
const platformIndex = process.env.WDIO_WORKER_ID ? parseInt(process.env.WDIO_WORKER_ID.split('-')[0]) : 0;
|
|
158
|
+
this.logger.debug(`configureModules: Configuring module=${moduleName} platformIndex=${platformIndex}`);
|
|
159
|
+
await module.configure(this.binSessionId, platformIndex, GrpcClient.getInstance().client, this.config);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Start the CLI process and return a promise that resolves when it's ready
|
|
164
|
+
* @returns {Promise<void>}
|
|
165
|
+
* @throws {Error} If the process fails to start
|
|
166
|
+
*/
|
|
167
|
+
async start() {
|
|
168
|
+
PerformanceTester.start(PerformanceEvents.SDK_CLI_START);
|
|
169
|
+
if (CLIUtils.isDevelopmentEnv()) {
|
|
170
|
+
this.loadCliParams(CLIUtils.getCLIParamsForDevEnv());
|
|
171
|
+
PerformanceTester.end(PerformanceEvents.SDK_CLI_START);
|
|
172
|
+
return Promise.resolve();
|
|
173
|
+
}
|
|
174
|
+
// Skip if process is already running
|
|
175
|
+
if (this.process && this.process.connected) {
|
|
176
|
+
PerformanceTester.end(PerformanceEvents.SDK_CLI_START);
|
|
177
|
+
return Promise.resolve();
|
|
178
|
+
}
|
|
179
|
+
const SDK_CLI_BIN_PATH = await this.getCliBinPath();
|
|
180
|
+
const cmd = [SDK_CLI_BIN_PATH, 'sdk'];
|
|
181
|
+
this.logger.debug(`spawning command='${cmd}'`);
|
|
182
|
+
// Create a child process
|
|
183
|
+
this.process = spawn(cmd[0], cmd.slice(1), {
|
|
184
|
+
env: process.env
|
|
185
|
+
});
|
|
186
|
+
// Check if process started successfully
|
|
187
|
+
if (!this.process.pid) {
|
|
188
|
+
throw new Error('failed to start CLI, no PID found');
|
|
189
|
+
}
|
|
190
|
+
// Return a promise that resolves when CLI is ready
|
|
191
|
+
return new Promise((resolve, reject) => {
|
|
192
|
+
const cliOut = {};
|
|
193
|
+
this.process.stdout.on('data', (data) => {
|
|
194
|
+
const lines = data.toString().trim().split('\n');
|
|
195
|
+
for (const line of lines) {
|
|
196
|
+
// Parse key=value pairs
|
|
197
|
+
if (/^(id|listen|port)=.*$/.test(line)) {
|
|
198
|
+
const [key, value] = line.split('=', 2);
|
|
199
|
+
if (value !== undefined) {
|
|
200
|
+
cliOut[key] = value;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Check for ready message
|
|
204
|
+
if (line.toLowerCase().includes('ready')) {
|
|
205
|
+
this.loadCliParams(cliOut);
|
|
206
|
+
PerformanceTester.end(PerformanceEvents.SDK_CLI_START);
|
|
207
|
+
resolve();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
this.process.stderr.on('data', (data) => {
|
|
213
|
+
this.logger.error(`CLI stderr: ${data.toString().trim()}`);
|
|
214
|
+
});
|
|
215
|
+
this.process.on('error', (err) => {
|
|
216
|
+
cliOut.error = `Error in start: ${err.message}`;
|
|
217
|
+
PerformanceTester.end(PerformanceEvents.SDK_CLI_START, false, err);
|
|
218
|
+
reject(new Error(`Failed to start CLI process: ${err.message}`));
|
|
219
|
+
});
|
|
220
|
+
this.process.on('close', (code) => {
|
|
221
|
+
if (code !== 0) {
|
|
222
|
+
reject(new Error(`CLI process exited with code ${code}`));
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Stop the CLI
|
|
229
|
+
* @returns {Promise<void>}
|
|
230
|
+
*/
|
|
231
|
+
async stop() {
|
|
232
|
+
PerformanceTester.start(PerformanceEvents.SDK_CLI_ON_STOP);
|
|
233
|
+
this.logger.debug('stop: CLI stop triggered');
|
|
234
|
+
try {
|
|
235
|
+
if (this.isMainConnected) {
|
|
236
|
+
const response = await GrpcClient.getInstance().stopBinSession();
|
|
237
|
+
BStackLogger.debug(`stop: stopBinSession response=${JSON.stringify(response)}`);
|
|
238
|
+
}
|
|
239
|
+
await this.unConfigureModules();
|
|
240
|
+
if (this.process && this.process.pid) {
|
|
241
|
+
this.logger.debug('stop: shutting down CLI');
|
|
242
|
+
this.process.kill();
|
|
243
|
+
// Wait for process to fully exit
|
|
244
|
+
await new Promise((resolve) => {
|
|
245
|
+
let exited = false;
|
|
246
|
+
// Listen for exit event
|
|
247
|
+
this.process.on('exit', () => {
|
|
248
|
+
this.logger.debug('stop: CLI process exited');
|
|
249
|
+
exited = true;
|
|
250
|
+
PerformanceTester.end(PerformanceEvents.SDK_CLI_ON_STOP);
|
|
251
|
+
resolve();
|
|
252
|
+
});
|
|
253
|
+
// Set a timeout in case process doesn't exit cleanly
|
|
254
|
+
setTimeout(() => {
|
|
255
|
+
if (!exited) {
|
|
256
|
+
this.logger.warn('stop: process exit timeout, forcing kill');
|
|
257
|
+
this.process.kill('SIGKILL');
|
|
258
|
+
PerformanceTester.end(PerformanceEvents.SDK_CLI_ON_STOP);
|
|
259
|
+
resolve();
|
|
260
|
+
}
|
|
261
|
+
}, CLI_STOP_TIMEOUT);
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
PerformanceTester.end(PerformanceEvents.SDK_CLI_ON_STOP, false, util.format(error));
|
|
267
|
+
const errorMessage = error instanceof Error ? error.stack || error.message : String(error);
|
|
268
|
+
this.logger.error(`stop: error in stop session exception=${errorMessage}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Unconfigure modules
|
|
273
|
+
* @returns {Promise<void>}
|
|
274
|
+
* @private
|
|
275
|
+
*/
|
|
276
|
+
async unConfigureModules() {
|
|
277
|
+
this.logger.debug('Unconfiguring modules');
|
|
278
|
+
for (const moduleName in this.modules) {
|
|
279
|
+
const module = this.modules[moduleName];
|
|
280
|
+
const platformIndex = process.env.WDIO_WORKER_ID ? parseInt(process.env.WDIO_WORKER_ID.split('-')[0]) : 0;
|
|
281
|
+
await module.configure(null, platformIndex, GrpcClient.getInstance().client);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Load CLI parameters from the output
|
|
286
|
+
* @param {Object} params - Parameters parsed from CLI output
|
|
287
|
+
* @private
|
|
288
|
+
*/
|
|
289
|
+
loadCliParams(params) {
|
|
290
|
+
this.logger.debug(`CLI params loaded: ${JSON.stringify(params)}`);
|
|
291
|
+
this.cliParams = params;
|
|
292
|
+
GrpcClient.getInstance().init(params);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Start as a child process with the specified binSessionId
|
|
296
|
+
* @param {string} binSessionId - session ID to connect to the CLI process
|
|
297
|
+
* @returns {Promise<void>}
|
|
298
|
+
*/
|
|
299
|
+
async startChild(binSessionId) {
|
|
300
|
+
PerformanceTester.start(PerformanceEvents.SDK_CONNECT_BIN_SESSION);
|
|
301
|
+
try {
|
|
302
|
+
this.logger.info(`Starting as child process with session ID: ${binSessionId}`);
|
|
303
|
+
GrpcClient.getInstance().connect();
|
|
304
|
+
const response = await GrpcClient.getInstance().connectBinSession();
|
|
305
|
+
this.logger.info(`Connected to bin session: ${JSON.stringify(response)}`);
|
|
306
|
+
this.loadModules(response);
|
|
307
|
+
this.isChildConnected = true;
|
|
308
|
+
PerformanceTester.end(PerformanceEvents.SDK_CONNECT_BIN_SESSION);
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
PerformanceTester.end(PerformanceEvents.SDK_CONNECT_BIN_SESSION, false, util.format(error));
|
|
312
|
+
this.logger.error(`Failed to start as child process: ${util.format(error)}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Check if the CLI is running
|
|
317
|
+
* @returns {boolean} True if the CLI is running
|
|
318
|
+
*/
|
|
319
|
+
isRunning() {
|
|
320
|
+
return (
|
|
321
|
+
// is Dev mode
|
|
322
|
+
CLIUtils.isDevelopmentEnv() ||
|
|
323
|
+
// Main process connection check
|
|
324
|
+
(this.isMainConnected && this.process !== null && this.process.exitCode === null && GrpcClient.getInstance().getClient() !== null && GrpcClient.getInstance().getChannel().getConnectivityState(false) !== 4) ||
|
|
325
|
+
// Child process connection check
|
|
326
|
+
(this.isChildConnected && GrpcClient.getInstance().getChannel() !== null && GrpcClient.getInstance().getChannel().getConnectivityState(false) !== 4));
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Get the Browserstack configuration
|
|
330
|
+
* @returns {Object} The Browserstack configuration
|
|
331
|
+
*/
|
|
332
|
+
getBrowserstackConfig() {
|
|
333
|
+
return this.browserstackConfig;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Set the Browserstack configuration
|
|
337
|
+
* @param {Object}
|
|
338
|
+
* @returns {void}
|
|
339
|
+
*/
|
|
340
|
+
setBrowserstackConfig(browserstackConfig) {
|
|
341
|
+
this.browserstackConfig = browserstackConfig;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Get the CLI binary path
|
|
345
|
+
* @returns {string} The CLI binary path
|
|
346
|
+
*/
|
|
347
|
+
async getCliBinPath() {
|
|
348
|
+
if (!this.SDK_CLI_BIN_PATH) {
|
|
349
|
+
this.SDK_CLI_BIN_PATH = await CLIUtils.setupCliPath(this.browserstackConfig);
|
|
350
|
+
}
|
|
351
|
+
return this.SDK_CLI_BIN_PATH || ''; // TODO: Type hack
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Check if the CLI is enabled
|
|
355
|
+
* @returns {boolean} True if the CLI is enabled
|
|
356
|
+
*/
|
|
357
|
+
isCliEnabled() {
|
|
358
|
+
return BrowserstackCLI.enabled;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Get the configuration
|
|
362
|
+
* @returns {Object} The configuration
|
|
363
|
+
*/
|
|
364
|
+
getConfig() {
|
|
365
|
+
return this.config;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Set the configuration
|
|
369
|
+
* @param {Object}
|
|
370
|
+
* @returns {void}
|
|
371
|
+
*/
|
|
372
|
+
setConfig(response) {
|
|
373
|
+
try {
|
|
374
|
+
this.config = JSON.parse(response.config);
|
|
375
|
+
this.logger.debug(`loadModules: config=${JSON.stringify(this.config)}`);
|
|
376
|
+
}
|
|
377
|
+
catch (error) {
|
|
378
|
+
this.logger.error(`setConfig: error=${util.format(error)}`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Setup the test framework
|
|
383
|
+
* @returns {void}
|
|
384
|
+
*/
|
|
385
|
+
setupTestFramework() {
|
|
386
|
+
const testFrameworkDetail = CLIUtils.getTestFrameworkDetail();
|
|
387
|
+
if (testFrameworkDetail.name.toLowerCase() === 'webdriverio-mocha') {
|
|
388
|
+
this.testFramework = new WdioMochaTestFramework([testFrameworkDetail.name], testFrameworkDetail.version, this.binSessionId);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Setup the automation framework
|
|
393
|
+
* @returns {void}
|
|
394
|
+
*/
|
|
395
|
+
setupAutomationFramework() {
|
|
396
|
+
const automationFrameworkDetail = CLIUtils.getAutomationFrameworkDetail();
|
|
397
|
+
if (automationFrameworkDetail.name.toLowerCase() === 'webdriverio') {
|
|
398
|
+
this.automationFramework = new WdioAutomationFramework(automationFrameworkDetail.name, automationFrameworkDetail.version);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Get the test framework
|
|
403
|
+
* @returns {Object} The test framework
|
|
404
|
+
*/
|
|
405
|
+
getTestFramework() {
|
|
406
|
+
return this.testFramework;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Get the automation framework
|
|
410
|
+
* @returns {Object} The automation framework
|
|
411
|
+
*/
|
|
412
|
+
getAutomationFramework() {
|
|
413
|
+
return this.automationFramework;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type TrackedContext from './trackedContext.js';
|
|
2
|
+
import TrackedInstance from './trackedInstance.js';
|
|
3
|
+
/**
|
|
4
|
+
* Class representing an automation framework instance
|
|
5
|
+
* @extends TrackedInstance
|
|
6
|
+
*/
|
|
7
|
+
export default class AutomationFrameworkInstance extends TrackedInstance {
|
|
8
|
+
frameworkName: string;
|
|
9
|
+
frameworkVersion: string;
|
|
10
|
+
state: State;
|
|
11
|
+
constructor(context: TrackedContext, frameworkName: string, frameworkVersion: string, state: State);
|
|
12
|
+
/**
|
|
13
|
+
* Get the framework name
|
|
14
|
+
* @returns {string} The name of the automation framework
|
|
15
|
+
*/
|
|
16
|
+
getFrameworkName(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Get the framework version
|
|
19
|
+
* @returns {string} The version of the automation framework
|
|
20
|
+
*/
|
|
21
|
+
getFrameworkVersion(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Get the current state
|
|
24
|
+
* @returns {AutomationFrameworkState} The current state of the automation framework
|
|
25
|
+
*/
|
|
26
|
+
getState(): State;
|
|
27
|
+
/**
|
|
28
|
+
* Set the current state
|
|
29
|
+
* @param {AutomationFrameworkState} state - The new state to set
|
|
30
|
+
*/
|
|
31
|
+
setState(state: State): void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=automationFrameworkInstance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"automationFrameworkInstance.d.ts","sourceRoot":"","sources":["../../../src/cli/instances/automationFrameworkInstance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAErD,OAAO,eAAe,MAAM,sBAAsB,CAAA;AAElD;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,2BAA4B,SAAQ,eAAe;IACpE,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;gBAEA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;IAOlG;;;KAGC;IACD,gBAAgB;IAIhB;;;KAGC;IACD,mBAAmB;IAInB;;;KAGC;IACD,QAAQ;IAIR;;;KAGC;IACD,QAAQ,CAAC,KAAK,EAAE,KAAK;CAGxB"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import TrackedInstance from './trackedInstance.js';
|
|
2
|
+
/**
|
|
3
|
+
* Class representing an automation framework instance
|
|
4
|
+
* @extends TrackedInstance
|
|
5
|
+
*/
|
|
6
|
+
export default class AutomationFrameworkInstance extends TrackedInstance {
|
|
7
|
+
frameworkName;
|
|
8
|
+
frameworkVersion;
|
|
9
|
+
state;
|
|
10
|
+
constructor(context, frameworkName, frameworkVersion, state) {
|
|
11
|
+
super(context);
|
|
12
|
+
this.frameworkName = frameworkName;
|
|
13
|
+
this.frameworkVersion = frameworkVersion;
|
|
14
|
+
this.state = state;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get the framework name
|
|
18
|
+
* @returns {string} The name of the automation framework
|
|
19
|
+
*/
|
|
20
|
+
getFrameworkName() {
|
|
21
|
+
return this.frameworkName;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get the framework version
|
|
25
|
+
* @returns {string} The version of the automation framework
|
|
26
|
+
*/
|
|
27
|
+
getFrameworkVersion() {
|
|
28
|
+
return this.frameworkVersion;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get the current state
|
|
32
|
+
* @returns {AutomationFrameworkState} The current state of the automation framework
|
|
33
|
+
*/
|
|
34
|
+
getState() {
|
|
35
|
+
return this.state;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Set the current state
|
|
39
|
+
* @param {AutomationFrameworkState} state - The new state to set
|
|
40
|
+
*/
|
|
41
|
+
setState(state) {
|
|
42
|
+
this.state = state;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import TrackedInstance from './trackedInstance.js';
|
|
2
|
+
import type TrackedContext from './trackedContext.js';
|
|
3
|
+
export default class TestFrameworkInstance extends TrackedInstance {
|
|
4
|
+
#private;
|
|
5
|
+
testFrameworks: Array<string>;
|
|
6
|
+
testFrameworksVersions: Record<string, string>;
|
|
7
|
+
/**
|
|
8
|
+
* create TestFrameworkInstance
|
|
9
|
+
* @param {TrackedContext} context
|
|
10
|
+
* @param {Array} testFrameworks
|
|
11
|
+
* @param {Map} testFrameworksVersions
|
|
12
|
+
* @param {TestFrameworkState} testFrameworkState
|
|
13
|
+
* @param {HookState} hookState
|
|
14
|
+
*/
|
|
15
|
+
constructor(context: TrackedContext, testFrameworks: Array<string>, testFrameworksVersions: Record<string, string>, testFrameworkState: State, hookState: State);
|
|
16
|
+
/**
|
|
17
|
+
* get CurrentTestState of instance
|
|
18
|
+
* @returns {*} - returns TestFramework State
|
|
19
|
+
*/
|
|
20
|
+
getCurrentTestState(): State;
|
|
21
|
+
/**
|
|
22
|
+
* set CurrentTestState of instance
|
|
23
|
+
* @param {TestFrameworkState} currentTestState - Set Current TestFramework State
|
|
24
|
+
*/
|
|
25
|
+
setCurrentTestState(currentTestState: State): void;
|
|
26
|
+
/**
|
|
27
|
+
* get CurrentHookState of instance
|
|
28
|
+
* @returns {HookState} - return current hook state.
|
|
29
|
+
*/
|
|
30
|
+
getCurrentHookState(): State;
|
|
31
|
+
/**
|
|
32
|
+
* set CurrentHookState of instance
|
|
33
|
+
* @param {HookState} currentHookState - set current hook state.
|
|
34
|
+
*/
|
|
35
|
+
setCurrentHookState(currentHookState: State): void;
|
|
36
|
+
/**
|
|
37
|
+
* get LastTestState of instance
|
|
38
|
+
* @returns {TestFrameworkState} - return last test framework state
|
|
39
|
+
*/
|
|
40
|
+
getLastTestState(): State;
|
|
41
|
+
/**
|
|
42
|
+
* set LastTestState of instance
|
|
43
|
+
* @param {TestFrameworkState} lastTestState - set last test framework state
|
|
44
|
+
*/
|
|
45
|
+
setLastTestState(lastTestState: State): void;
|
|
46
|
+
/**
|
|
47
|
+
* get LastHookState of instance
|
|
48
|
+
* @returns {HookState} get last hook state
|
|
49
|
+
*/
|
|
50
|
+
getLastHookState(): State;
|
|
51
|
+
/**
|
|
52
|
+
* set LastHookState of instance
|
|
53
|
+
* @param {HookState} lastHookState - returns late hook state
|
|
54
|
+
*/
|
|
55
|
+
setLastHookState(lastHookState: State): void;
|
|
56
|
+
/**
|
|
57
|
+
* get CreatedAt of instance
|
|
58
|
+
* @returns {string} - return created time
|
|
59
|
+
*/
|
|
60
|
+
getCreatedAt(): string;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=testFrameworkInstance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testFrameworkInstance.d.ts","sourceRoot":"","sources":["../../../src/cli/instances/testFrameworkInstance.ts"],"names":[],"mappings":"AAGA,OAAO,eAAe,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAIrD,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,eAAe;;IAC9D,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC7B,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAO9C;;;;;;;KAOC;gBACW,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK;IAW/J;;;KAGC;IACD,mBAAmB;IAInB;;;KAGC;IACD,mBAAmB,CAAC,gBAAgB,EAAE,KAAK;IAK3C;;;KAGC;IACD,mBAAmB;IAInB;;;KAGC;IACD,mBAAmB,CAAC,gBAAgB,EAAE,KAAK;IAK3C;;;KAGC;IACD,gBAAgB;IAIhB;;;KAGC;IACD,gBAAgB,CAAC,aAAa,EAAE,KAAK;IAIrC;;;KAGC;IACD,gBAAgB;IAIhB;;;KAGC;IACD,gBAAgB,CAAC,aAAa,EAAE,KAAK;IAIrC;;;KAGC;IACD,YAAY;CAIf"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { HookState } from '../states/hookState.js';
|
|
2
|
+
import { TestFrameworkState } from '../states/testFrameworkState.js';
|
|
3
|
+
import TrackedInstance from './trackedInstance.js';
|
|
4
|
+
const now = new Date();
|
|
5
|
+
export default class TestFrameworkInstance extends TrackedInstance {
|
|
6
|
+
testFrameworks;
|
|
7
|
+
testFrameworksVersions;
|
|
8
|
+
#currentTestState;
|
|
9
|
+
#currentHookState;
|
|
10
|
+
#lastTestState;
|
|
11
|
+
#lastHookState;
|
|
12
|
+
#createdAt;
|
|
13
|
+
/**
|
|
14
|
+
* create TestFrameworkInstance
|
|
15
|
+
* @param {TrackedContext} context
|
|
16
|
+
* @param {Array} testFrameworks
|
|
17
|
+
* @param {Map} testFrameworksVersions
|
|
18
|
+
* @param {TestFrameworkState} testFrameworkState
|
|
19
|
+
* @param {HookState} hookState
|
|
20
|
+
*/
|
|
21
|
+
constructor(context, testFrameworks, testFrameworksVersions, testFrameworkState, hookState) {
|
|
22
|
+
super(context);
|
|
23
|
+
this.testFrameworks = testFrameworks;
|
|
24
|
+
this.testFrameworksVersions = testFrameworksVersions;
|
|
25
|
+
this.#currentTestState = testFrameworkState;
|
|
26
|
+
this.#currentHookState = hookState;
|
|
27
|
+
this.#lastTestState = TestFrameworkState.NONE;
|
|
28
|
+
this.#lastHookState = HookState.NONE;
|
|
29
|
+
this.#createdAt = now.toLocaleString();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* get CurrentTestState of instance
|
|
33
|
+
* @returns {*} - returns TestFramework State
|
|
34
|
+
*/
|
|
35
|
+
getCurrentTestState() {
|
|
36
|
+
return this.#currentTestState;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* set CurrentTestState of instance
|
|
40
|
+
* @param {TestFrameworkState} currentTestState - Set Current TestFramework State
|
|
41
|
+
*/
|
|
42
|
+
setCurrentTestState(currentTestState) {
|
|
43
|
+
this.setLastTestState(this.#currentTestState);
|
|
44
|
+
this.#currentTestState = currentTestState;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* get CurrentHookState of instance
|
|
48
|
+
* @returns {HookState} - return current hook state.
|
|
49
|
+
*/
|
|
50
|
+
getCurrentHookState() {
|
|
51
|
+
return this.#currentHookState;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* set CurrentHookState of instance
|
|
55
|
+
* @param {HookState} currentHookState - set current hook state.
|
|
56
|
+
*/
|
|
57
|
+
setCurrentHookState(currentHookState) {
|
|
58
|
+
this.setLastHookState(this.#currentHookState);
|
|
59
|
+
this.#currentHookState = currentHookState;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* get LastTestState of instance
|
|
63
|
+
* @returns {TestFrameworkState} - return last test framework state
|
|
64
|
+
*/
|
|
65
|
+
getLastTestState() {
|
|
66
|
+
return this.#lastTestState;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* set LastTestState of instance
|
|
70
|
+
* @param {TestFrameworkState} lastTestState - set last test framework state
|
|
71
|
+
*/
|
|
72
|
+
setLastTestState(lastTestState) {
|
|
73
|
+
this.#lastTestState = lastTestState;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* get LastHookState of instance
|
|
77
|
+
* @returns {HookState} get last hook state
|
|
78
|
+
*/
|
|
79
|
+
getLastHookState() {
|
|
80
|
+
return this.#lastHookState;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* set LastHookState of instance
|
|
84
|
+
* @param {HookState} lastHookState - returns late hook state
|
|
85
|
+
*/
|
|
86
|
+
setLastHookState(lastHookState) {
|
|
87
|
+
this.#lastHookState = lastHookState;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* get CreatedAt of instance
|
|
91
|
+
* @returns {string} - return created time
|
|
92
|
+
*/
|
|
93
|
+
getCreatedAt() {
|
|
94
|
+
return this.#createdAt;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export default class TrackedContext {
|
|
2
|
+
#private;
|
|
3
|
+
/**
|
|
4
|
+
* Create TrackedContext
|
|
5
|
+
* @param {number} string - string Id for context - VERIFY
|
|
6
|
+
* @param {number} threadId- Integer Thread Id for context
|
|
7
|
+
* @param {number} processId - Integer Process Id for context
|
|
8
|
+
* @param {string} type
|
|
9
|
+
*/
|
|
10
|
+
constructor(id: string, threadId: number, processId: number, type: string);
|
|
11
|
+
/**
|
|
12
|
+
* get TrackedContext thread id
|
|
13
|
+
* @returns {number} - return thread id of context
|
|
14
|
+
*/
|
|
15
|
+
getThreadId(): number;
|
|
16
|
+
/**
|
|
17
|
+
* get TrackedContext process id
|
|
18
|
+
* @returns {number} - return process id of context
|
|
19
|
+
*/
|
|
20
|
+
getProcessId(): number;
|
|
21
|
+
/**
|
|
22
|
+
* get TrackedContext id
|
|
23
|
+
* @returns {string} - returns context id
|
|
24
|
+
*/
|
|
25
|
+
getId(): string;
|
|
26
|
+
/**
|
|
27
|
+
* get TrackedContext type
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
getType(): string;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=trackedContext.d.ts.map
|