@wdio/browserstack-service 7.30.3 → 7.32.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/util.js CHANGED
@@ -26,21 +26,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.sleep = exports.getObservabilityBuildTags = exports.getObservabilityBuild = exports.getObservabilityProject = exports.getObservabilityKey = exports.getObservabilityUser = exports.batchAndPostEvents = exports.shouldAddServiceVersion = exports.isScreenshotCommand = exports.getHookType = exports.getHierarchy = exports.uploadEventData = exports.getLogTag = exports.removeAnsiColors = exports.getScenarioExamples = exports.isBrowserstackSession = exports.getCloudProvider = exports.getUniqueIdentifierForCucumber = exports.getUniqueIdentifier = exports.getGitMetaData = exports.getCiInfo = exports.stopBuildUpstream = exports.launchTestSession = exports.getParentSuiteName = exports.isBrowserstackCapability = exports.getBrowserCapabilities = exports.getBrowserDescription = void 0;
29
+ exports.sleep = exports.frameworkSupportsHook = exports.getObservabilityBuildTags = exports.getObservabilityBuild = exports.getObservabilityProject = exports.getObservabilityKey = exports.getObservabilityUser = exports.batchAndPostEvents = exports.shouldAddServiceVersion = exports.isBStackSession = exports.isScreenshotCommand = exports.getHookType = exports.getHierarchy = exports.uploadEventData = exports.getLogTag = exports.removeAnsiColors = exports.getScenarioExamples = exports.isBrowserstackSession = exports.getCloudProvider = exports.getUniqueIdentifierForCucumber = exports.getUniqueIdentifier = exports.getGitMetaData = exports.getCiInfo = exports.stopBuildUpstream = exports.launchTestSession = exports.o11yClassErrorHandler = exports.o11yErrorHandler = exports.getParentSuiteName = exports.isBrowserstackCapability = exports.getBrowserCapabilities = exports.getBrowserDescription = exports.DEFAULT_REQUEST_CONFIG = void 0;
30
30
  const os_1 = require("os");
31
31
  const util_1 = require("util");
32
32
  const http_1 = __importDefault(require("http"));
33
33
  const https_1 = __importDefault(require("https"));
34
34
  const path_1 = __importDefault(require("path"));
35
+ const util_2 = __importDefault(require("util"));
35
36
  const logger_1 = __importDefault(require("@wdio/logger"));
36
37
  const got_1 = __importStar(require("got"));
37
38
  const git_repo_info_1 = __importDefault(require("git-repo-info"));
38
39
  const gitconfiglocal_1 = __importDefault(require("gitconfiglocal"));
40
+ const crash_reporter_1 = __importDefault(require("./crash-reporter"));
39
41
  const constants_1 = require("./constants");
40
42
  const request_handler_1 = __importDefault(require("./request-handler"));
43
+ const performance_tester_1 = __importDefault(require("./performance-tester"));
41
44
  const pGitconfig = (0, util_1.promisify)(gitconfiglocal_1.default);
42
45
  const log = (0, logger_1.default)('@wdio/browserstack-service');
