@wdio/browserstack-service 9.7.3 → 9.9.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/build/index.js CHANGED
@@ -1,16 +1,24 @@
1
1
  var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
2
3
  var __export = (target, all) => {
3
4
  for (var name in all)
4
5
  __defProp(target, name, { get: all[name], enumerable: true });
5
6
  };
7
+ var __decorateClass = (decorators, target, key, kind) => {
8
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
9
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
10
+ if (decorator = decorators[i])
11
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
12
+ if (kind && result) __defProp(target, key, result);
13
+ return result;
14
+ };
6
15
 
7
16
  // src/launcher.ts
8
- import { v4 as uuidv4 } from "uuid";
9
17
  import fs11 from "node:fs";
10
18
  import { readFile } from "node:fs/promises";
11
- import path11 from "node:path";
19
+ import path12 from "node:path";
12
20
  import { promisify as promisify2, format as format3 } from "node:util";
13
- import { performance as performance2, PerformanceObserver as PerformanceObserver2 } from "node:perf_hooks";
21
+ import { performance as performance3, PerformanceObserver as PerformanceObserver2 } from "node:perf_hooks";
14
22
  import os5 from "node:os";
15
23
  import { SevereServiceError } from "webdriverio";
16
24
  import * as BrowserstackLocalLauncher from "browserstack-local";
@@ -18,7 +26,7 @@ import * as BrowserstackLocalLauncher from "browserstack-local";
18
26
  // package.json
