@wdio/browserstack-service 8.32.4 → 8.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/build/bstackLogger.d.ts +2 -1
  2. package/build/bstackLogger.d.ts.map +1 -1
  3. package/build/bstackLogger.js +6 -3
  4. package/build/cleanup.d.ts +5 -1
  5. package/build/cleanup.d.ts.map +1 -1
  6. package/build/cleanup.js +72 -7
  7. package/build/config.d.ts +23 -0
  8. package/build/config.d.ts.map +1 -0
  9. package/build/config.js +39 -0
  10. package/build/constants.d.ts +14 -0
  11. package/build/constants.d.ts.map +1 -1
  12. package/build/constants.js +22 -0
  13. package/build/crash-reporter.js +2 -2
  14. package/build/data-store.d.ts +4 -0
  15. package/build/data-store.d.ts.map +1 -0
  16. package/build/data-store.js +41 -0
  17. package/build/exitHandler.d.ts +4 -0
  18. package/build/exitHandler.d.ts.map +1 -0
  19. package/build/exitHandler.js +32 -0
  20. package/build/insights-handler.d.ts +5 -8
  21. package/build/insights-handler.d.ts.map +1 -1
  22. package/build/insights-handler.js +40 -93
  23. package/build/instrumentation/funnelInstrumentation.d.ts +6 -0
  24. package/build/instrumentation/funnelInstrumentation.d.ts.map +1 -0
  25. package/build/instrumentation/funnelInstrumentation.js +119 -0
  26. package/build/launcher.d.ts +1 -1
  27. package/build/launcher.d.ts.map +1 -1
  28. package/build/launcher.js +22 -13
  29. package/build/reporter.d.ts +3 -3
  30. package/build/reporter.d.ts.map +1 -1
  31. package/build/reporter.js +11 -27
  32. package/build/request-handler.d.ts +5 -13
  33. package/build/request-handler.d.ts.map +1 -1
  34. package/build/request-handler.js +30 -48
  35. package/build/service.d.ts +1 -0
  36. package/build/service.d.ts.map +1 -1
  37. package/build/service.js +13 -5
  38. package/build/testOps/featureStats.d.ts +45 -0
  39. package/build/testOps/featureStats.d.ts.map +1 -0
  40. package/build/testOps/featureStats.js +116 -0
  41. package/build/testOps/featureUsage.d.ts +22 -0
  42. package/build/testOps/featureUsage.d.ts.map +1 -0
  43. package/build/testOps/featureUsage.js +47 -0
  44. package/build/testOps/listener.d.ts +33 -0
  45. package/build/testOps/listener.d.ts.map +1 -0
  46. package/build/testOps/listener.js +222 -0
  47. package/build/testOps/requestUtils.d.ts +4 -0
  48. package/build/testOps/requestUtils.d.ts.map +1 -0
  49. package/build/testOps/requestUtils.js +39 -0
  50. package/build/testOps/testOpsConfig.d.ts +11 -0
  51. package/build/testOps/testOpsConfig.d.ts.map +1 -0
  52. package/build/testOps/testOpsConfig.js +19 -0
  53. package/build/testOps/usageStats.d.ts +404 -0
  54. package/build/testOps/usageStats.d.ts.map +1 -0
  55. package/build/testOps/usageStats.js +114 -0
  56. package/build/types.d.ts +33 -7
  57. package/build/types.d.ts.map +1 -1
  58. package/build/util.d.ts +3 -7
  59. package/build/util.d.ts.map +1 -1
  60. package/build/util.js +57 -77
  61. package/package.json +4 -4
package/build/util.js CHANGED
@@ -6,24 +6,20 @@ import http from 'node:http';
6
6
  import https from 'node:https';
7
7
  import path from 'node:path';
8
8
  import util from 'node:util';
9
- import { spawn } from 'node:child_process';
10
- import { fileURLToPath } from 'node:url';
11
9
  import got, { HTTPError } from 'got';
12
10
  import gitRepoInfo from 'git-repo-info';
13
11
  import gitconfig from 'gitconfiglocal';
14
12
  import { FormData } from 'formdata-node';