43
- const DEFAULT_REQUEST_CONFIG = {
46
+ exports.DEFAULT_REQUEST_CONFIG = {
44
47
  agent: {
45
48
  http: new http_1.default.Agent({ keepAlive: true }),
46
49
  https: new https_1.default.Agent({ keepAlive: true }),
@@ -109,7 +112,66 @@ function getParentSuiteName(fullTitle, testSuiteTitle) {
109
112
  return parentSuiteName.trim();
110
113
  }
111
114
  exports.getParentSuiteName = getParentSuiteName;
112
- async function launchTestSession(options, config, bsConfig) {
115
+ function processError(error, fn, args) {
116
+ log.error(`Error in executing ${fn.name} with args ${args}: ${error}`);
117
+ let argsString;
118
+ try {
119
+ argsString = JSON.stringify(args);
120
+ }
121
+ catch (e) {
122
+ argsString = util_2.default.inspect(args, { depth: 2 });
123
+ }
124
+ crash_reporter_1.default.uploadCrashReport(`Error in executing ${fn.name} with args ${argsString} : ${error}`, error && error.stack);
125
+ }
126
+ function o11yErrorHandler(fn) {
127
+ return function (...args) {
128
+ try {
129
+ let functionToHandle = fn;
130
+ if (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT) {
131
+ functionToHandle = performance_tester_1.default.getPerformance().timerify(functionToHandle);
132
+ }
133
+ const result = functionToHandle(...args);
134
+ if (result instanceof Promise) {
135
+ return result.catch(error => processError(error, fn, args));
136
+ }
137
+ return result;
138
+ }
139
+ catch (error) {
140
+ processError(error, fn, args);
141
+ }
142
+ };
143
+ }
144
+ exports.o11yErrorHandler = o11yErrorHandler;
145
+ function o11yClassErrorHandler(errorClass) {
146
+ const prototype = errorClass.prototype;
147
+ if (Object.getOwnPropertyNames(prototype).length < 2) {
148
+ return errorClass;
149
+ }
150
+ Object.getOwnPropertyNames(prototype).forEach((methodName) => {
151
+ const method = prototype[methodName];
152
+ if (typeof method === 'function' && methodName !== 'constructor') {
153
+ // In order to preserve this context, need to define like this
154
+ Object.defineProperty(prototype, methodName, {
155
+ writable: true,
156
+ value: function (...args) {
157
+ try {
158
+ const result = (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT ? performance_tester_1.default.getPerformance().timerify(method) : method).call(this, ...args);
159
+ if (result instanceof Promise) {
160
+ return result.catch(error => processError(error, method, args));
161
+ }
162
+ return result;
163
+ }
164
+ catch (err) {
165
+ processError(err, method, args);
166
+ }
167
+ }
168
+ });
169
+ }
170
+ });
171
+ return errorClass;
172
+ }
173
+ exports.o11yClassErrorHandler = o11yClassErrorHandler;
174
+ exports.launchTestSession = o11yErrorHandler(async function launchTestSession(options, config, bsConfig) {
113
175
  const data = {
114
176
  format: 'json',
115
177
  project_name: getObservabilityProject(options, bsConfig.projectName),
@@ -131,12 +193,22 @@ async function launchTestSession(options, config, bsConfig) {
131
193
  observability_version: {
132
194
  frameworkName: 'WebdriverIO-' + config.framework,
133
195
  sdkVersion: bsConfig.bstackServiceVersion
134
- }
196
+ },
197
+ config: {}
135
198
  };
199
+ try {
200
+ if (Object.keys(crash_reporter_1.default.userConfigForReporting).length === 0) {
201
+ crash_reporter_1.default.userConfigForReporting = process.env.USER_CONFIG_FOR_REPORTING !== undefined ? JSON.parse(process.env.USER_CONFIG_FOR_REPORTING) : {};
202
+ }
203
+ }
204
+ catch (error) {
205
+ log.error(`[Crash_Report_Upload] Failed to parse user config while sending build start event due to ${error}`);
206
+ }
207
+ data.config = crash_reporter_1.default.userConfigForReporting;
136
208
  try {
137
209
  const url = `${constants_1.DATA_ENDPOINT}/api/v1/builds`;
138
210
  const response = await got_1.default.post(url, {
139
- ...DEFAULT_REQUEST_CONFIG,
211
+ ...exports.DEFAULT_REQUEST_CONFIG,
140
212
  username: getObservabilityUser(options, config),
141
213
  password: getObservabilityKey(options, config),
142
214
  json: data
@@ -172,9 +244,8 @@ async function launchTestSession(options, config, bsConfig) {
172
244
  log.error(`Data upload to BrowserStack Test Observability failed due to ${error}`);
173
245
  }
174
246
  }
175
- }
176
- exports.launchTestSession = launchTestSession;
177
- async function stopBuildUpstream() {
247
+ });
248
+ exports.stopBuildUpstream = o11yErrorHandler(async function stopBuildUpstream() {
178
249
  if (!process.env.BS_TESTOPS_BUILD_COMPLETED) {
179
250
  return;
180
251
  }
@@ -191,9 +262,9 @@ async function stopBuildUpstream() {
191
262
  try {
192
263
  const url = `${constants_1.DATA_ENDPOINT}/api/v1/builds/${process.env.BS_TESTOPS_BUILD_HASHED_ID}/stop`;
193
264
  const response = await got_1.default.put(url, {
194
- agent: DEFAULT_REQUEST_CONFIG.agent,
265
+ agent: exports.DEFAULT_REQUEST_CONFIG.agent,
195
266
  headers: {
196
- ...DEFAULT_REQUEST_CONFIG.headers,
267
+ ...exports.DEFAULT_REQUEST_CONFIG.headers,
197
268
  'Authorization': `Bearer ${process.env.BS_TESTOPS_JWT}`
198
269
  },
199
270
  json: data
@@ -211,8 +282,7 @@ async function stopBuildUpstream() {
211
282
  message: error.message
212
283
  };
213
284
  }
214
- }
215
- exports.stopBuildUpstream = stopBuildUpstream;
285
+ });
216
286
  function getCiInfo() {
217
287
  var env = process.env;
218
288
  // Jenkins
@@ -335,8 +405,17 @@ async function getGitMetaData() {
335
405
  };
336
406
  }
337
407
  exports.getGitMetaData = getGitMetaData;
338
- function getUniqueIdentifier(test) {
339
- return `${test.parent} - ${test.title}`;
408
+ function getUniqueIdentifier(test, framework) {
409
+ if (framework === 'jasmine') {
410
+ return test.fullName;
411
+ }
412
+ let parentTitle = test.parent;
413
+ // Sometimes parent will be an object instead of a string
414
+ if (typeof test.parent === 'object') {
415
+ // @ts-ignore
416
+ parentTitle = parentTitle.title;
417
+ }
418
+ return `${parentTitle} - ${test.title}`;
340
419
  }
341
420
  exports.getUniqueIdentifier = getUniqueIdentifier;
342
421
  function getUniqueIdentifierForCucumber(world) {
@@ -435,9 +514,9 @@ async function uploadEventData(eventData, eventUrl = constants_1.DATA_EVENT_ENDP
435
514
  const url = `${constants_1.DATA_ENDPOINT}/${eventUrl}`;
436
515
  request_handler_1.default.getInstance().pendingUploads += 1;
437
516
  const data = await got_1.default.post(url, {
438
- agent: DEFAULT_REQUEST_CONFIG.agent,
517
+ agent: exports.DEFAULT_REQUEST_CONFIG.agent,
439
518
  headers: {
440
- ...DEFAULT_REQUEST_CONFIG.headers,
519
+ ...exports.DEFAULT_REQUEST_CONFIG.headers,
441
520
  'Authorization': `Bearer ${process.env.BS_TESTOPS_JWT}`
442
521
  },
443
522
  json: eventData
@@ -459,16 +538,16 @@ function getHierarchy(fullTitle) {
459
538
  }
460
539
  exports.getHierarchy = getHierarchy;
461
540
  function getHookType(hookName) {
462
- if (hookName.includes('before each')) {
541
+ if (hookName.startsWith('"before each"')) {
463
542
  return 'BEFORE_EACH';
464
543
  }
465
- else if (hookName.includes('before all')) {
544
+ else if (hookName.startsWith('"before all"')) {
466
545
  return 'BEFORE_ALL';
467
546
  }
468
- else if (hookName.includes('after each')) {
547
+ else if (hookName.startsWith('"after each"')) {
469
548
  return 'AFTER_EACH';
470
549
  }
471
- else if (hookName.includes('after all')) {
550
+ else if (hookName.startsWith('"after all"')) {
472
551
  return 'AFTER_ALL';
473
552
  }
474
553
  return 'unknown';
@@ -478,6 +557,13 @@ function isScreenshotCommand(args) {
478
557
  return args.endpoint && args.endpoint.includes('/screenshot');
479
558
  }
480
559
  exports.isScreenshotCommand = isScreenshotCommand;
560
+ function isBStackSession(config) {
561
+ if (typeof config.user === 'string' && typeof config.key === 'string' && config.key.length === 20) {
562
+ return true;
563
+ }
564
+ return false;
565
+ }
566
+ exports.isBStackSession = isBStackSession;
481
567
  function shouldAddServiceVersion(config, testObservability) {
482
568
  if (config.services && config.services.toString().includes('chromedriver') && testObservability != false) {
483
569
  return false;
@@ -492,9 +578,9 @@ async function batchAndPostEvents(eventUrl, kind, data) {
492
578
  try {
493
579
  const url = `${constants_1.DATA_ENDPOINT}/${eventUrl}`;
494
580
  const response = await got_1.default.post(url, {
495
- agent: DEFAULT_REQUEST_CONFIG.agent,
581
+ agent: exports.DEFAULT_REQUEST_CONFIG.agent,
496
582
  headers: {
497
- ...DEFAULT_REQUEST_CONFIG.headers,
583
+ ...exports.DEFAULT_REQUEST_CONFIG.headers,
498
584
  'Authorization': `Bearer ${process.env.BS_TESTOPS_JWT}`
499
585
  },
500
586
  json: data
@@ -559,5 +645,12 @@ function getObservabilityBuildTags(options, bstackBuildTag) {
559
645
  return [];
560
646
  }
561
647
  exports.getObservabilityBuildTags = getObservabilityBuildTags;
648
+ function frameworkSupportsHook(hook, framework) {
649
+ if (framework === 'mocha' && (hook === 'before' || hook === 'after' || hook === 'beforeEach' || hook === 'afterEach')) {
650
+ return true;
651
+ }
652
+ return false;
653
+ }
654
+ exports.frameworkSupportsHook = frameworkSupportsHook;
562
655
  const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms));
563
656
  exports.sleep = sleep;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wdio/browserstack-service",
3
- "version": "7.30.3",
3
+ "version": "7.32.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",
@@ -28,12 +28,13 @@
28
28
  "@wdio/reporter": "7.25.4",
29
29
  "@wdio/types": "7.30.2",
30
30
  "browserstack-local": "^1.4.5",
31
+ "csv-writer": "^1.6.0",
31
32
  "form-data": "^4.0.0",
32
33
  "git-repo-info": "^2.1.1",
33
34
  "gitconfiglocal": "^2.1.0",
34
35
  "got": "^11.0.2",
35
36
  "uuid": "^8.3.2",
36
- "webdriverio": "7.30.2"
37
+ "webdriverio": "7.32.0"
37
38
  },
38
39
  "peerDependencies": {
39
40
  "@wdio/cli": "^5.0.0 || ^6.0.0 || ^7.0.0"
@@ -42,5 +43,5 @@
42
43
  "access": "public"
43
44
  },
44
45
  "types": "./build/index.d.ts",
45
- "gitHead": "cdc92da66a3cd9ab3ce5c6333ec2ab9541313a9d"
46
+ "gitHead": "c413d9310c8abb487bd9e1d2f82124c15a71b134"
46
47
  }