19
27
  var package_default = {
20
28
  name: "@wdio/browserstack-service",
21
- version: "9.7.2",
29
+ version: "9.8.0",
22
30
  description: "WebdriverIO service for better Browserstack integration",
23
31
  author: "Adam Bjerstedt <abjerstedt@gmail.com>",
24
32
  homepage: "https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-browserstack-service",
@@ -143,6 +151,7 @@ var LOG_KIND_USAGE_MAP = {
143
151
  "HTTP": "http"
144
152
  };
145
153
  var FUNNEL_INSTRUMENTATION_URL = "https://api.browserstack.com/sdk/v1/event";
154
+ var EDS_URL = "https://eds.browserstack.com";
146
155
  var SUPPORTED_BROWSERS_FOR_AI = ["chrome", "microsoftedge", "firefox"];
147
156
  var TCG_URL = "https://tcg.browserstack.com";
148
157
  var TCG_INFO = {
@@ -165,21 +174,22 @@ var MAX_GIT_META_DATA_SIZE_IN_BYTES = 64 * 1024;
165
174
  var GIT_META_DATA_TRUNCATED = "...[TRUNCATED]";
166
175
 
167
176
  // src/bstackLogger.ts
168
- import path3 from "node:path";
177
+ import path4 from "node:path";
169
178
  import fs4 from "node:fs";
170
179
  import chalk from "chalk";
171
180
  import logger from "@wdio/logger";
172
181
 
173
182
  // src/util.ts
174
- import { hostname, platform, type, version, arch } from "node:os";
183
+ import { hostname as hostname2, platform as platform2, type as type2, version as version2, arch as arch2 } from "node:os";
175
184
  import fs3 from "node:fs";
176
185
  import zlib from "node:zlib";
177
186
  import { format, promisify } from "node:util";
178
- import path2 from "node:path";
179
- import util from "node:util";
187
+ import path3 from "node:path";
188
+ import util2 from "node:util";
180
189
  import gitRepoInfo from "git-repo-info";
181
190
  import gitconfig from "gitconfiglocal";
182
191
  import { FormData as FormData2 } from "formdata-node";
192
+ import { performance as performance2 } from "node:perf_hooks";
183
193
 
184
194
  // src/logPatcher.ts
185
195
  import Transport from "winston-transport";
@@ -222,33 +232,81 @@ var logPatcher = class extends Transport {
222
232
  };
223
233
  var logPatcher_default = logPatcher;
224
234
 
225
- // src/performance-tester.ts
235
+ // src/instrumentation/performance/performance-tester.ts
226
236
  import { createObjectCsvWriter } from "csv-writer";
227
237
  import fs from "node:fs";
238
+ import fsPromise from "node:fs/promises";
228
239
  import { performance, PerformanceObserver } from "node:perf_hooks";
229
- var PerformanceTester = class {
240
+ import util from "node:util";
241
+ import worker from "node:worker_threads";
242
+ import path from "node:path";
243
+ import { arch, hostname, platform, type, version } from "node:os";
244
+
245
+ // src/fetchWrapper.ts
246
+ var ResponseError = class extends Error {
247
+ response;
248
+ constructor(message, res) {
249
+ super(message);
250
+ this.response = res;
251
+ }
252
+ };
253
+ async function fetchWrap(input, init) {
254
+ const res = await fetch(input, init);
255
+ if (!res.ok) {
256
+ throw new ResponseError(`Error response from server ${res.status}: ${await res.text()}`, res);
257
+ }
258
+ return res;
259
+ }
260
+
261
+ // src/instrumentation/performance/performance-tester.ts
262
+ var PerformanceTester = class _PerformanceTester {
230
263
  static _observer;
231
264
  static _csvWriter;
232
265
  static _events = [];
266
+ static _measuredEvents = [];
233
267
  static started = false;
268
+ static details = {};
269
+ static eventsMap = {};
270
+ static browser;
271
+ static scenarioThatRan;
272
+ static jsonReportDirName = "performance-report";
273
+ static jsonReportDirPath = path.join(process.cwd(), "logs", this.jsonReportDirName);
274
+ static jsonReportFileName = `${this.jsonReportDirPath}/performance-report-${_PerformanceTester.getProcessId()}.json`;
234
275
  static startMonitoring(csvName = "performance-report.csv") {
276
+ if (!fs.existsSync(this.jsonReportDirPath)) {
277
+ fs.mkdirSync(this.jsonReportDirPath, { recursive: true });
278
+ }
235
279
  this._observer = new PerformanceObserver((list) => {
236
- list.getEntries().forEach((entry) => {
237
- this._events.push(entry);
238
- });
280
+ list.getEntries().filter((entry) => entry.entryType === "measure").forEach(
281
+ (entry) => {
282
+ let finalEntry = entry;
283
+ finalEntry = entry.toJSON();
284
+ if (this.details[entry.name]) {
285
+ finalEntry = Object.assign(finalEntry, this.details[entry.name]);
286
+ }
287
+ delete this.details[entry.name];
288
+ this._measuredEvents.push(finalEntry);
289
+ }
290
+ );
291
+ if (process.env[PERF_MEASUREMENT_ENV]) {
292
+ list.getEntries().forEach((entry) => this._events.push(entry));
293
+ }
239
294
  });
240
- this._observer.observe({ buffered: true, entryTypes: ["function"] });
295
+ const entryTypes = ["measure"];
296
+ if (process.env[PERF_MEASUREMENT_ENV]) {
297
+ entryTypes.push("function");
298
+ }
299
+ this._observer.observe({ buffered: true, entryTypes });
241
300
  this.started = true;
242
- this._csvWriter = createObjectCsvWriter({
243
- path: csvName,
244
- header: [
245
- { id: "name", title: "Function Name" },
246
- { id: "time", title: "Execution Time (ms)" }
247
- ]
248
- });
249
- }
250
- static getPerformance() {
251
- return performance;
301
+ if (process.env[PERF_MEASUREMENT_ENV]) {
302
+ this._csvWriter = createObjectCsvWriter({
303
+ path: csvName,
304
+ header: [
305
+ { id: "name", title: "Function Name" },
306
+ { id: "time", title: "Execution Time (ms)" }
307
+ ]
308
+ });
309
+ }
252
310
  }
253
311
  static calculateTimes(methods) {
254
312
  const times = {};
@@ -261,26 +319,35 @@ var PerformanceTester = class {
261
319
  const timeTaken = methods.reduce((a, c) => {
262
320
  return times[c] + (a || 0);
263
321
  }, 0);
264
- BStackLogger.info(`Time for ${methods} is ${timeTaken}`);
322
+ BStackLogger.debug(`Time for ${methods} is ${timeTaken}`);
265
323
  return timeTaken;
266
324
  }
267
325
  static async stopAndGenerate(filename = "performance-own.html") {
268
326
  if (!this.started) {
269
327
  return;
270
328
  }
271
- await sleep(2e3);
329
+ try {
330
+ const eventsJson = JSON.stringify(this._measuredEvents);
331
+ const finalJSONStr = eventsJson.slice(1, -1) + ",";
332
+ await fsPromise.appendFile(this.jsonReportFileName, finalJSONStr);
333
+ } catch (er) {
334
+ BStackLogger.debug(`Failed to write events of the worker to ${this.jsonReportFileName}: ${util.format(er)}`);
335
+ }
272
336
  this._observer.disconnect();
337
+ if (!process.env[PERF_MEASUREMENT_ENV]) {
338
+ return;
339
+ }
340
+ await _PerformanceTester.sleep(2e3);
273
341
  this.started = false;
274
342
  this.generateCSV(this._events);
275
343
  const content = this.generateReport(this._events);
276
- const path14 = process.cwd() + "/" + filename;
277
- fs.writeFile(path14, content, (err) => {
278
- if (err) {
279
- BStackLogger.error(`Error in writing html ${err}`);
280
- return;
281
- }
282
- BStackLogger.info(`Performance report is at ${path14}`);
283
- });
344
+ const dir = path.join(process.cwd(), filename);
345
+ try {
346
+ await fsPromise.writeFile(dir, content);
347
+ BStackLogger.info(`Performance report is at ${path}`);
348
+ } catch (err) {
349
+ BStackLogger.error(`Error in writing html ${util.format(err)}`);
350
+ }
284
351
  }
285
352
  static generateReport(entries) {
286
353
  let html = "<!DOCTYPE html><html><head><title>Performance Report</title></head><body>";
@@ -312,6 +379,221 @@ var PerformanceTester = class {
312
379
  });
313
380
  this._csvWriter.writeRecords(dat).then(() => BStackLogger.info("Performance CSV report generated successfully")).catch((error) => console.error(error));
314
381
  }
382
+ static Measure(label, details = {}) {
383
+ const self = this;
384
+ return (target, key, descriptor) => {
385
+ const originalMethod = descriptor.value;
386
+ if (descriptor.value) {
387
+ descriptor.value = function(...args) {
388
+ return _PerformanceTester.measure.apply(self, [label, originalMethod, { methodName: key.toString(), ...details }, args, this]);
389
+ };
390
+ }
391
+ };
392
+ }
393
+ static measureWrapper(name, fn, details = {}) {
394
+ const self = this;
395
+ details.worker = _PerformanceTester.getProcessId();
396
+ details.testName = _PerformanceTester.scenarioThatRan && _PerformanceTester.scenarioThatRan[_PerformanceTester.scenarioThatRan.length - 1];
397
+ details.platform = _PerformanceTester.browser?.sessionId;
398
+ return function(...args) {
399
+ return self.measure(name, fn, details, args);
400
+ };
401
+ }
402
+ static isEnabled() {
403
+ return !(process.env.BROWSERSTACK_SDK_INSTRUMENTATION === "false");
404
+ }
405
+ static measure(label, fn, details = {}, args, thisArg = null) {
406
+ if (!this.started || !this.isEnabled()) {
407
+ return fn.apply(thisArg, args);
408
+ }
409
+ _PerformanceTester.start(label);
410
+ if (this.details) {
411
+ this.details[label] = details;
412
+ }
413
+ try {
414
+ const returnVal = fn.apply(thisArg, args);
415
+ if (returnVal instanceof Promise) {
416
+ return new Promise((resolve, reject) => {
417
+ returnVal.then((v) => {
418
+ _PerformanceTester.end(label);
419
+ resolve(v);
420
+ }).catch((e) => {
421
+ _PerformanceTester.end(label, false, util.format(e));
422
+ reject(e);
423
+ });
424
+ });
425
+ }
426
+ _PerformanceTester.end(label);
427
+ return returnVal;
428
+ } catch (er) {
429
+ _PerformanceTester.end(label, false, util.format(er));
430
+ throw er;
431
+ }
432
+ }
433
+ static start(event) {
434
+ const finalEvent = event + "-start";
435
+ if (this.eventsMap[finalEvent]) {
436
+ return;
437
+ }
438
+ performance.mark(finalEvent);
439
+ this.eventsMap[finalEvent] = 1;
440
+ }
441
+ static end(event, success = true, failure, details = {}) {
442
+ performance.mark(event + "-end");
443
+ performance.measure(event, event + "-start", event + "-end");
444
+ this.details[event] = Object.assign({ success, failure: util.format(failure) }, Object.assign(Object.assign({
445
+ worker: _PerformanceTester.getProcessId(),
446
+ platform: _PerformanceTester.browser?.sessionId,
447
+ testName: _PerformanceTester.scenarioThatRan && _PerformanceTester.scenarioThatRan[_PerformanceTester.scenarioThatRan.length - 1]
448
+ }, details), this.details[event] || {}));
449
+ }
450
+ static getProcessId() {
451
+ return `${process.pid}-${worker.threadId}`;
452
+ }
453
+ static sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms));
454
+ static async uploadEventsData() {
455
+ try {
456
+ let measures = [];
457
+ if (await fsPromise.access(this.jsonReportDirPath).then(() => true).catch(() => false)) {
458
+ const files = (await fsPromise.readdir(this.jsonReportDirPath)).map((file) => path.resolve(this.jsonReportDirPath, file));
459
+ measures = (await Promise.all(files.map((file) => fsPromise.readFile(file, "utf-8")))).map((el) => `[${el.slice(0, -1)}]`).map((el) => JSON.parse(el)).flat();
460
+ }
461
+ if (this._measuredEvents.length > 0) {
462
+ measures = measures.concat(this._measuredEvents);
463
+ }
464
+ const date = /* @__PURE__ */ new Date();
465
+ const options = {
466
+ timeZone: "UTC",
467
+ year: "numeric",
468
+ month: "2-digit",
469
+ day: "2-digit",
470
+ hour: "2-digit",
471
+ minute: "2-digit",
472
+ second: "2-digit",
473
+ fractionalSecondDigits: 3,
474
+ // To include microseconds
475
+ hour12: false
476
+ };
477
+ const formattedDate = new Intl.DateTimeFormat("en-GB", options).formatToParts(date).map(({ type: type3, value }) => type3 === "timeZoneName" ? "Z" : value).join("").replace(",", "T");
478
+ const payload = {
479
+ event_type: "sdk_events",
480
+ data: {
481
+ testhub_uuid: process.env.PERF_TESTHUB_UUID || process.env.SDK_RUN_ID,
482
+ created_day: formattedDate,
483
+ event_name: "SDKFeaturePerformance",
484
+ user_data: process.env.PERF_USER_NAME,
485
+ host_info: JSON.stringify({
486
+ hostname: hostname(),
487
+ platform: platform(),
488
+ type: type(),
489
+ version: version(),
490
+ arch: arch()
491
+ }),
492
+ event_json: { measures, sdkRunId: process.env.SDK_RUN_ID }
493
+ }
494
+ };
495
+ const result = await fetchWrap(`${EDS_URL}/send_sdk_events`, {
496
+ method: "POST",
497
+ headers: {
498
+ "content-type": "application/json"
499
+ },
500
+ body: JSON.stringify(payload)
501
+ });
502
+ BStackLogger.debug(`Successfully uploaded performance events ${util.format(await result.text())}`);
503
+ } catch (er) {
504
+ BStackLogger.debug(`Failed to upload performance events ${util.format(er)}`);
505
+ }
506
+ try {
507
+ if (await fsPromise.access(this.jsonReportDirPath).then(() => true, () => false)) {
508
+ const files = await fsPromise.readdir(this.jsonReportDirPath);
509
+ for (const file of files) {
510
+ await fsPromise.unlink(path.join(this.jsonReportDirPath, file));
511
+ }
512
+ }
513
+ } catch (er) {
514
+ BStackLogger.debug(`Failed to delete performance related files ${util.format(er)}`);
515
+ }
516
+ }
517
+ };
518
+
519
+ // src/instrumentation/performance/constants.ts
520
+ var EVENTS = {
521
+ SDK_SETUP: "sdk:setup",
522
+ SDK_CLEANUP: "sdk:cleanup",
523
+ SDK_PRE_TEST: "sdk:pre-test",
524
+ SDK_TEST: "sdk:test",
525
+ SDK_POST_TEST: "sdk:post-test",
526
+ SDK_HOOK: "sdk:hook",
527
+ SDK_DRIVER: "sdk:driver",
528
+ SDK_A11Y: "sdk:a11y",
529
+ SDK_O11Y: "sdk:o11y",
530
+ SDK_AUTO_CAPTURE: "sdk:auto-capture",
531
+ SDK_PROXY_SETUP: "sdk:proxy-setup",
532
+ SDK_TESTHUB: "sdk:testhub",
533
+ SDK_AUTOMATE: "sdk:automate",
534
+ SDK_APP_AUTOMATE: "sdk:app-automate",
535
+ SDK_TURBOSCALE: "sdk:turboscale",
536
+ SDK_PERCY: "sdk:percy",
537
+ SDK_PRE_INITIALIZE: "sdk:driver:pre-initialization",
538
+ SDK_POST_INITIALIZE: "sdk:driver:post-initialization"
539
+ };
540
+ var TESTHUB_EVENTS = {
541
+ START: `${EVENTS.SDK_TESTHUB}:start`,
542
+ STOP: `${EVENTS.SDK_TESTHUB}:stop`
543
+ };
544
+ var AUTOMATE_EVENTS = {
545
+ KEEP_ALIVE: `${EVENTS.SDK_AUTOMATE}:keep-alive`,
546
+ HUB_MANAGEMENT: `${EVENTS.SDK_AUTOMATE}:hub-management`,
547
+ LOCAL_START: `${EVENTS.SDK_AUTOMATE}:local-start`,
548
+ LOCAL_STOP: `${EVENTS.SDK_AUTOMATE}:local-stop`,
549
+ DRIVER_MANAGE: `${EVENTS.SDK_AUTOMATE}:driver-manage`,
550
+ SESSION_NAME: `${EVENTS.SDK_AUTOMATE}:session-name`,
551
+ SESSION_STATUS: `${EVENTS.SDK_AUTOMATE}:session-status`,
552
+ SESSION_ANNOTATION: `${EVENTS.SDK_AUTOMATE}:session-annotation`,
553
+ IDLE_TIMEOUT: `${EVENTS.SDK_AUTOMATE}:idle-timeout`,
554
+ GENERATE_CI_ARTIFACT: `${EVENTS.SDK_AUTOMATE}:ci-artifacts`,
555
+ PRINT_BUILDLINK: `${EVENTS.SDK_AUTOMATE}:print-buildlink`
556
+ };
557
+ var A11Y_EVENTS = {
558
+ PERFORM_SCAN: `${EVENTS.SDK_A11Y}:driver-performscan`,
559
+ SAVE_RESULTS: `${EVENTS.SDK_A11Y}:save-results`,
560
+ GET_RESULTS: `${EVENTS.SDK_A11Y}:get-accessibility-results`,
561
+ GET_RESULTS_SUMMARY: `${EVENTS.SDK_A11Y}:get-accessibility-results-summary`
562
+ };
563
+ var PERCY_EVENTS = {
564
+ DOWNLOAD: `${EVENTS.SDK_PERCY}:download`,
565
+ SCREENSHOT: `${EVENTS.SDK_PERCY}:screenshot`,
566
+ START: `${EVENTS.SDK_PERCY}:start`,
567
+ STOP: `${EVENTS.SDK_PERCY}:stop`,
568
+ AUTO_CAPTURE: `${EVENTS.SDK_PERCY}:auto-capture`,
569
+ SNAPSHOT: `${EVENTS.SDK_PERCY}:snapshot`,
570
+ SCREENSHOT_APP: `${EVENTS.SDK_PERCY}:screenshot-app`
571
+ };
572
+ var O11Y_EVENTS = {
573
+ SYNC: `${EVENTS.SDK_O11Y}:sync`,
574
+ TAKE_SCREENSHOT: `${EVENTS.SDK_O11Y}:driver-takeScreenShot`,
575
+ PRINT_BUILDLINK: `${EVENTS.SDK_O11Y}:print-buildlink`
576
+ };
577
+ var HOOK_EVENTS = {
578
+ BEFORE_EACH: `${EVENTS.SDK_HOOK}:before-each`,
579
+ AFTER_EACH: `${EVENTS.SDK_HOOK}:after-each`,
580
+ AFTER_ALL: `${EVENTS.SDK_HOOK}:after-all`,
581
+ BEFORE_ALL: `${EVENTS.SDK_HOOK}:before-all`,
582
+ BEFORE: `${EVENTS.SDK_HOOK}:before`,
583
+ AFTER: `${EVENTS.SDK_HOOK}:after`
584
+ };
585
+ var TURBOSCALE_EVENTS = {
586
+ HUB_MANAGEMENT: `${EVENTS.SDK_TURBOSCALE}:hub-management`,
587
+ PRINT_BUILDLINK: `${EVENTS.SDK_TURBOSCALE}:print-buildlink`
588
+ };
589
+ var APP_AUTOMATE_EVENTS = {
590
+ APP_UPLOAD: `${EVENTS.SDK_APP_AUTOMATE}:app-upload`
591
+ };
592
+ var DRIVER_EVENT = {
593
+ QUIT: `${EVENTS.SDK_DRIVER}:quit`,
594
+ GET: `${EVENTS.SDK_DRIVER}:get`,
595
+ PRE_EXECUTE: `${EVENTS.SDK_DRIVER}:pre-execute`,
596
+ POST_EXECUTE: `${EVENTS.SDK_DRIVER}:post-execute`
315
597
  };
316
598
 
317
599
  // src/crash-reporter.ts
@@ -740,7 +1022,7 @@ var UsageStats = class _UsageStats {
740
1022
  var usageStats_default = UsageStats;
741
1023
 
742
1024
  // src/scripts/accessibility-scripts.ts
743
- import path from "node:path";
1025
+ import path2 from "node:path";
744
1026
  import fs2 from "node:fs";
745
1027
  import os from "node:os";
746
1028
  var AccessibilityScripts = class _AccessibilityScripts {
@@ -755,7 +1037,7 @@ var AccessibilityScripts = class _AccessibilityScripts {
755
1037
  // don't allow to create instances from it other than through `checkAndGetInstance`
756
1038
  constructor() {
757
1039
  this.browserstackFolderPath = this.getWritableDir();
758
- this.commandsPath = path.join(this.browserstackFolderPath, "commands.json");
1040
+ this.commandsPath = path2.join(this.browserstackFolderPath, "commands.json");
759
1041
  }
760
1042
  static checkAndGetInstance() {
761
1043
  if (!_AccessibilityScripts.instance) {
@@ -767,7 +1049,7 @@ var AccessibilityScripts = class _AccessibilityScripts {
767
1049
  /* eslint-disable @typescript-eslint/no-unused-vars */
768
1050
  getWritableDir() {
769
1051
  const orderedPaths = [
770
- path.join(os.homedir(), ".browserstack"),
1052
+ path2.join(os.homedir(), ".browserstack"),
771
1053
  process.cwd(),
772
1054
  os.tmpdir()
773
1055
  ];
@@ -879,7 +1161,7 @@ function processError(error, fn, args) {
879
1161
  try {
880
1162
  argsString = JSON.stringify(args);
881
1163
  } catch {
882
- argsString = util.inspect(args, { depth: 2 });
1164
+ argsString = util2.inspect(args, { depth: 2 });
883
1165
  }
884
1166
  CrashReporter.uploadCrashReport(`Error in executing ${fn.name} with args ${argsString} : ${error}`, error && error.stack || "unknown error");
885
1167
  }
@@ -888,7 +1170,7 @@ function o11yErrorHandler(fn) {
888
1170
  try {
889
1171
  let functionToHandle = fn;
890
1172
  if (process.env[PERF_MEASUREMENT_ENV]) {
891
- functionToHandle = PerformanceTester.getPerformance().timerify(functionToHandle);
1173
+ functionToHandle = performance2.timerify(functionToHandle);
892
1174
  }
893
1175
  const result = functionToHandle(...args);
894
1176
  if (result instanceof Promise) {
@@ -951,7 +1233,7 @@ function o11yClassErrorHandler(errorClass) {
951
1233
  writable: true,
952
1234
  value: function(...args) {
953
1235
  try {
954
- const result = (process.env[PERF_MEASUREMENT_ENV] ? PerformanceTester.getPerformance().timerify(method) : method).call(this, ...args);
1236
+ const result = (process.env[PERF_MEASUREMENT_ENV] ? performance2.timerify(method) : method).call(this, ...args);
955
1237
  if (result instanceof Promise) {
956
1238
  return result.catch((error) => processError(error, method, args));
957
1239
  }
@@ -1026,7 +1308,7 @@ var processLaunchBuildResponse = (response, options) => {
1026
1308
  processAccessibilityResponse(response);
1027
1309
  }
1028
1310
  };
1029
- var launchTestSession = o11yErrorHandler(async function launchTestSession2(options, config, bsConfig, bStackConfig) {
1311
+ var launchTestSession = PerformanceTester.measureWrapper(TESTHUB_EVENTS.START, o11yErrorHandler(async function launchTestSession2(options, config, bsConfig, bStackConfig) {
1030
1312
  const launchBuildUsage = usageStats_default.getInstance().launchBuildUsage;
1031
1313
  launchBuildUsage.triggered();
1032
1314
  const data = {
@@ -1037,11 +1319,11 @@ var launchTestSession = o11yErrorHandler(async function launchTestSession2(optio
1037
1319
  started_at: (/* @__PURE__ */ new Date()).toISOString(),
1038
1320
  tags: getObservabilityBuildTags(options, bsConfig.buildTag),
1039
1321
  host_info: {
1040
- hostname: hostname(),
1041
- platform: platform(),
1042
- type: type(),
1043
- version: version(),
1044
- arch: arch()
1322
+ hostname: hostname2(),
1323
+ platform: platform2(),
1324
+ type: type2(),
1325
+ version: version2(),
1326
+ arch: arch2()
1045
1327
  },
1046
1328
  ci_info: getCiInfo(),
1047
1329
  build_run_identifier: process.env.BROWSERSTACK_BUILD_RUN_IDENTIFIER,
@@ -1093,6 +1375,7 @@ var launchTestSession = o11yErrorHandler(async function launchTestSession2(optio
1093
1375
  if (jsonResponse.build_hashed_id) {
1094
1376
  process.env[BROWSERSTACK_TESTHUB_UUID] = jsonResponse.build_hashed_id;
1095
1377
  testOpsConfig_default.getInstance().buildHashedId = jsonResponse.build_hashed_id;
1378
+ BStackLogger.info(`Testhub started with id: ${testOpsConfig_default.getInstance()?.buildHashedId}`);
1096
1379
  }
1097
1380
  processLaunchBuildResponse(jsonResponse, options);
1098
1381
  launchBuildUsage.success();
@@ -1104,7 +1387,7 @@ var launchTestSession = o11yErrorHandler(async function launchTestSession2(optio
1104
1387
  return;
1105
1388
  }
1106
1389
  }
1107
- });
1390
+ }));
1108
1391
  var validateCapsWithAppA11y = (platformMeta) => {
1109
1392
  if (platformMeta?.platform_name && String(platformMeta?.platform_name).toLowerCase() === "android" && (platformMeta?.platform_version && parseInt(platformMeta?.platform_version?.toString()) < 11)) {
1110
1393
  BStackLogger.warn("App Accessibility Automation tests are supported on OS version 11 and above for Android devices.");
@@ -1202,7 +1485,7 @@ var performA11yScan = async (isAppAutomate, browser, isBrowserStackSession, isAc
1202
1485
  try {
1203
1486
  if (isAppAccessibilityAutomationSession(isAccessibility, isAppAutomate)) {
1204
1487
  const results = await browser.execute(formatString(accessibility_scripts_default.performScan, JSON.stringify(_getParamsForAppAccessibility(commandName))), {});
1205
- BStackLogger.debug(util.format(results));
1488
+ BStackLogger.debug(util2.format(results));
1206
1489
  return results;
1207
1490
  }
1208
1491
  if (accessibility_scripts_default.performScan) {
@@ -1216,7 +1499,7 @@ var performA11yScan = async (isAppAutomate, browser, isBrowserStackSession, isAc
1216
1499
  return;
1217
1500
  }
1218
1501
  };
1219
- var getA11yResults = async (isAppAutomate, browser, isBrowserStackSession, isAccessibility) => {
1502
+ var getA11yResults = PerformanceTester.measureWrapper(A11Y_EVENTS.GET_RESULTS, async (isAppAutomate, browser, isBrowserStackSession, isAccessibility) => {
1220
1503
  if (!isBrowserStackSession) {
1221
1504
  BStackLogger.warn("Not a BrowserStack Automate session, cannot retrieve Accessibility results.");
1222
1505
  return [];
@@ -1239,8 +1522,8 @@ var getA11yResults = async (isAppAutomate, browser, isBrowserStackSession, isAcc
1239
1522
  BStackLogger.debug(`getA11yResults Failed. Error: ${error}`);
1240
1523
  return [];
1241
1524
  }
1242
- };
1243
- var getAppA11yResults = async (isAppAutomate, browser, isBrowserStackSession, isAccessibility, sessionId) => {
1525
+ });
1526
+ var getAppA11yResults = PerformanceTester.measureWrapper(A11Y_EVENTS.GET_RESULTS, async (isAppAutomate, browser, isBrowserStackSession, isAccessibility, sessionId) => {
1244
1527
  if (!isBrowserStackSession) {
1245
1528
  return [];
1246
1529
  }
@@ -1259,8 +1542,8 @@ var getAppA11yResults = async (isAppAutomate, browser, isBrowserStackSession, is
1259
1542
  BStackLogger.debug(`getAppA11yResults Failed. Error: ${error}`);
1260
1543
  return [];
1261
1544
  }
1262
- };
1263
- var getAppA11yResultsSummary = async (isAppAutomate, browser, isBrowserStackSession, isAccessibility, sessionId) => {
1545
+ });
1546
+ var getAppA11yResultsSummary = PerformanceTester.measureWrapper(A11Y_EVENTS.GET_RESULTS_SUMMARY, async (isAppAutomate, browser, isBrowserStackSession, isAccessibility, sessionId) => {
1264
1547
  if (!isBrowserStackSession) {
1265
1548
  return {};
1266
1549
  }
@@ -1278,7 +1561,7 @@ var getAppA11yResultsSummary = async (isAppAutomate, browser, isBrowserStackSess
1278
1561
  BStackLogger.error("No accessibility summary was found.");
1279
1562
  return {};
1280
1563
  }
1281
- };
1564
+ });
1282
1565
  var getAppA11yResultResponse = async (apiUrl, isAppAutomate, browser, isBrowserStackSession, isAccessibility, sessionId) => {
1283
1566
  BStackLogger.debug("Performing scan before getting results summary");
1284
1567
  await performA11yScan(isAppAutomate, browser, isBrowserStackSession, isAccessibility);
@@ -1289,7 +1572,7 @@ var getAppA11yResultResponse = async (apiUrl, isAppAutomate, browser, isBrowserS
1289
1572
  BStackLogger.debug(`Polling Result: ${JSON.stringify(apiRespone)}`);
1290
1573
  return apiRespone;
1291
1574
  };
1292
- var getA11yResultsSummary = async (isAppAutomate, browser, isBrowserStackSession, isAccessibility) => {
1575
+ var getA11yResultsSummary = PerformanceTester.measureWrapper(A11Y_EVENTS.GET_RESULTS_SUMMARY, async (isAppAutomate, browser, isBrowserStackSession, isAccessibility) => {
1293
1576
  if (!isBrowserStackSession) {
1294
1577
  return {};
1295
1578
  }
@@ -1310,8 +1593,8 @@ var getA11yResultsSummary = async (isAppAutomate, browser, isBrowserStackSession
1310
1593
  BStackLogger.error("No accessibility summary was found.");
1311
1594
  return {};
1312
1595
  }
1313
- };
1314
- var stopBuildUpstream = o11yErrorHandler(async function stopBuildUpstream2() {
1596
+ });
1597
+ var stopBuildUpstream = PerformanceTester.measureWrapper(TESTHUB_EVENTS.STOP, o11yErrorHandler(async function stopBuildUpstream2() {
1315
1598
  const stopBuildUsage = usageStats_default.getInstance().stopBuildUsage;
1316
1599
  stopBuildUsage.triggered();
1317
1600
  if (!process.env[TESTOPS_BUILD_COMPLETED_ENV]) {
@@ -1356,7 +1639,7 @@ var stopBuildUpstream = o11yErrorHandler(async function stopBuildUpstream2() {
1356
1639
  message: error.message
1357
1640
  };
1358
1641
  }
1359
- });
1642
+ }));
1360
1643
  function getCiInfo() {
1361
1644
  const env = process.env;
1362
1645
  if (typeof env.JENKINS_URL === "string" && env.JENKINS_URL.length > 0 || typeof env.JENKINS_HOME === "string" && env.JENKINS_HOME.length > 0) {
@@ -1779,7 +2062,7 @@ function getObservabilityBuild(options, bstackBuildName) {
1779
2062
  if (options.testObservabilityOptions && options.testObservabilityOptions.buildName) {
1780
2063
  return options.testObservabilityOptions.buildName;
1781
2064
  }
1782
- return bstackBuildName || path2.basename(path2.resolve(process.cwd()));
2065
+ return bstackBuildName || path3.basename(path3.resolve(process.cwd()));
1783
2066
  }
1784
2067
  function getObservabilityBuildTags(options, bstackBuildTag) {
1785
2068
  if (process.env.TEST_OBSERVABILITY_BUILD_TAG) {
@@ -2075,8 +2358,8 @@ async function executeAccessibilityScript(browser, fnBody, arg) {
2075
2358
  // src/bstackLogger.ts
2076
2359
  var log = logger("@wdio/browserstack-service");
2077
2360
  var BStackLogger = class {
2078
- static logFilePath = path3.join(process.cwd(), LOGS_FILE);
2079
- static logFolderPath = path3.join(process.cwd(), "logs");
2361
+ static logFilePath = path4.join(process.cwd(), LOGS_FILE);
2362
+ static logFolderPath = path4.join(process.cwd(), "logs");
2080
2363
  static logFileStream;
2081
2364
  static logToFile(logMessage, logLevel) {
2082
2365
  try {
@@ -2194,14 +2477,14 @@ var logBuildError = (error, product = "") => {
2194
2477
  };
2195
2478
 
2196
2479
  // src/Percy/PercyLogger.ts
2197
- import path4 from "node:path";
2480
+ import path5 from "node:path";
2198
2481
  import fs5 from "node:fs";
2199
2482
  import chalk2 from "chalk";
2200
2483
  import logger2 from "@wdio/logger";
2201
2484
  var log2 = logger2("@wdio/browserstack-service");
2202
2485
  var PercyLogger = class {
2203
- static logFilePath = path4.join(process.cwd(), PERCY_LOGS_FILE);
2204
- static logFolderPath = path4.join(process.cwd(), "logs");
2486
+ static logFilePath = path5.join(process.cwd(), PERCY_LOGS_FILE);
2487
+ static logFolderPath = path5.join(process.cwd(), "logs");
2205
2488
  static logFileStream;
2206
2489
  static logToFile(logMessage, logLevel) {
2207
2490
  try {
@@ -2261,7 +2544,7 @@ var PercyLogger = class {
2261
2544
 
2262
2545
  // src/Percy/Percy.ts
2263
2546
  import fs7 from "node:fs";
2264
- import path6 from "node:path";
2547
+ import path7 from "node:path";
2265
2548
  import os3 from "node:os";
2266
2549
  import { spawn as spawn2 } from "node:child_process";
2267
2550
 
@@ -2270,7 +2553,7 @@ import yauzl from "yauzl";
2270
2553
  import fs6 from "node:fs";
2271
2554
  import fsp from "node:fs/promises";
2272
2555
  import { pipeline } from "node:stream/promises";
2273
- import path5 from "node:path";
2556
+ import path6 from "node:path";
2274
2557
  import os2 from "node:os";
2275
2558
  import { spawn } from "node:child_process";
2276
2559
  var PercyBinary = class {
@@ -2278,7 +2561,7 @@ var PercyBinary = class {
2278
2561
  #httpPath = null;
2279
2562
  #binaryName = "percy";
2280
2563
  #orderedPaths = [
2281
- path5.join(os2.homedir(), ".browserstack"),
2564
+ path6.join(os2.homedir(), ".browserstack"),
2282
2565
  process.cwd(),
2283
2566
  os2.tmpdir()
2284
2567
  ];
@@ -2293,15 +2576,15 @@ var PercyBinary = class {
2293
2576
  this.#httpPath = base + "/percy-linux.zip";
2294
2577
  }
2295
2578
  }
2296
- async #makePath(path14) {
2297
- if (await this.#checkPath(path14)) {
2579
+ async #makePath(path15) {
2580
+ if (await this.#checkPath(path15)) {
2298
2581
  return true;
2299
2582
  }
2300
- return fsp.mkdir(path14).then(() => true).catch(() => false);
2583
+ return fsp.mkdir(path15).then(() => true).catch(() => false);
2301
2584
  }
2302
- async #checkPath(path14) {
2585
+ async #checkPath(path15) {
2303
2586
  try {
2304
- const hasDir = await fsp.access(path14).then(() => true, () => false);
2587
+ const hasDir = await fsp.access(path15).then(() => true, () => false);
2305
2588
  if (hasDir) {
2306
2589
  return true;
2307
2590
  }
@@ -2311,16 +2594,16 @@ var PercyBinary = class {
2311
2594
  }
2312
2595
  async #getAvailableDirs() {
2313
2596
  for (let i = 0; i < this.#orderedPaths.length; i++) {
2314
- const path14 = this.#orderedPaths[i];
2315
- if (await this.#makePath(path14)) {
2316
- return path14;
2597
+ const path15 = this.#orderedPaths[i];
2598
+ if (await this.#makePath(path15)) {
2599
+ return path15;
2317
2600
  }
2318
2601
  }
2319
2602
  throw new Error("Error trying to download percy binary");
2320
2603
  }
2321
2604
  async getBinaryPath() {
2322
2605
  const destParentDir = await this.#getAvailableDirs();
2323
- const binaryPath = path5.join(destParentDir, this.#binaryName);
2606
+ const binaryPath = path6.join(destParentDir, this.#binaryName);
2324
2607
  if (await this.#checkPath(binaryPath)) {
2325
2608
  return binaryPath;
2326
2609
  }
@@ -2351,8 +2634,8 @@ var PercyBinary = class {
2351
2634
  await fsp.mkdir(destParentDir);
2352
2635
  }
2353
2636
  const binaryName = this.#binaryName;
2354
- const zipFilePath = path5.join(destParentDir, binaryName + ".zip");
2355
- const binaryPath = path5.join(destParentDir, binaryName);
2637
+ const zipFilePath = path6.join(destParentDir, binaryName + ".zip");
2638
+ const binaryPath = path6.join(destParentDir, binaryName);
2356
2639
  const downloadedFileStream = fs6.createWriteStream(zipFilePath);
2357
2640
  const response = await fetch(this.#httpPath);
2358
2641
  await pipeline(response.body, downloadedFileStream);
@@ -2367,7 +2650,7 @@ var PercyBinary = class {
2367
2650
  zipfile.readEntry();
2368
2651
  } else {
2369
2652
  const writeStream = fs6.createWriteStream(
2370
- path5.join(destParentDir, entry.fileName)
2653
+ path6.join(destParentDir, entry.fileName)
2371
2654
  );
2372
2655
  zipfile.openReadStream(entry, function(zipErr, readStream) {
2373
2656
  if (zipErr) {
@@ -2400,12 +2683,15 @@ var PercyBinary = class {
2400
2683
  });
2401
2684
  }
2402
2685
  };
2686
+ __decorateClass([
2687
+ PerformanceTester.Measure(PERCY_EVENTS.DOWNLOAD)
2688
+ ], PercyBinary.prototype, "download", 1);
2403
2689
  var PercyBinary_default = PercyBinary;
2404
2690
 
2405
2691
  // src/Percy/Percy.ts
2406
2692
  var logDir = "logs";
2407
2693
  var Percy = class {
2408
- #logfile = path6.join(logDir, "percy.log");
2694
+ #logfile = path7.join(logDir, "percy.log");
2409
2695
  #address = process.env.PERCY_SERVER_ADDRESS || "http://127.0.0.1:5338";
2410
2696
  #binaryPath = null;
2411
2697
  #options;
@@ -2494,13 +2780,13 @@ var Percy = class {
2494
2780
  async fetchPercyToken() {
2495
2781
  const projectName = this.#projectName;
2496
2782
  try {
2497
- const type2 = this.#isApp ? "app" : "automate";
2783
+ const type3 = this.#isApp ? "app" : "automate";
2498
2784
  const params = new URLSearchParams();
2499
2785
  if (projectName) {
2500
2786
  params.set("name", projectName);
2501
2787
  }
2502
- if (type2) {
2503
- params.set("type", type2);
2788
+ if (type3) {
2789
+ params.set("type", type3);
2504
2790
  }
2505
2791
  if (this.#options.percyCaptureMode) {
2506
2792
  params.set("percy_capture_mode", this.#options.percyCaptureMode);
@@ -2533,7 +2819,7 @@ var Percy = class {
2533
2819
  if (!this.#options.percyOptions) {
2534
2820
  return null;
2535
2821
  }
2536
- const configPath = path6.join(os3.tmpdir(), "percy.json");
2822
+ const configPath = path7.join(os3.tmpdir(), "percy.json");
2537
2823
  const percyOptions = this.#options.percyOptions;
2538
2824
  if (!percyOptions.version) {
2539
2825
  percyOptions.version = "2";
@@ -2556,6 +2842,12 @@ var Percy = class {
2556
2842
  });
2557
2843
  }
2558
2844
  };
2845
+ __decorateClass([
2846
+ PerformanceTester.Measure(PERCY_EVENTS.START)
2847
+ ], Percy.prototype, "start", 1);
2848
+ __decorateClass([
2849
+ PerformanceTester.Measure(PERCY_EVENTS.STOP)
2850
+ ], Percy.prototype, "stop", 1);
2559
2851
  var Percy_default = Percy;
2560
2852
 
2561
2853
  // src/Percy/PercyHelper.ts
@@ -2566,7 +2858,7 @@ var startPercy = async (options, config, bsConfig) => {
2566
2858
  if (response) {
2567
2859
  return percy;
2568
2860
  }
2569
- return {};
2861
+ return void 0;
2570
2862
  };
2571
2863
  var stopPercy = async (percy) => {
2572
2864
  PercyLogger.debug("Stopping percy");
@@ -2623,6 +2915,7 @@ var getBestPlatformForPercySnapshot = (capabilities) => {
2623
2915
  };
2624
2916
 
2625
2917
  // src/config.ts
2918
+ import { v4 as uuidv4 } from "uuid";
2626
2919
  var BrowserStackConfig = class _BrowserStackConfig {
2627
2920
  static getInstance(options, config) {
2628
2921
  if (!this._instance && options && config) {
@@ -2646,6 +2939,7 @@ var BrowserStackConfig = class _BrowserStackConfig {
2646
2939
  funnelDataSent = false;
2647
2940
  percyBuildId;
2648
2941
  isPercyAutoEnabled = false;
2942
+ sdkRunID;
2649
2943
  constructor(options, config) {
2650
2944
  this.framework = config.framework;
2651
2945
  this.userName = config.user;
@@ -2657,6 +2951,8 @@ var BrowserStackConfig = class _BrowserStackConfig {
2657
2951
  this.appAutomate = !isUndefined(options.app);
2658
2952
  this.automate = !this.appAutomate;
2659
2953
  this.buildIdentifier = options.buildIdentifier;
2954
+ this.sdkRunID = uuidv4();
2955
+ BStackLogger.info(`BrowserStack service started with id: ${this.sdkRunID}`);
2660
2956
  }
2661
2957
  sentFunnelData() {
2662
2958
  this.funnelDataSent = true;
@@ -2666,18 +2962,18 @@ var config_default = BrowserStackConfig;
2666
2962
 
2667
2963
  // src/exitHandler.ts
2668
2964
  import { spawn as spawn3 } from "node:child_process";
2669
- import path9 from "node:path";
2965
+ import path10 from "node:path";
2670
2966
 
2671
2967
  // src/instrumentation/funnelInstrumentation.ts
2672
2968
  import os4 from "node:os";
2673
- import util2, { format as format2 } from "node:util";
2674
- import path8 from "node:path";
2969
+ import util3, { format as format2 } from "node:util";
2970
+ import path9 from "node:path";
2675
2971
  import fs9 from "node:fs";
2676
2972
 
2677
2973
  // src/data-store.ts
2678
- import path7 from "node:path";
2974
+ import path8 from "node:path";
2679
2975
  import fs8 from "node:fs";
2680
- var workersDataDirPath = path7.join(process.cwd(), "logs", "worker_data");
2976
+ var workersDataDirPath = path8.join(process.cwd(), "logs", "worker_data");
2681
2977
  function getDataFromWorkers() {
2682
2978
  const workersData = [];
2683
2979
  if (!fs8.existsSync(workersDataDirPath)) {
@@ -2686,7 +2982,7 @@ function getDataFromWorkers() {
2686
2982
  const files = fs8.readdirSync(workersDataDirPath);
2687
2983
  files.forEach((file) => {
2688
2984
  BStackLogger.debug("Reading worker file " + file);
2689
- const filePath = path7.join(workersDataDirPath, file);
2985
+ const filePath = path8.join(workersDataDirPath, file);
2690
2986
  const fileContent = fs8.readFileSync(filePath, "utf8");
2691
2987
  const workerData = JSON.parse(fileContent);
2692
2988
  workersData.push(workerData);
@@ -2695,7 +2991,7 @@ function getDataFromWorkers() {
2695
2991
  return workersData;
2696
2992
  }
2697
2993
  function saveWorkerData(data) {
2698
- const filePath = path7.join(workersDataDirPath, "worker-data-" + process.pid + ".json");
2994
+ const filePath = path8.join(workersDataDirPath, "worker-data-" + process.pid + ".json");
2699
2995
  try {
2700
2996
  createWorkersDataDir();
2701
2997
  fs8.writeFileSync(filePath, JSON.stringify(data));
@@ -2714,22 +3010,6 @@ function createWorkersDataDir() {
2714
3010
  return true;
2715
3011
  }
2716
3012
 
2717
- // src/fetchWrapper.ts
2718
- var ResponseError = class extends Error {
2719
- response;
2720
- constructor(message, res) {
2721
- super(message);
2722
- this.response = res;
2723
- }
2724
- };
2725
- async function fetchWrap(input, init) {
2726
- const res = await fetch(input, init);
2727
- if (!res.ok) {
2728
- throw new ResponseError(`Error response from server ${res.status}: ${await res.text()}`, res);
2729
- }
2730
- return res;
2731
- }
2732
-
2733
3013
  // src/instrumentation/funnelInstrumentation.ts
2734
3014
  async function fireFunnelTestEvent(eventType, config) {
2735
3015
  if (!config.userName || !config.accessKey) {
@@ -2754,7 +3034,7 @@ async function sendFinish(config) {
2754
3034
  function saveFunnelData(eventType, config) {
2755
3035
  const data = buildEventData(eventType, config);
2756
3036
  BStackLogger.ensureLogsFolder();
2757
- const filePath = path8.join(BStackLogger.logFolderPath, "funnelData.json");
3037
+ const filePath = path9.join(BStackLogger.logFolderPath, "funnelData.json");
2758
3038
  fs9.writeFileSync(filePath, JSON.stringify(data));
2759
3039
  return filePath;
2760
3040
  }
@@ -2772,7 +3052,7 @@ function redactCredentialsFromFunnelData(data) {
2772
3052
  async function fireFunnelRequest(data) {
2773
3053
  const { userName, accessKey } = data;
2774
3054
  redactCredentialsFromFunnelData(data);
2775
- BStackLogger.debug("Sending SDK event with data " + util2.inspect(data, { depth: 6 }));
3055
+ BStackLogger.debug("Sending SDK event with data " + util3.inspect(data, { depth: 6 }));
2776
3056
  const encodedAuth = Buffer.from(`${userName}:${accessKey}`, "utf8").toString("base64");
2777
3057
  const response = await fetchWrap(FUNNEL_INSTRUMENTATION_URL, {
2778
3058
  method: "POST",
@@ -2806,6 +3086,8 @@ function getProductList(config) {
2806
3086
  function buildEventData(eventType, config) {
2807
3087
  const eventProperties = {
2808
3088
  // Framework Details
3089
+ sdkRunId: config?.sdkRunID,
3090
+ testhub_uuid: testOpsConfig_default.getInstance().buildHashedId,
2809
3091
  language_framework: getLanguageFramework(config.framework),
2810
3092
  referrer: getReferrer(config.framework),
2811
3093
  language: "WebdriverIO",
@@ -2818,7 +3100,9 @@ function buildEventData(eventType, config) {
2818
3100
  hostname: os4.hostname() || "unknown",
2819
3101
  // Product Details
2820
3102
  productMap: getProductMap(config),
2821
- product: getProductList(config)
3103
+ product: getProductList(config),
3104
+ // framework details
3105
+ framework: config.framework
2822
3106
  };
2823
3107
  if (eventType === "SDKTestSuccessful") {
2824
3108
  const workerData = getDataFromWorkers();
@@ -2930,12 +3214,12 @@ function handleHealingInstrumentation(authResult, config, isSelfHealEnabled) {
2930
3214
  // src/exitHandler.ts
2931
3215
  import { fileURLToPath } from "node:url";
2932
3216
  var __filename = fileURLToPath(import.meta.url);
2933
- var __dirname = path9.dirname(__filename);
3217
+ var __dirname = path10.dirname(__filename);
2934
3218
  function setupExitHandlers() {
2935
3219
  process.on("exit", (code) => {
2936
3220
  const args = shouldCallCleanup(config_default.getInstance());
2937
3221
  if (Array.isArray(args) && args.length) {
2938
- const childProcess = spawn3("node", [`${path9.join(__dirname, "cleanup.js")}`, ...args], { detached: true, stdio: "inherit", env: { ...process.env } });
3222
+ const childProcess = spawn3("node", [`${path10.join(__dirname, "cleanup.js")}`, ...args], { detached: true, stdio: "inherit", env: { ...process.env } });
2939
3223
  childProcess.unref();
2940
3224
  process.exit(code);
2941
3225
  }
@@ -2950,11 +3234,17 @@ function shouldCallCleanup(config) {
2950
3234
  const savedFilePath = saveFunnelData("SDKTestSuccessful", config);
2951
3235
  args.push("--funnelData", savedFilePath);
2952
3236
  }
3237
+ if (PerformanceTester.isEnabled()) {
3238
+ process.env.PERF_USER_NAME = config.userName;
3239
+ process.env.PERF_TESTHUB_UUID = testOpsConfig_default.getInstance().buildHashedId;
3240
+ process.env.SDK_RUN_ID = config.sdkRunID;
3241
+ args.push("--performanceData");
3242
+ }
2953
3243
  return args;
2954
3244
  }
2955
3245
 
2956
3246
  // src/ai-handler.ts
2957
- import path10 from "node:path";
3247
+ import path11 from "node:path";
2958
3248
  import fs10 from "node:fs";
2959
3249
  import url from "node:url";
2960
3250
  import aiSDK from "@browserstack/ai-sdk-node";
@@ -2988,7 +3278,7 @@ var AiHandler = class {
2988
3278
  }
2989
3279
  async installFirefoxExtension(browser) {
2990
3280
  const __dirname2 = url.fileURLToPath(new URL(".", import.meta.url));
2991
- const extensionPath = path10.resolve(__dirname2, aiSDK.BrowserstackHealing.getFirefoxAddonPath());
3281
+ const extensionPath = path11.resolve(__dirname2, aiSDK.BrowserstackHealing.getFirefoxAddonPath());
2992
3282
  const extFile = fs10.readFileSync(extensionPath);
2993
3283
  await browser.installAddOn(extFile.toString("base64"), true);
2994
3284
  }
@@ -3197,9 +3487,7 @@ var BrowserstackLauncherService = class {
3197
3487
  }
3198
3488
  this.browserStackConfig.buildIdentifier = this._buildIdentifier;
3199
3489
  this.browserStackConfig.buildName = this._buildName;
3200
- if (process.env[PERF_MEASUREMENT_ENV]) {
3201
- PerformanceTester.startMonitoring("performance-report-launcher.csv");
3202
- }
3490
+ PerformanceTester.startMonitoring("performance-report-launcher.csv");
3203
3491
  this._accessibilityAutomation ||= isTrue(this._options.accessibility);
3204
3492
  this._options.accessibility = this._accessibilityAutomation;
3205
3493
  this._options.testObservability = this._options.testObservability !== false;
@@ -3265,7 +3553,7 @@ var BrowserstackLauncherService = class {
3265
3553
  } catch (error) {
3266
3554
  throw new SevereServiceError(error.message);
3267
3555
  }
3268
- if (VALID_APP_EXTENSION.includes(path11.extname(app.app))) {
3556
+ if (VALID_APP_EXTENSION.includes(path12.extname(app.app))) {
3269
3557
  if (fs11.existsSync(app.app)) {
3270
3558
  const data = await this._uploadApp(app);
3271
3559
  BStackLogger.info(`app upload completed: ${JSON.stringify(data)}`);
@@ -3340,7 +3628,8 @@ var BrowserstackLauncherService = class {
3340
3628
  });
3341
3629
  obs.observe({ entryTypes: ["measure"] });
3342
3630
  let timer;
3343
- performance2.mark("tbTunnelStart");
3631
+ performance3.mark("tbTunnelStart");
3632
+ PerformanceTester.start(AUTOMATE_EVENTS.LOCAL_START);
3344
3633
  return Promise.race(
3345
3634
  [
3346
3635
  promisify2(this.browserstackLocal.start.bind(this.browserstackLocal))(opts),
@@ -3352,10 +3641,12 @@ var BrowserstackLauncherService = class {
3352
3641
  ]
3353
3642
  ).then(function(result) {
3354
3643
  clearTimeout(timer);
3355
- performance2.mark("tbTunnelEnd");
3356
- performance2.measure("bootTime", "tbTunnelStart", "tbTunnelEnd");
3644
+ performance3.mark("tbTunnelEnd");
3645
+ PerformanceTester.end(AUTOMATE_EVENTS.LOCAL_START);
3646
+ performance3.measure("bootTime", "tbTunnelStart", "tbTunnelEnd");
3357
3647
  return Promise.resolve(result);
3358
3648
  }, function(err) {
3649
+ PerformanceTester.end(AUTOMATE_EVENTS.LOCAL_START, false, err);
3359
3650
  clearTimeout(timer);
3360
3651
  return Promise.reject(err);
3361
3652
  });
@@ -3370,8 +3661,8 @@ Visit https://observability.browserstack.com/builds/${process.env[BROWSERSTACK_T
3370
3661
  `);
3371
3662
  }
3372
3663
  this.browserStackConfig.testObservability.buildStopped = true;
3664
+ await PerformanceTester.stopAndGenerate("performance-launcher.html");
3373
3665
  if (process.env[PERF_MEASUREMENT_ENV]) {
3374
- await PerformanceTester.stopAndGenerate("performance-launcher.html");
3375
3666
  PerformanceTester.calculateTimes(["launchTestSession", "stopBuildUpstream"]);
3376
3667
  if (!process.env.START_TIME) {
3377
3668
  return;
@@ -3379,6 +3670,7 @@ Visit https://observability.browserstack.com/builds/${process.env[BROWSERSTACK_T
3379
3670
  const duration = (/* @__PURE__ */ new Date()).getTime() - new Date(process.env.START_TIME).getTime();
3380
3671
  BStackLogger.info(`Total duration is ${duration / 1e3} s`);
3381
3672
  }
3673
+ BStackLogger.info(`BrowserStack service run ended for id: ${this.browserStackConfig?.sdkRunID} testhub id: ${testOpsConfig_default.getInstance()?.buildHashedId}`);
3382
3674
  await sendFinish(this.browserStackConfig);
3383
3675
  try {
3384
3676
  await this._uploadServiceLogs();
@@ -3397,6 +3689,7 @@ Visit https://observability.browserstack.com/builds/${process.env[BROWSERSTACK_T
3397
3689
  return process.kill(this.browserstackLocal.pid);
3398
3690
  }
3399
3691
  let timer;
3692
+ PerformanceTester.start(AUTOMATE_EVENTS.LOCAL_STOP);
3400
3693
  return Promise.race(
3401
3694
  [
3402
3695
  new Promise((resolve, reject) => {
@@ -3415,9 +3708,11 @@ Visit https://observability.browserstack.com/builds/${process.env[BROWSERSTACK_T
3415
3708
  })
3416
3709
  ]
3417
3710
  ).then(function(result) {
3711
+ PerformanceTester.end(AUTOMATE_EVENTS.LOCAL_STOP);
3418
3712
  clearTimeout(timer);
3419
3713
  return Promise.resolve(result);
3420
3714
  }, function(err) {
3715
+ PerformanceTester.end(AUTOMATE_EVENTS.LOCAL_STOP, false, err);
3421
3716
  clearTimeout(timer);
3422
3717
  return Promise.reject(err);
3423
3718
  });
@@ -3464,7 +3759,7 @@ Visit https://observability.browserstack.com/builds/${process.env[BROWSERSTACK_T
3464
3759
  BStackLogger.info(`uploading app ${app.app} ${app.customId ? `and custom_id: ${app.customId}` : ""} to browserstack`);
3465
3760
  const form = new FormData();
3466
3761
  if (app.app) {
3467
- const fileName = path11.basename(app.app);
3762
+ const fileName = path12.basename(app.app);
3468
3763
  const fileBlob = new Blob([await readFile(app.app)]);
3469
3764
  form.append("file", fileBlob, fileName);
3470
3765
  }
@@ -3761,12 +4056,12 @@ Visit https://observability.browserstack.com/builds/${process.env[BROWSERSTACK_T
3761
4056
  * else returns corresponding value in json file (e.g. { "wdio-build": { "identifier" : 2 } } => 2 in this case)
3762
4057
  */
3763
4058
  _getLocalBuildNumber() {
3764
- const browserstackFolderPath = path11.join(os5.homedir(), ".browserstack");
4059
+ const browserstackFolderPath = path12.join(os5.homedir(), ".browserstack");
3765
4060
  try {
3766
4061
  if (!fs11.existsSync(browserstackFolderPath)) {
3767
4062
  fs11.mkdirSync(browserstackFolderPath);
3768
4063
  }
3769
- const filePath = path11.join(browserstackFolderPath, ".build-name-cache.json");
4064
+ const filePath = path12.join(browserstackFolderPath, ".build-name-cache.json");
3770
4065
  if (!fs11.existsSync(filePath)) {
3771
4066
  fs11.appendFileSync(filePath, JSON.stringify({}));
3772
4067
  }
@@ -3797,18 +4092,30 @@ Visit https://observability.browserstack.com/builds/${process.env[BROWSERSTACK_T
3797
4092
  if (process.env[BROWSERSTACK_TESTHUB_UUID]) {
3798
4093
  return process.env[BROWSERSTACK_TESTHUB_UUID];
3799
4094
  }
3800
- const uuid = uuidv4();
4095
+ const uuid = this.browserStackConfig?.sdkRunID;
3801
4096
  BStackLogger.logToFile(`If facing any issues, please contact BrowserStack support with the Build Run Id - ${uuid}`, "info");
3802
4097
  return uuid;
3803
4098
  }
3804
4099
  };
4100
+ __decorateClass([
4101
+ PerformanceTester.Measure(EVENTS.SDK_SETUP)
4102
+ ], BrowserstackLauncherService.prototype, "onWorkerStart", 1);
4103
+ __decorateClass([
4104
+ PerformanceTester.Measure(EVENTS.SDK_PRE_TEST)
4105
+ ], BrowserstackLauncherService.prototype, "onPrepare", 1);
4106
+ __decorateClass([
4107
+ PerformanceTester.Measure(EVENTS.SDK_CLEANUP)
4108
+ ], BrowserstackLauncherService.prototype, "onComplete", 1);
4109
+ __decorateClass([
4110
+ PerformanceTester.Measure(APP_AUTOMATE_EVENTS.APP_UPLOAD)
4111
+ ], BrowserstackLauncherService.prototype, "_uploadApp", 1);
3805
4112
 
3806
4113
  // src/insights-handler.ts
3807
- import path13 from "node:path";
4114
+ import path14 from "node:path";
3808
4115
  import { v4 as uuidv43 } from "uuid";
3809
4116
 
3810
4117
  // src/reporter.ts
3811
- import path12 from "node:path";
4118
+ import path13 from "node:path";
3812
4119
  import WDIOReporter from "@wdio/reporter";
3813
4120
  import * as url2 from "node:url";
3814
4121
  import { v4 as uuidv42 } from "uuid";
@@ -4362,9 +4669,9 @@ var _TestReporter = class __TestReporter extends WDIOReporter {
4362
4669
  scope,
4363
4670
  scopes,
4364
4671
  identifier,
4365
- file_name: suiteFileName ? path12.relative(process.cwd(), suiteFileName) : void 0,
4366
- location: suiteFileName ? path12.relative(process.cwd(), suiteFileName) : void 0,
4367
- vc_filepath: this._gitConfigPath && suiteFileName ? path12.relative(this._gitConfigPath, suiteFileName) : void 0,
4672
+ file_name: suiteFileName ? path13.relative(process.cwd(), suiteFileName) : void 0,
4673
+ location: suiteFileName ? path13.relative(process.cwd(), suiteFileName) : void 0,
4674
+ vc_filepath: this._gitConfigPath && suiteFileName ? path13.relative(this._gitConfigPath, suiteFileName) : void 0,
4368
4675
  started_at: testStats.start && testStats.start.toISOString(),
4369
4676
  finished_at: testStats.end && testStats.end.toISOString(),
4370
4677
  framework,
@@ -4671,9 +4978,9 @@ var _InsightsHandler = class {
4671
4978
  test_run_id: hookData.testRunId,
4672
4979
  scope: feature?.name,
4673
4980
  scopes: [feature?.name || ""],
4674
- file_name: uri ? path13.relative(process.cwd(), uri) : void 0,
4675
- location: uri ? path13.relative(process.cwd(), uri) : void 0,
4676
- vc_filepath: this._gitConfigPath && uri ? path13.relative(this._gitConfigPath, uri) : void 0,
4981
+ file_name: uri ? path14.relative(process.cwd(), uri) : void 0,
4982
+ location: uri ? path14.relative(process.cwd(), uri) : void 0,
4983
+ vc_filepath: this._gitConfigPath && uri ? path14.relative(this._gitConfigPath, uri) : void 0,
4677
4984
  result: "pending",
4678
4985
  framework: this._framework
4679
4986
  };
@@ -4938,9 +5245,9 @@ var _InsightsHandler = class {
4938
5245
  scope: fullTitle,
4939
5246
  scopes: this.getHierarchy(test),
4940
5247
  identifier: fullTitle,
4941
- file_name: filename ? path13.relative(process.cwd(), filename) : void 0,
4942
- location: filename ? path13.relative(process.cwd(), filename) : void 0,
4943
- vc_filepath: this._gitConfigPath && filename ? path13.relative(this._gitConfigPath, filename) : void 0,
5248
+ file_name: filename ? path14.relative(process.cwd(), filename) : void 0,
5249
+ location: filename ? path14.relative(process.cwd(), filename) : void 0,
5250
+ vc_filepath: this._gitConfigPath && filename ? path14.relative(this._gitConfigPath, filename) : void 0,
4944
5251
  started_at: testMetaData.startedAt,
4945
5252
  finished_at: testMetaData.finishedAt,
4946
5253
  result: "pending",
@@ -5042,9 +5349,9 @@ var _InsightsHandler = class {
5042
5349
  scope: fullNameWithExamples,
5043
5350
  scopes: [feature?.name || ""],
5044
5351
  identifier: scenario?.name,
5045
- file_name: feature && feature.path ? path13.relative(process.cwd(), feature.path) : void 0,
5046
- location: feature && feature.path ? path13.relative(process.cwd(), feature.path) : void 0,
5047
- vc_filepath: this._gitConfigPath && feature?.path ? path13.relative(this._gitConfigPath, feature?.path) : void 0,
5352
+ file_name: feature && feature.path ? path14.relative(process.cwd(), feature.path) : void 0,
5353
+ location: feature && feature.path ? path14.relative(process.cwd(), feature.path) : void 0,
5354
+ vc_filepath: this._gitConfigPath && feature?.path ? path14.relative(this._gitConfigPath, feature?.path) : void 0,
5048
5355
  framework: this._framework,
5049
5356
  result: "pending",
5050
5357
  meta: {
@@ -5140,7 +5447,7 @@ var InsightsHandler = o11yClassErrorHandler(_InsightsHandler);
5140
5447
  var insights_handler_default = InsightsHandler;
5141
5448
 
5142
5449
  // src/accessibility-handler.ts
5143
- import util3 from "node:util";
5450
+ import util4 from "node:util";
5144
5451
  var _AccessibilityHandler = class {
5145
5452
  constructor(_browser, _capabilities, isAppAutomate, _framework, _accessibilityAutomation, _accessibilityOpts) {
5146
5453
  this._browser = _browser;
@@ -5362,16 +5669,20 @@ var _AccessibilityHandler = class {
5362
5669
  }
5363
5670
  async sendTestStopEvent(browser, dataForExtension) {
5364
5671
  BStackLogger.debug("Performing scan before saving results");
5365
- await performA11yScan(this.isAppAutomate, browser, true, true);
5672
+ await PerformanceTester.measureWrapper(A11Y_EVENTS.PERFORM_SCAN, async () => {
5673
+ await performA11yScan(this.isAppAutomate, browser, true, true);
5674
+ }, { command: "afterTest" })();
5366
5675
  if (isAppAccessibilityAutomationSession(this._accessibility, this.isAppAutomate)) {
5367
5676
  return;
5368
5677
  }
5369
- if (accessibility_scripts_default.saveTestResults) {
5370
- const results = await executeAccessibilityScript(browser, accessibility_scripts_default.saveTestResults, dataForExtension);
5371
- BStackLogger.debug(util3.format(results));
5372
- } else {
5373
- BStackLogger.error("saveTestResults script is null or undefined");
5374
- }
5678
+ await PerformanceTester.measureWrapper(A11Y_EVENTS.SAVE_RESULTS, async () => {
5679
+ if (accessibility_scripts_default.saveTestResults) {
5680
+ const results = await executeAccessibilityScript(browser, accessibility_scripts_default.saveTestResults, dataForExtension);
5681
+ BStackLogger.debug(util4.format(results));
5682
+ } else {
5683
+ BStackLogger.error("saveTestResults script is null or undefined");
5684
+ }
5685
+ })();
5375
5686
  }
5376
5687
  getIdentifier(test) {
5377
5688
  if ("pickle" in test) {
@@ -5479,7 +5790,7 @@ if (percySnapshot) {
5479
5790
  };
5480
5791
  }
5481
5792
  var snapshot = snapshotHandler;
5482
- var screenshotHelper = (type2, driverOrName, nameOrOptions, options) => {
5793
+ var screenshotHelper = (type3, driverOrName, nameOrOptions, options) => {
5483
5794
  let { name, uuid } = insights_handler_default.currentTest;
5484
5795
  if (isUndefined(name)) {
5485
5796
  ({ name, uuid } = reporter_default.currentTest);
@@ -5499,7 +5810,7 @@ var screenshotHelper = (type2, driverOrName, nameOrOptions, options) => {
5499
5810
  testCase: name || ""
5500
5811
  };
5501
5812
  }
5502
- if (type2 === "app") {
5813
+ if (type3 === "app") {
5503
5814
  return percyAppScreenshot(driverOrName, nameOrOptions, options);
5504
5815
  }
5505
5816
  return percySnapshot.percyScreenshot(driverOrName, nameOrOptions, options);
@@ -5554,6 +5865,7 @@ var _PercyHandler = class {
5554
5865
  });
5555
5866
  }
5556
5867
  async percyAutoCapture(eventName, sessionName) {
5868
+ PerformanceTester.start(PERCY_EVENTS.AUTO_CAPTURE);
5557
5869
  try {
5558
5870
  if (eventName) {
5559
5871
  if (!sessionName) {
@@ -5566,8 +5878,10 @@ var _PercyHandler = class {
5566
5878
  } catch (err) {
5567
5879
  this._percyScreenshotCounter -= 1;
5568
5880
  this._percyCaptureMap?.decrement(sessionName ? sessionName : this._sessionName, eventName);
5881
+ PerformanceTester.end(PERCY_EVENTS.AUTO_CAPTURE, false, err, { eventName, sessionName });
5569
5882
  PercyLogger.error(`Error while trying to auto capture Percy screenshot ${err}`);
5570
5883
  }
5884
+ PerformanceTester.end(PERCY_EVENTS.AUTO_CAPTURE, true, null, { eventName, sessionName });
5571
5885
  }
5572
5886
  async before() {
5573
5887
  this._percyCaptureMap = new PercyCaptureMap_default();
@@ -5665,11 +5979,9 @@ var BrowserstackService = class {
5665
5979
  this._percy = isTrue(process.env.BROWSERSTACK_PERCY);
5666
5980
  this._percyCaptureMode = process.env.BROWSERSTACK_PERCY_CAPTURE_MODE;
5667
5981
  this._turboScale = this._options.turboScale;
5982
+ PerformanceTester.startMonitoring("performance-report-service.csv");
5668
5983
  if (shouldProcessEventForTesthub("")) {
5669
5984
  this._config.reporters?.push(reporter_default);
5670
- if (process.env[PERF_MEASUREMENT_ENV]) {
5671
- PerformanceTester.startMonitoring("performance-report-service.csv");
5672
- }
5673
5985
  }
5674
5986
  if (process.env.BROWSERSTACK_TURBOSCALE) {
5675
5987
  this._turboScale = process.env.BROWSERSTACK_TURBOSCALE === "true";
@@ -5722,6 +6034,7 @@ var BrowserstackService = class {
5722
6034
  }
5723
6035
  async before(caps, specs, browser) {
5724
6036
  this._browser = browser ? browser : globalThis.browser;
6037
+ PerformanceTester.browser = this._browser;
5725
6038
  if (!isBrowserstackSession(this._browser)) {
5726
6039
  try {
5727
6040
  await ai_handler_default.selfHeal(this._options, caps, this._browser);
@@ -5738,6 +6051,7 @@ var BrowserstackService = class {
5738
6051
  this._sessionBaseUrl = "https://api.browserstack.com/automate-turboscale/v1/sessions";
5739
6052
  }
5740
6053
  this._scenariosThatRan = [];
6054
+ PerformanceTester.scenarioThatRan = this._scenariosThatRan;
5741
6055
  if (this._browser) {
5742
6056
  try {
5743
6057
  const sessionId = this._browser.sessionId;
@@ -5810,13 +6124,6 @@ var BrowserstackService = class {
5810
6124
  }
5811
6125
  return await this._printSessionURL();
5812
6126
  }
5813
- /**
5814
- * Set the default job name at the suite level to make sure we account
5815
- * for the cases where there is a long running `before` function for a
5816
- * suite or one that can fail.
5817
- * Don't do this for Jasmine because `suite.title` is `Jasmine__TopLevel__Suite`
5818
- * and `suite.fullTitle` is `undefined`, so no alternative to use for the job name.
5819
- */
5820
6127
  async beforeSuite(suite) {
5821
6128
  this._suiteTitle = suite.title;
5822
6129
  this._insightsHandler?.setSuiteFile(suite.file);
@@ -5865,19 +6172,21 @@ var BrowserstackService = class {
5865
6172
  if (preferScenarioName && this._scenariosThatRan.length === 1) {
5866
6173
  this._fullTitle = this._scenariosThatRan.pop();
5867
6174
  }
5868
- if (setSessionStatus) {
5869
- const hasReasons = this._failReasons.length > 0;
5870
- await this._updateJob({
5871
- status: result === 0 && this._specsRan ? "passed" : "failed",
5872
- ...setSessionName ? { name: this._fullTitle } : {},
5873
- ...result === 0 && this._specsRan ? {} : hasReasons ? { reason: this._failReasons.join("\n") } : {}
5874
- });
5875
- }
6175
+ await PerformanceTester.measureWrapper(AUTOMATE_EVENTS.SESSION_STATUS, async () => {
6176
+ if (setSessionStatus) {
6177
+ const hasReasons = this._failReasons.length > 0;
6178
+ await this._updateJob({
6179
+ status: result === 0 && this._specsRan ? "passed" : "failed",
6180
+ ...setSessionName ? { name: this._fullTitle } : {},
6181
+ ...result === 0 && this._specsRan ? {} : hasReasons ? { reason: this._failReasons.join("\n") } : {}
6182
+ });
6183
+ }
6184
+ })();
5876
6185
  await listener_default.getInstance().onWorkerEnd();
5877
6186
  await this._percyHandler?.teardown();
5878
6187
  this.saveWorkerData();
6188
+ await PerformanceTester.stopAndGenerate("performance-service.html");
5879
6189
  if (process.env[PERF_MEASUREMENT_ENV]) {
5880
- await PerformanceTester.stopAndGenerate("performance-service.html");
5881
6190
  PerformanceTester.calculateTimes([
5882
6191
  "onRunnerStart",
5883
6192
  "onSuiteStart",
@@ -5896,19 +6205,12 @@ var BrowserstackService = class {
5896
6205
  ]);
5897
6206
  }
5898
6207
  }
5899
- /**
5900
- * For CucumberJS
5901
- */
5902
6208
  async beforeFeature(uri, feature) {
5903
6209
  this._suiteTitle = feature.name;
5904
6210
  await this._setSessionName(feature.name);
5905
6211
  await this._setAnnotation(`Feature: ${feature.name}`);
5906
6212
  await this._insightsHandler?.beforeFeature(uri, feature);
5907
6213
  }
5908
- /**
5909
- * Runs before a Cucumber Scenario.
5910
- * @param world world object containing information on pickle and test step
5911
- */
5912
6214
  async beforeScenario(world) {
5913
6215
  this._currentTest = world;
5914
6216
  await this._accessibilityHandler?.beforeScenario(world);
@@ -6102,6 +6404,51 @@ var BrowserstackService = class {
6102
6404
  });
6103
6405
  }
6104
6406
  };
6407
+ __decorateClass([
6408
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "beforeSession" })
6409
+ ], BrowserstackService.prototype, "beforeSession", 1);
6410
+ __decorateClass([
6411
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "before" })
6412
+ ], BrowserstackService.prototype, "before", 1);
6413
+ __decorateClass([
6414
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "beforeSuite" })
6415
+ ], BrowserstackService.prototype, "beforeSuite", 1);
6416
+ __decorateClass([
6417
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "beforeHook" })
6418
+ ], BrowserstackService.prototype, "beforeHook", 1);
6419
+ __decorateClass([
6420
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "afterHook" })
6421
+ ], BrowserstackService.prototype, "afterHook", 1);
6422
+ __decorateClass([
6423
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "beforeTest" })
6424
+ ], BrowserstackService.prototype, "beforeTest", 1);
6425
+ __decorateClass([
6426
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "afterTest" })
6427
+ ], BrowserstackService.prototype, "afterTest", 1);
6428
+ __decorateClass([
6429
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "after" })
6430
+ ], BrowserstackService.prototype, "after", 1);
6431
+ __decorateClass([
6432
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "beforeFeature" })
6433
+ ], BrowserstackService.prototype, "beforeFeature", 1);
6434
+ __decorateClass([
6435
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "beforeScenario" })
6436
+ ], BrowserstackService.prototype, "beforeScenario", 1);
6437
+ __decorateClass([
6438
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "afterScenario" })
6439
+ ], BrowserstackService.prototype, "afterScenario", 1);
6440
+ __decorateClass([
6441
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "beforeStep" })
6442
+ ], BrowserstackService.prototype, "beforeStep", 1);
6443
+ __decorateClass([
6444
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "afterStep" })
6445
+ ], BrowserstackService.prototype, "afterStep", 1);
6446
+ __decorateClass([
6447
+ PerformanceTester.Measure(EVENTS.SDK_HOOK, { hookType: "onReload" })
6448
+ ], BrowserstackService.prototype, "onReload", 1);
6449
+ __decorateClass([
6450
+ PerformanceTester.Measure(AUTOMATE_EVENTS.PRINT_BUILDLINK)
6451
+ ], BrowserstackService.prototype, "_printSessionURL", 1);
6105
6452
 
6106
6453
  // src/logReportingAPI.ts
6107
6454
  import Transport2 from "winston-transport";