15
13
  import logPatcher from './logPatcher.js';
16
14
  import PerformanceTester from './performance-tester.js';
17
- import { ACCESSIBILITY_API_URL, BROWSER_DESCRIPTION, DATA_ENDPOINT, DATA_EVENT_ENDPOINT, DATA_SCREENSHOT_ENDPOINT, UPLOAD_LOGS_ADDRESS, UPLOAD_LOGS_ENDPOINT, consoleHolder } from './constants.js';
18
- import RequestQueueHandler from './request-handler.js';
15
+ import { ACCESSIBILITY_API_URL, BROWSER_DESCRIPTION, DATA_ENDPOINT, UPLOAD_LOGS_ADDRESS, UPLOAD_LOGS_ENDPOINT, consoleHolder, TESTOPS_SCREENSHOT_ENV, TESTOPS_BUILD_ID_ENV, PERF_MEASUREMENT_ENV, RERUN_ENV, TESTOPS_BUILD_COMPLETED_ENV, TESTOPS_JWT_ENV } from './constants.js';
19
16
  import CrashReporter from './crash-reporter.js';
20
17
  import { accessibilityResults, accessibilityResultsSummary } from './scripts/test-event-scripts.js';
21
18
  import { BStackLogger } from './bstackLogger.js';
22
19
  import { FileStream } from './fileStream.js';
23
- import BrowserstackLauncherService from './launcher.js';
20
+ import UsageStats from './testOps/usageStats.js';
21
+ import TestOpsConfig from './testOps/testOpsConfig.js';
24
22
  const pGitconfig = promisify(gitconfig);
25
- const __filename = fileURLToPath(import.meta.url);
26
- const __dirname = path.dirname(__filename);
27
23
  export const DEFAULT_REQUEST_CONFIG = {
28
24
  agent: {
29
25
  http: new http.Agent({ keepAlive: true }),
@@ -112,7 +108,7 @@ export function o11yErrorHandler(fn) {
112
108
  return function (...args) {
113
109
  try {
114
110
  let functionToHandle = fn;
115
- if (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT) {
111
+ if (process.env[PERF_MEASUREMENT_ENV]) {
116
112
  functionToHandle = PerformanceTester.getPerformance().timerify(functionToHandle);
117
113
  }
118
114
  const result = functionToHandle(...args);
@@ -191,7 +187,7 @@ export function o11yClassErrorHandler(errorClass) {
191
187
  writable: true,
192
188
  value: function (...args) {
193
189
  try {
194
- const result = (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT ? PerformanceTester.getPerformance().timerify(method) : method).call(this, ...args);
190
+ const result = (process.env[PERF_MEASUREMENT_ENV] ? PerformanceTester.getPerformance().timerify(method) : method).call(this, ...args);
195
191
  if (result instanceof Promise) {
196
192
  return result.catch(error => processError(error, method, args));
197
193
  }
@@ -207,6 +203,8 @@ export function o11yClassErrorHandler(errorClass) {
207
203
  return errorClass;
208
204
  }
209
205
  export const launchTestSession = o11yErrorHandler(async function launchTestSession(options, config, bsConfig) {
206
+ const launchBuildUsage = UsageStats.getInstance().launchBuildUsage;
207
+ launchBuildUsage.triggered();
210
208
  const data = {
211
209
  format: 'json',
212
210
  project_name: getObservabilityProject(options, bsConfig.projectName),
@@ -223,7 +221,7 @@ export const launchTestSession = o11yErrorHandler(async function launchTestSessi
223
221
  },
224
222
  ci_info: getCiInfo(),
225
223
  build_run_identifier: process.env.BROWSERSTACK_BUILD_RUN_IDENTIFIER,
226
- failed_tests_rerun: process.env.BROWSERSTACK_RERUN || false,
224
+ failed_tests_rerun: process.env[RERUN_ENV] || false,
227
225
  version_control: await getGitMetaData(),
228
226
  observability_version: {
229
227
  frameworkName: 'WebdriverIO-' + config.framework,
@@ -249,18 +247,21 @@ export const launchTestSession = o11yErrorHandler(async function launchTestSessi
249
247
  json: data
250
248
  }).json();
251
249
  BStackLogger.debug(`[Start_Build] Success response: ${JSON.stringify(response)}`);
252
- process.env.BS_TESTOPS_BUILD_COMPLETED = 'true';
250
+ process.env[TESTOPS_BUILD_COMPLETED_ENV] = 'true';
253
251
  if (response.jwt) {
254
- process.env.BS_TESTOPS_JWT = response.jwt;
252
+ launchBuildUsage.success();
253
+ process.env[TESTOPS_JWT_ENV] = response.jwt;
255
254
  }
256
255
  if (response.build_hashed_id) {
257
- process.env.BS_TESTOPS_BUILD_HASHED_ID = response.build_hashed_id;
256
+ process.env[TESTOPS_BUILD_ID_ENV] = response.build_hashed_id;
257
+ TestOpsConfig.getInstance().buildHashedId = response.build_hashed_id;
258
258
  }
259
259
  if (response.allow_screenshots) {
260
- process.env.BS_TESTOPS_ALLOW_SCREENSHOTS = response.allow_screenshots.toString();
260
+ process.env[TESTOPS_SCREENSHOT_ENV] = response.allow_screenshots.toString();
261
261
  }
262
262
  }
263
263
  catch (error) {
264
+ launchBuildUsage.failed(error);
264
265
  if (error instanceof HTTPError && error.response) {
265
266
  const errorMessageJson = error.response.body ? JSON.parse(error.response.body.toString()) : null;
266
267
  const errorMessage = errorMessageJson ? errorMessageJson.message : null, errorType = errorMessageJson ? errorMessageJson.errorType : null;
@@ -486,10 +487,18 @@ export const stopAccessibilityTestRun = errorHandler(async function stopAccessib
486
487
  }
487
488
  });
488
489
  export const stopBuildUpstream = o11yErrorHandler(async function stopBuildUpstream() {
489
- if (!process.env.BS_TESTOPS_BUILD_COMPLETED) {
490
- return;
490
+ const stopBuildUsage = UsageStats.getInstance().stopBuildUsage;
491
+ stopBuildUsage.triggered();
492
+ if (!process.env[TESTOPS_BUILD_COMPLETED_ENV]) {
493
+ stopBuildUsage.failed('Build is not completed yet');
494
+ return {
495
+ status: 'error',
496
+ message: 'Build is not completed yet'
497
+ };
491
498
  }
492
- if (!process.env.BS_TESTOPS_JWT) {
499
+ const jwtToken = process.env[TESTOPS_JWT_ENV];
500
+ if (!jwtToken) {
501
+ stopBuildUsage.failed('Token/buildID is undefined, build creation might have failed');
493
502
  BStackLogger.debug('[STOP_BUILD] Missing Authentication Token/ Build ID');
494
503
  return {
495
504
  status: 'error',
@@ -500,22 +509,24 @@ export const stopBuildUpstream = o11yErrorHandler(async function stopBuildUpstre
500
509
  'stop_time': (new Date()).toISOString()
501
510
  };
502
511
  try {
503
- const url = `${DATA_ENDPOINT}/api/v1/builds/${process.env.BS_TESTOPS_BUILD_HASHED_ID}/stop`;
512
+ const url = `${DATA_ENDPOINT}/api/v1/builds/${process.env[TESTOPS_BUILD_ID_ENV]}/stop`;
504
513
  const response = await got.put(url, {
505
514
  agent: DEFAULT_REQUEST_CONFIG.agent,
506
515
  headers: {
507
516
  ...DEFAULT_REQUEST_CONFIG.headers,
508
- 'Authorization': `Bearer ${process.env.BS_TESTOPS_JWT}`
517
+ 'Authorization': `Bearer ${jwtToken}`
509
518
  },
510
519
  json: data
511
520
  }).json();
512
521
  BStackLogger.debug(`[STOP_BUILD] Success response: ${JSON.stringify(response)}`);
522
+ stopBuildUsage.success();
513
523
  return {
514
524
  status: 'success',
515
525
  message: ''
516
526
  };
517
527
  }
518
528
  catch (error) {
529
+ stopBuildUsage.failed(error);
519
530
  BStackLogger.debug(`[STOP_BUILD] Failed. Error: ${error}`);
520
531
  return {
521
532
  status: 'error',
@@ -848,43 +859,6 @@ export function getLogTag(eventType) {
848
859
  }
849
860
  return 'undefined';
850
861
  }
851
- export async function uploadEventData(eventData, eventUrl = DATA_EVENT_ENDPOINT) {
852
- let logTag = 'BATCH_UPLOAD';
853
- if (!Array.isArray(eventData)) {
854
- logTag = getLogTag(eventData.event_type);
855
- }
856
- if (eventUrl === DATA_SCREENSHOT_ENDPOINT) {
857
- logTag = 'screenshot_upload';
858
- }
859
- if (!process.env.BS_TESTOPS_BUILD_COMPLETED) {
860
- return;
861
- }
862
- if (!process.env.BS_TESTOPS_JWT) {
863
- BStackLogger.debug(`[${logTag}] Missing Authentication Token/ Build ID`);
864
- return {
865
- status: 'error',
866
- message: 'Token/buildID is undefined, build creation might have failed'
867
- };
868
- }
869
- try {
870
- const url = `${DATA_ENDPOINT}/${eventUrl}`;
871
- RequestQueueHandler.getInstance().pendingUploads += 1;
872
- const data = await got.post(url, {
873
- agent: DEFAULT_REQUEST_CONFIG.agent,
874
- headers: {
875
- ...DEFAULT_REQUEST_CONFIG.headers,
876
- 'Authorization': `Bearer ${process.env.BS_TESTOPS_JWT}`
877
- },
878
- json: eventData
879
- }).json();
880
- BStackLogger.debug(`[${logTag}] Success response: ${JSON.stringify(data)}`);
881
- RequestQueueHandler.getInstance().pendingUploads -= 1;
882
- }
883
- catch (error) {
884
- BStackLogger.debug(`[${logTag}] Failed. Error: ${error}`);
885
- RequestQueueHandler.getInstance().pendingUploads -= 1;
886
- }
887
- }
888
862
  // get hierarchy for a particular test (called by reporter for skipped tests)
889
863
  export function getHierarchy(fullTitle) {
890
864
  if (!fullTitle) {
@@ -923,8 +897,12 @@ export function shouldAddServiceVersion(config, testObservability) {
923
897
  return true;
924
898
  }
925
899
  export async function batchAndPostEvents(eventUrl, kind, data) {
926
- if (!process.env.BS_TESTOPS_BUILD_COMPLETED || !process.env.BS_TESTOPS_JWT) {
927
- return;
900
+ if (!process.env[TESTOPS_BUILD_COMPLETED_ENV]) {
901
+ throw new Error('Build not completed yet');
902
+ }
903
+ const jwtToken = process.env[TESTOPS_JWT_ENV];
904
+ if (!jwtToken) {
905
+ throw new Error('Missing authentication Token');
928
906
  }
929
907
  try {
930
908
  const url = `${DATA_ENDPOINT}/${eventUrl}`;
@@ -932,7 +910,7 @@ export async function batchAndPostEvents(eventUrl, kind, data) {
932
910
  agent: DEFAULT_REQUEST_CONFIG.agent,
933
911
  headers: {
934
912
  ...DEFAULT_REQUEST_CONFIG.headers,
935
- 'Authorization': `Bearer ${process.env.BS_TESTOPS_JWT}`
913
+ 'Authorization': `Bearer ${jwtToken}`
936
914
  },
937
915
  json: data
938
916
  }).json();
@@ -940,6 +918,7 @@ export async function batchAndPostEvents(eventUrl, kind, data) {
940
918
  }
941
919
  catch (error) {
942
920
  BStackLogger.debug(`[${kind}] EXCEPTION IN ${kind} REQUEST TO TEST OBSERVABILITY : ${error}`);
921
+ throw new Error('Exception in request ' + error);
943
922
  }
944
923
  }
945
924
  export function getObservabilityUser(options, config) {
@@ -1008,6 +987,9 @@ export function isUndefined(value) {
1008
987
  export function isTrue(value) {
1009
988
  return (value + '').toLowerCase() === 'true';
1010
989
  }
990
+ export function isFalse(value) {
991
+ return (value + '').toLowerCase() === 'false';
992
+ }
1011
993
  export function frameworkSupportsHook(hook, framework) {
1012
994
  if (framework === 'mocha' && (hook === 'before' || hook === 'after' || hook === 'beforeEach' || hook === 'afterEach')) {
1013
995
  return true;
@@ -1042,15 +1024,6 @@ export function getFailureObject(error) {
1042
1024
  failure_type: message ? (message.toString().match(/AssertionError/) ? 'AssertionError' : 'UnhandledError') : null
1043
1025
  };
1044
1026
  }
1045
- export async function pushDataToQueue(data, requestQueueHandler = undefined) {
1046
- if (!requestQueueHandler) {
1047
- requestQueueHandler = RequestQueueHandler.getInstance();
1048
- }
1049
- const req = requestQueueHandler.add(data);
1050
- if (req.proceed && req.data) {
1051
- await uploadEventData(req.data, req.url);
1052
- }
1053
- }
1054
1027
  export const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms));
1055
1028
  export async function uploadLogs(user, key, clientBuildUuid) {
1056
1029
  if (!user || !key) {
@@ -1090,15 +1063,6 @@ export const ObjectsAreEqual = (object1, object2) => {
1090
1063
  }
1091
1064
  return true;
1092
1065
  };
1093
- export function setupExitHandlers() {
1094
- process.on('exit', (code) => {
1095
- if (!!process.env.BS_TESTOPS_JWT && !BrowserstackLauncherService._testOpsBuildStopped) {
1096
- const childProcess = spawn('node', [`${path.join(__dirname, 'cleanup.js')}`], { detached: true, stdio: 'inherit', env: { ...process.env } });
1097
- childProcess.unref();
1098
- process.exit(code);
1099
- }
1100
- });
1101
- }
1102
1066
  export const getPlatformVersion = o11yErrorHandler(function getPlatformVersion(caps) {
1103
1067
  if (!caps) {
1104
1068
  return undefined;
@@ -1115,3 +1079,19 @@ export const getPlatformVersion = o11yErrorHandler(function getPlatformVersion(c
1115
1079
  }
1116
1080
  return undefined;
1117
1081
  });
1082
+ export const isObjectEmpty = (objectName) => {
1083
+ return (objectName &&
1084
+ Object.keys(objectName).length === 0 &&
1085
+ objectName.constructor === Object);
1086
+ };
1087
+ export const getErrorString = (err) => {
1088
+ if (!err) {
1089
+ return undefined;
1090
+ }
1091
+ if (typeof err === 'string') {
1092
+ return err; // works, `e` narrowed to string
1093
+ }
1094
+ else if (err instanceof Error) {
1095
+ return err.message; // works, `e` narrowed to Error
1096
+ }
1097
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wdio/browserstack-service",
3
- "version": "8.32.4",
3
+ "version": "8.33.0",
4
4
  "description": "WebdriverIO service for better Browserstack integration",
5
5
  "author": "Adam Bjerstedt <abjerstedt@gmail.com>",
6
6
  "homepage": "https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-browserstack-service",
@@ -44,7 +44,7 @@
44
44
  "gitconfiglocal": "^2.1.0",
45
45
  "got": "^12.6.1",
46
46
  "uuid": "^9.0.0",
47
- "webdriverio": "8.32.4",
47
+ "webdriverio": "8.33.0",
48
48
  "winston-transport": "^4.5.0",
49
49
  "yauzl": "^3.0.0"
50
50
  },
@@ -53,10 +53,10 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@types/node": "^20.1.0",
56
- "@wdio/globals": "8.32.4"
56
+ "@wdio/globals": "8.33.0"
57
57
  },
58
58
  "publishConfig": {
59
59
  "access": "public"
60
60
  },
61
- "gitHead": "f8d2d051d1331f4c24521a3c3b0e830ff3e45282"
61
+ "gitHead": "b00f5062e9ca87d6b2d01b1e9fa66ab15d8636b4"
62
62
  }