@wdio/browserstack-service 7.32.4 → 7.34.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 (47) hide show
  1. package/build/accessibility-handler.d.ts +39 -0
  2. package/build/accessibility-handler.d.ts.map +1 -0
  3. package/build/accessibility-handler.js +258 -0
  4. package/build/cleanup.d.ts +5 -0
  5. package/build/cleanup.d.ts.map +1 -0
  6. package/build/cleanup.js +23 -0
  7. package/build/constants.d.ts +3 -0
  8. package/build/constants.d.ts.map +1 -1
  9. package/build/constants.js +6 -2
  10. package/build/cucumber-types.d.ts +17 -0
  11. package/build/cucumber-types.d.ts.map +1 -1
  12. package/build/index.d.ts +5 -0
  13. package/build/index.d.ts.map +1 -1
  14. package/build/index.js +5 -1
  15. package/build/insights-handler.d.ts +19 -3
  16. package/build/insights-handler.d.ts.map +1 -1
  17. package/build/insights-handler.js +275 -17
  18. package/build/launcher.d.ts +6 -0
  19. package/build/launcher.d.ts.map +1 -1
  20. package/build/launcher.js +164 -0
  21. package/build/log4jsAppender.d.ts +2 -0
  22. package/build/log4jsAppender.d.ts.map +1 -0
  23. package/build/log4jsAppender.js +26 -0
  24. package/build/logPatcher.d.ts +13 -0
  25. package/build/logPatcher.d.ts.map +1 -0
  26. package/build/logPatcher.js +43 -0
  27. package/build/logReportingAPI.d.ts +12 -0
  28. package/build/logReportingAPI.d.ts.map +1 -0
  29. package/build/logReportingAPI.js +61 -0
  30. package/build/reporter.d.ts +6 -1
  31. package/build/reporter.d.ts.map +1 -1
  32. package/build/reporter.js +42 -1
  33. package/build/request-handler.d.ts +1 -0
  34. package/build/request-handler.d.ts.map +1 -1
  35. package/build/request-handler.js +5 -0
  36. package/build/scripts/test-event-scripts.d.ts +10 -0
  37. package/build/scripts/test-event-scripts.d.ts.map +1 -0
  38. package/build/scripts/test-event-scripts.js +73 -0
  39. package/build/service.d.ts +6 -3
  40. package/build/service.d.ts.map +1 -1
  41. package/build/service.js +50 -7
  42. package/build/types.d.ts +43 -1
  43. package/build/types.d.ts.map +1 -1
  44. package/build/util.d.ts +48 -1
  45. package/build/util.d.ts.map +1 -1
  46. package/build/util.js +448 -11
  47. package/package.json +6 -5
package/build/util.js CHANGED
@@ -26,7 +26,7 @@ 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.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;
29
+ exports.isTrue = exports.isUndefined = exports.getBrowserStackKey = exports.getBrowserStackUser = exports.stopAccessibilityTestRun = exports.getA11yResultsSummary = exports.getA11yResults = exports.createAccessibilityTestRun = exports.isAccessibilityAutomationSession = exports.shouldScanTestForAccessibility = exports.validateCapsWithA11y = exports.pushDataToQueue = exports.sleep = exports.patchConsoleLogs = exports.getFailureObject = 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.nodeRequest = exports.getCiInfo = exports.stopBuildUpstream = exports.launchTestSession = exports.o11yClassErrorHandler = exports.o11yErrorHandler = exports.errorHandler = 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"));
@@ -38,9 +38,11 @@ const got_1 = __importStar(require("got"));
38
38
  const git_repo_info_1 = __importDefault(require("git-repo-info"));
39
39
  const gitconfiglocal_1 = __importDefault(require("gitconfiglocal"));
40
40
  const crash_reporter_1 = __importDefault(require("./crash-reporter"));
41
+ const logPatcher_1 = __importDefault(require("./logPatcher"));
41
42
  const constants_1 = require("./constants");
42
43
  const request_handler_1 = __importDefault(require("./request-handler"));
43
44
  const performance_tester_1 = __importDefault(require("./performance-tester"));
45
+ const test_event_scripts_1 = require("./scripts/test-event-scripts");
44
46
  const pGitconfig = (0, util_1.promisify)(gitconfiglocal_1.default);
45
47
  const log = (0, logger_1.default)('@wdio/browserstack-service');
46
48
  exports.DEFAULT_REQUEST_CONFIG = {
@@ -123,6 +125,22 @@ function processError(error, fn, args) {
123
125
  }
124
126
  crash_reporter_1.default.uploadCrashReport(`Error in executing ${fn.name} with args ${argsString} : ${error}`, error && error.stack);
125
127
  }
128
+ function errorHandler(fn) {
129
+ return function (...args) {
130
+ try {
131
+ const functionToHandle = fn;
132
+ const result = functionToHandle(...args);
133
+ if (result instanceof Promise) {
134
+ return result.catch(error => log.error(`Error in executing ${fn.name} with args ${args}: ${error}`));
135
+ }
136
+ return result;
137
+ }
138
+ catch (error) {
139
+ log.error(`Error in executing ${fn.name} with args ${args}: ${error}`);
140
+ }
141
+ };
142
+ }
143
+ exports.errorHandler = errorHandler;
126
144
  function o11yErrorHandler(fn) {
127
145
  return function (...args) {
128
146
  try {
@@ -284,7 +302,7 @@ exports.stopBuildUpstream = o11yErrorHandler(async function stopBuildUpstream()
284
302
  }
285
303
  });
286
304
  function getCiInfo() {
287
- var env = process.env;
305
+ const env = process.env;
288
306
  // Jenkins
289
307
  if ((typeof env.JENKINS_URL === 'string' && env.JENKINS_URL.length > 0) || (typeof env.JENKINS_HOME === 'string' && env.JENKINS_HOME.length > 0)) {
290
308
  return {
@@ -295,7 +313,7 @@ function getCiInfo() {
295
313
  };
296
314
  }
297
315
  // CircleCI
298
- if (env.CI === 'true' && env.CIRCLECI === 'true') {
316
+ if (isTrue(env.CI) && isTrue(env.CIRCLECI)) {
299
317
  return {
300
318
  name: 'CircleCI',
301
319
  build_url: env.CIRCLE_BUILD_URL,
@@ -304,7 +322,7 @@ function getCiInfo() {
304
322
  };
305
323
  }
306
324
  // Travis CI
307
- if (env.CI === 'true' && env.TRAVIS === 'true') {
325
+ if (isTrue(env.CI) && isTrue(env.TRAVIS)) {
308
326
  return {
309
327
  name: 'Travis CI',
310
328
  build_url: env.TRAVIS_BUILD_WEB_URL,
@@ -313,7 +331,7 @@ function getCiInfo() {
313
331
  };
314
332
  }
315
333
  // Codeship
316
- if (env.CI === 'true' && env.CI_NAME === 'codeship') {
334
+ if (isTrue(env.CI) && env.CI_NAME === 'codeship') {
317
335
  return {
318
336
  name: 'Codeship',
319
337
  build_url: null,
@@ -331,7 +349,7 @@ function getCiInfo() {
331
349
  };
332
350
  }
333
351
  // Drone
334
- if (env.CI === 'true' && env.DRONE === 'true') {
352
+ if (isTrue(env.CI) && isTrue(env.DRONE)) {
335
353
  return {
336
354
  name: 'Drone',
337
355
  build_url: env.DRONE_BUILD_LINK,
@@ -340,7 +358,7 @@ function getCiInfo() {
340
358
  };
341
359
  }
342
360
  // Semaphore
343
- if (env.CI === 'true' && env.SEMAPHORE === 'true') {
361
+ if (isTrue(env.CI) && isTrue(env.SEMAPHORE)) {
344
362
  return {
345
363
  name: 'Semaphore',
346
364
  build_url: env.SEMAPHORE_ORGANIZATION_URL,
@@ -349,7 +367,7 @@ function getCiInfo() {
349
367
  };
350
368
  }
351
369
  // GitLab
352
- if (env.CI === 'true' && env.GITLAB_CI === 'true') {
370
+ if (isTrue(env.CI) && isTrue(env.GITLAB_CI)) {
353
371
  return {
354
372
  name: 'GitLab',
355
373
  build_url: env.CI_JOB_URL,
@@ -358,7 +376,7 @@ function getCiInfo() {
358
376
  };
359
377
  }
360
378
  // Buildkite
361
- if (env.CI === 'true' && env.BUILDKITE === 'true') {
379
+ if (isTrue(env.CI) && isTrue(env.BUILDKITE)) {
362
380
  return {
363
381
  name: 'Buildkite',
364
382
  build_url: env.BUILDKITE_BUILD_URL,
@@ -367,7 +385,7 @@ function getCiInfo() {
367
385
  };
368
386
  }
369
387
  // Visual Studio Team Services
370
- if (env.TF_BUILD === 'True') {
388
+ if (isTrue(env.TF_BUILD) && env.TF_BUILD_BUILDNUMBER) {
371
389
  return {
372
390
  name: 'Visual Studio Team Services',
373
391
  build_url: `${env.SYSTEM_TEAMFOUNDATIONSERVERURI}${env.SYSTEM_TEAMPROJECTID}`,
@@ -375,16 +393,172 @@ function getCiInfo() {
375
393
  build_number: env.BUILD_BUILDID
376
394
  };
377
395
  }
396
+ // Appveyor
397
+ if (isTrue(env.APPVEYOR)) {
398
+ return {
399
+ name: 'Appveyor',
400
+ build_url: `${env.APPVEYOR_URL}/project/${env.APPVEYOR_ACCOUNT_NAME}/${env.APPVEYOR_PROJECT_SLUG}/builds/${env.APPVEYOR_BUILD_ID}`,
401
+ job_name: env.APPVEYOR_JOB_NAME,
402
+ build_number: env.APPVEYOR_BUILD_NUMBER
403
+ };
404
+ }
405
+ // Azure CI
406
+ if (env.AZURE_HTTP_USER_AGENT && env.TF_BUILD) {
407
+ return {
408
+ name: 'Azure CI',
409
+ build_url: `${env.SYSTEM_TEAMFOUNDATIONSERVERURI}${env.SYSTEM_TEAMPROJECT}/_build/results?buildId=${env.BUILD_BUILDID}`,
410
+ job_name: env.BUILD_BUILDID,
411
+ build_number: env.BUILD_BUILDID
412
+ };
413
+ }
414
+ // AWS CodeBuild
415
+ if (env.CODEBUILD_BUILD_ID || env.CODEBUILD_RESOLVED_SOURCE_VERSION || env.CODEBUILD_SOURCE_VERSION) {
416
+ return {
417
+ name: 'AWS CodeBuild',
418
+ build_url: env.CODEBUILD_PUBLIC_BUILD_URL,
419
+ job_name: env.CODEBUILD_BUILD_ID,
420
+ build_number: env.CODEBUILD_BUILD_ID
421
+ };
422
+ }
423
+ // Bamboo
424
+ if (env.bamboo_buildNumber) {
425
+ return {
426
+ name: 'Bamboo',
427
+ build_url: env.bamboo_buildResultsUrl,
428
+ job_name: env.bamboo_shortJobName,
429
+ build_number: env.bamboo_buildNumber
430
+ };
431
+ }
432
+ // Wercker
433
+ if (env.WERCKER || env.WERCKER_MAIN_PIPELINE_STARTED) {
434
+ return {
435
+ name: 'Wercker',
436
+ build_url: env.WERCKER_BUILD_URL,
437
+ job_name: env.WERCKER_MAIN_PIPELINE_STARTED ? 'Main Pipeline' : null,
438
+ build_number: env.WERCKER_GIT_COMMIT
439
+ };
440
+ }
441
+ // Google Cloud
442
+ if (env.GCP_PROJECT || env.GCLOUD_PROJECT || env.GOOGLE_CLOUD_PROJECT) {
443
+ return {
444
+ name: 'Google Cloud',
445
+ build_url: null,
446
+ job_name: env.PROJECT_ID,
447
+ build_number: env.BUILD_ID,
448
+ };
449
+ }
450
+ // Shippable
451
+ if (env.SHIPPABLE) {
452
+ return {
453
+ name: 'Shippable',
454
+ build_url: env.SHIPPABLE_BUILD_URL,
455
+ job_name: env.SHIPPABLE_JOB_ID ? `Job #${env.SHIPPABLE_JOB_ID}` : null,
456
+ build_number: env.SHIPPABLE_BUILD_NUMBER
457
+ };
458
+ }
459
+ // Netlify
460
+ if (isTrue(env.NETLIFY)) {
461
+ return {
462
+ name: 'Netlify',
463
+ build_url: env.DEPLOY_URL,
464
+ job_name: env.SITE_NAME,
465
+ build_number: env.BUILD_ID
466
+ };
467
+ }
468
+ // Github Actions
469
+ if (isTrue(env.GITHUB_ACTIONS)) {
470
+ return {
471
+ name: 'GitHub Actions',
472
+ build_url: `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}/actions/runs/${env.GITHUB_RUN_ID}`,
473
+ job_name: env.GITHUB_WORKFLOW,
474
+ build_number: env.GITHUB_RUN_ID,
475
+ };
476
+ }
477
+ // Vercel
478
+ if (isTrue(env.CI) && env.VERCEL === '1') {
479
+ return {
480
+ name: 'Vercel',
481
+ build_url: `http://${env.VERCEL_URL}`,
482
+ job_name: null,
483
+ build_number: null,
484
+ };
485
+ }
486
+ // Teamcity
487
+ if (env.TEAMCITY_VERSION) {
488
+ return {
489
+ name: 'Teamcity',
490
+ build_url: null,
491
+ job_name: null,
492
+ build_number: env.BUILD_NUMBER,
493
+ };
494
+ }
495
+ // Concourse
496
+ if (env.CONCOURSE || env.CONCOURSE_URL || env.CONCOURSE_USERNAME || env.CONCOURSE_TEAM) {
497
+ return {
498
+ name: 'Concourse',
499
+ build_url: null,
500
+ job_name: env.BUILD_JOB_NAME || null,
501
+ build_number: env.BUILD_ID || null,
502
+ };
503
+ }
504
+ // GoCD
505
+ if (env.GO_JOB_NAME) {
506
+ return {
507
+ name: 'GoCD',
508
+ build_url: null,
509
+ job_name: env.GO_JOB_NAME,
510
+ build_number: env.GO_PIPELINE_COUNTER,
511
+ };
512
+ }
513
+ // CodeFresh
514
+ if (env.CF_BUILD_ID) {
515
+ return {
516
+ name: 'CodeFresh',
517
+ build_url: env.CF_BUILD_URL,
518
+ job_name: env.CF_PIPELINE_NAME,
519
+ build_number: env.CF_BUILD_ID,
520
+ };
521
+ }
378
522
  // if no matches, return null
379
523
  return null;
380
524
  }
381
525
  exports.getCiInfo = getCiInfo;
526
+ async function nodeRequest(requestType, apiEndpoint, options, apiUrl, timeout = 120000) {
527
+ try {
528
+ const response = await (0, got_1.default)(`${apiUrl}/${apiEndpoint}`, {
529
+ method: requestType,
530
+ timeout: {
531
+ request: timeout
532
+ },
533
+ ...options
534
+ }).json();
535
+ return response;
536
+ }
537
+ catch (error) {
538
+ if (error instanceof got_1.HTTPError && error.response) {
539
+ const errorMessageJson = error.response.body ? JSON.parse(error.response.body.toString()) : null;
540
+ const errorMessage = errorMessageJson ? errorMessageJson.message : null;
541
+ if (errorMessage) {
542
+ log.error(`${errorMessage} - ${error.stack}`);
543
+ }
544
+ else {
545
+ log.error(`${error.stack}`);
546
+ }
547
+ throw error;
548
+ }
549
+ else {
550
+ log.error(`Failed to fire api request due to ${error} - ${error.stack}`);
551
+ throw error;
552
+ }
553
+ }
554
+ }
555
+ exports.nodeRequest = nodeRequest;
382
556
  async function getGitMetaData() {
383
557
  var info = (0, git_repo_info_1.default)();
384
558
  if (!info.commonGitDir)
385
559
  return {};
386
560
  const { remote } = await pGitconfig(info.commonGitDir);
387
- const remotes = Object.keys(remote).map(remoteName => ({ name: remoteName, url: remote[remoteName]['url'] }));
561
+ const remotes = remote ? Object.keys(remote).map(remoteName => ({ name: remoteName, url: remote[remoteName]['url'] })) : [];
388
562
  return {
389
563
  name: 'git',
390
564
  sha: info.sha,
@@ -649,8 +823,271 @@ function frameworkSupportsHook(hook, framework) {
649
823
  if (framework === 'mocha' && (hook === 'before' || hook === 'after' || hook === 'beforeEach' || hook === 'afterEach')) {
650
824
  return true;
651
825
  }
826
+ if (framework === 'cucumber') {
827
+ return true;
828
+ }
652
829
  return false;
653
830
  }
654
831
  exports.frameworkSupportsHook = frameworkSupportsHook;
832
+ function getFailureObject(error) {
833
+ const stack = error.stack;
834
+ const message = typeof error === 'string' ? error : error.message;
835
+ const backtrace = stack ? removeAnsiColors(stack.toString()) : '';
836
+ return {
837
+ failure: [{ backtrace: [backtrace] }],
838
+ failure_reason: removeAnsiColors(message.toString()),
839
+ failure_type: message ? (message.toString().match(/AssertionError/) ? 'AssertionError' : 'UnhandledError') : null
840
+ };
841
+ }
842
+ exports.getFailureObject = getFailureObject;
843
+ function patchConsoleLogs() {
844
+ const BSTestOpsPatcher = new logPatcher_1.default({});
845
+ Object.keys(constants_1.consoleHolder).forEach((method) => {
846
+ const origMethod = console[method].bind(console);
847
+ // Make sure we don't override Constructors
848
+ // Arrow functions are not construable
849
+ if (typeof console[method] === 'function'
850
+ && method !== 'Console') {
851
+ console[method] = (...args) => {
852
+ origMethod(...args);
853
+ BSTestOpsPatcher[method](...args);
854
+ };
855
+ }
856
+ });
857
+ }
858
+ exports.patchConsoleLogs = patchConsoleLogs;
655
859
  const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms));
656
860
  exports.sleep = sleep;
861
+ async function pushDataToQueue(data, requestQueueHandler = undefined) {
862
+ if (!requestQueueHandler) {
863
+ requestQueueHandler = request_handler_1.default.getInstance();
864
+ }
865
+ const req = requestQueueHandler.add(data);
866
+ if (req.proceed && req.data) {
867
+ await uploadEventData(req.data, req.url);
868
+ }
869
+ }
870
+ exports.pushDataToQueue = pushDataToQueue;
871
+ const validateCapsWithA11y = (deviceName, platformMeta, chromeOptions) => {
872
+ var _a, _b;
873
+ try {
874
+ if (deviceName) {
875
+ log.warn('Accessibility Automation will run only on Desktop browsers.');
876
+ return false;
877
+ }
878
+ if (((_a = platformMeta === null || platformMeta === void 0 ? void 0 : platformMeta.browser_name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== 'chrome') {
879
+ log.warn('Accessibility Automation will run only on Chrome browsers.');
880
+ return false;
881
+ }
882
+ const browserVersion = platformMeta === null || platformMeta === void 0 ? void 0 : platformMeta.browser_version;
883
+ if (!isUndefined(browserVersion) && !(browserVersion === 'latest' || parseFloat(browserVersion + '') > 94)) {
884
+ log.warn('Accessibility Automation will run only on Chrome browser version greater than 94.');
885
+ return false;
886
+ }
887
+ if ((_b = chromeOptions === null || chromeOptions === void 0 ? void 0 : chromeOptions.args) === null || _b === void 0 ? void 0 : _b.includes('--headless')) {
888
+ log.warn('Accessibility Automation will not run on legacy headless mode. Switch to new headless mode or avoid using headless mode.');
889
+ return false;
890
+ }
891
+ return true;
892
+ }
893
+ catch (error) {
894
+ log.debug(`Exception in checking capabilities compatibility with Accessibility. Error: ${error}`);
895
+ }
896
+ return false;
897
+ };
898
+ exports.validateCapsWithA11y = validateCapsWithA11y;
899
+ const shouldScanTestForAccessibility = (suiteTitle, testTitle, accessibilityOptions) => {
900
+ try {
901
+ const includeTags = Array.isArray(accessibilityOptions === null || accessibilityOptions === void 0 ? void 0 : accessibilityOptions.includeTagsInTestingScope) ? accessibilityOptions === null || accessibilityOptions === void 0 ? void 0 : accessibilityOptions.includeTagsInTestingScope : [];
902
+ const excludeTags = Array.isArray(accessibilityOptions === null || accessibilityOptions === void 0 ? void 0 : accessibilityOptions.excludeTagsInTestingScope) ? accessibilityOptions === null || accessibilityOptions === void 0 ? void 0 : accessibilityOptions.excludeTagsInTestingScope : [];
903
+ const fullTestName = suiteTitle + ' ' + testTitle;
904
+ const excluded = excludeTags === null || excludeTags === void 0 ? void 0 : excludeTags.some((exclude) => fullTestName.includes(exclude));
905
+ const included = (includeTags === null || includeTags === void 0 ? void 0 : includeTags.length) === 0 || (includeTags === null || includeTags === void 0 ? void 0 : includeTags.some((include) => fullTestName.includes(include)));
906
+ return !excluded && included;
907
+ }
908
+ catch (error) {
909
+ log.debug('Error while validating test case for accessibility before scanning. Error : ', error);
910
+ }
911
+ return false;
912
+ };
913
+ exports.shouldScanTestForAccessibility = shouldScanTestForAccessibility;
914
+ const isAccessibilityAutomationSession = (accessibilityFlag) => {
915
+ try {
916
+ const hasA11yJwtToken = typeof process.env.BSTACK_A11Y_JWT === 'string' && process.env.BSTACK_A11Y_JWT.length > 0 && process.env.BSTACK_A11Y_JWT !== 'null' && process.env.BSTACK_A11Y_JWT !== 'undefined';
917
+ return accessibilityFlag && hasA11yJwtToken;
918
+ }
919
+ catch (error) {
920
+ log.debug(`Exception in verifying the Accessibility session with error : ${error}`);
921
+ }
922
+ return false;
923
+ };
924
+ exports.isAccessibilityAutomationSession = isAccessibilityAutomationSession;
925
+ exports.createAccessibilityTestRun = errorHandler(async function createAccessibilityTestRun(options, config, bsConfig) {
926
+ const userName = getBrowserStackUser(config);
927
+ const accessKey = getBrowserStackKey(config);
928
+ if (isUndefined(userName) || isUndefined(accessKey)) {
929
+ log.error('Exception while creating test run for BrowserStack Accessibility Automation: Missing BrowserStack credentials');
930
+ return null;
931
+ }
932
+ const data = {
933
+ 'projectName': bsConfig.projectName,
934
+ 'buildName': bsConfig.buildName ||
935
+ path_1.default.basename(path_1.default.resolve(process.cwd())),
936
+ 'startTime': (new Date()).toISOString(),
937
+ 'description': '',
938
+ 'source': {
939
+ frameworkName: 'WebdriverIO-' + config.framework,
940
+ frameworkVersion: bsConfig.bstackServiceVersion,
941
+ sdkVersion: bsConfig.bstackServiceVersion
942
+ },
943
+ 'settings': bsConfig.accessibilityOptions || {},
944
+ 'versionControl': await getGitMetaData(),
945
+ 'ciInfo': getCiInfo(),
946
+ 'hostInfo': {
947
+ hostname: (0, os_1.hostname)(),
948
+ platform: (0, os_1.platform)(),
949
+ type: (0, os_1.type)(),
950
+ version: (0, os_1.version)(),
951
+ arch: (0, os_1.arch)()
952
+ },
953
+ 'browserstackAutomation': true,
954
+ };
955
+ const requestOptions = {
956
+ json: data,
957
+ username: getBrowserStackUser(config),
958
+ password: getBrowserStackKey(config),
959
+ };
960
+ try {
961
+ const response = await nodeRequest('POST', 'test_runs', requestOptions, constants_1.ACCESSIBILITY_API_URL);
962
+ log.debug(`[Create Accessibility Test Run] Success response: ${JSON.stringify(response)}`);
963
+ if (response.data.accessibilityToken) {
964
+ process.env.BSTACK_A11Y_JWT = response.data.accessibilityToken;
965
+ }
966
+ if (response.data.id) {
967
+ process.env.BS_A11Y_TEST_RUN_ID = response.data.id;
968
+ }
969
+ log.debug(`BrowserStack Accessibility Automation Test Run ID: ${response.data.id}`);
970
+ return response.data.scannerVersion;
971
+ }
972
+ catch (error) {
973
+ if (error.response) {
974
+ log.error(`Exception while creating test run for BrowserStack Accessibility Automation: ${error.response.status} ${error.response.statusText} ${JSON.stringify(error.response.data)}`);
975
+ }
976
+ else {
977
+ const errorMessage = error.message;
978
+ if (errorMessage === 'Invalid configuration passed.') {
979
+ log.error(`Exception while creating test run for BrowserStack Accessibility Automation: ${errorMessage || error.stack}`);
980
+ for (const errorkey of error.errors) {
981
+ log.error(errorkey.message);
982
+ }
983
+ }
984
+ else {
985
+ log.error(`Exception while creating test run for BrowserStack Accessibility Automation: ${errorMessage || error.stack}`);
986
+ }
987
+ }
988
+ return null;
989
+ }
990
+ });
991
+ const getA11yResults = async (browser, isBrowserStackSession, isAccessibility) => {
992
+ if (!isBrowserStackSession) {
993
+ log.warn('Not a BrowserStack Automate session, cannot retrieve Accessibility results.');
994
+ return []; // since we are running only on Automate as of now
995
+ }
996
+ if (!(0, exports.isAccessibilityAutomationSession)(isAccessibility)) {
997
+ log.warn('Not an Accessibility Automation session, cannot retrieve Accessibility results.');
998
+ return [];
999
+ }
1000
+ try {
1001
+ const results = await browser.execute(test_event_scripts_1.accessibilityResults);
1002
+ return results;
1003
+ }
1004
+ catch {
1005
+ log.error('No accessibility results were found.');
1006
+ return [];
1007
+ }
1008
+ };
1009
+ exports.getA11yResults = getA11yResults;
1010
+ const getA11yResultsSummary = async (browser, isBrowserStackSession, isAccessibility) => {
1011
+ if (!isBrowserStackSession) {
1012
+ return {}; // since we are running only on Automate as of now
1013
+ }
1014
+ if (!(0, exports.isAccessibilityAutomationSession)(isAccessibility)) {
1015
+ log.warn('Not an Accessibility Automation session, cannot retrieve Accessibility results summary.');
1016
+ return {};
1017
+ }
1018
+ try {
1019
+ const summaryResults = await browser.execute(test_event_scripts_1.accessibilityResultsSummary);
1020
+ return summaryResults;
1021
+ }
1022
+ catch {
1023
+ log.error('No accessibility summary was found.');
1024
+ return {};
1025
+ }
1026
+ };
1027
+ exports.getA11yResultsSummary = getA11yResultsSummary;
1028
+ exports.stopAccessibilityTestRun = errorHandler(async function stopAccessibilityTestRun() {
1029
+ const hasA11yJwtToken = typeof process.env.BSTACK_A11Y_JWT === 'string' && process.env.BSTACK_A11Y_JWT.length > 0 && process.env.BSTACK_A11Y_JWT !== 'null' && process.env.BSTACK_A11Y_JWT !== 'undefined';
1030
+ if (!hasA11yJwtToken) {
1031
+ return {
1032
+ status: 'error',
1033
+ message: 'Build creation had failed.'
1034
+ };
1035
+ }
1036
+ const data = {
1037
+ 'endTime': (new Date()).toISOString(),
1038
+ };
1039
+ const requestOptions = { ...{
1040
+ json: data,
1041
+ headers: {
1042
+ 'Authorization': `Bearer ${process.env.BSTACK_A11Y_JWT}`,
1043
+ }
1044
+ } };
1045
+ try {
1046
+ const response = await nodeRequest('PUT', 'test_runs/stop', requestOptions, constants_1.ACCESSIBILITY_API_URL);
1047
+ if (response.data && response.data.error) {
1048
+ throw new Error('Invalid request: ' + response.data.error);
1049
+ }
1050
+ else if (response.error) {
1051
+ throw new Error('Invalid request: ' + response.error);
1052
+ }
1053
+ else {
1054
+ log.info(`BrowserStack Accessibility Automation Test Run marked as completed at ${new Date().toISOString()}`);
1055
+ return { status: 'success', message: '' };
1056
+ }
1057
+ }
1058
+ catch (error) {
1059
+ if (error.response && error.response.status && error.response.statusText && error.response.data) {
1060
+ log.error(`Exception while marking completion of BrowserStack Accessibility Automation Test Run: ${error.response.status} ${error.response.statusText} ${JSON.stringify(error.response.data)}`);
1061
+ }
1062
+ else {
1063
+ log.error(`Exception while marking completion of BrowserStack Accessibility Automation Test Run: ${error.message || util_2.default.format(error)}`);
1064
+ }
1065
+ return {
1066
+ status: 'error',
1067
+ message: error.message ||
1068
+ (error.response ? `${error.response.status}:${error.response.statusText}` : error)
1069
+ };
1070
+ }
1071
+ });
1072
+ function getBrowserStackUser(config) {
1073
+ if (process.env.BROWSERSTACK_USERNAME) {
1074
+ return process.env.BROWSERSTACK_USERNAME;
1075
+ }
1076
+ return config.user;
1077
+ }
1078
+ exports.getBrowserStackUser = getBrowserStackUser;
1079
+ function getBrowserStackKey(config) {
1080
+ if (process.env.BROWSERSTACK_ACCESS_KEY) {
1081
+ return process.env.BROWSERSTACK_ACCESS_KEY;
1082
+ }
1083
+ return config.key;
1084
+ }
1085
+ exports.getBrowserStackKey = getBrowserStackKey;
1086
+ function isUndefined(value) {
1087
+ return value === undefined || value === null;
1088
+ }
1089
+ exports.isUndefined = isUndefined;
1090
+ function isTrue(value) {
1091
+ return (value + '').toLowerCase() === 'true';
1092
+ }
1093
+ exports.isTrue = isTrue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wdio/browserstack-service",
3
- "version": "7.32.4",
3
+ "version": "7.34.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",
@@ -26,15 +26,16 @@
26
26
  "@types/gitconfiglocal": "^2.0.1",
27
27
  "@wdio/logger": "7.26.0",
28
28
  "@wdio/reporter": "7.25.4",
29
- "@wdio/types": "7.30.2",
29
+ "@wdio/types": "7.33.0",
30
30
  "browserstack-local": "^1.4.5",
31
31
  "csv-writer": "^1.6.0",
32
32
  "form-data": "^4.0.0",
33
33
  "git-repo-info": "^2.1.1",
34
34
  "gitconfiglocal": "^2.1.0",
35
35
  "got": "^11.0.2",
36
- "uuid": "^8.3.2",
37
- "webdriverio": "7.32.4"
36
+ "uuid": "^9.0.1",
37
+ "webdriverio": "7.34.0",
38
+ "winston-transport": "^4.5.0"
38
39
  },
39
40
  "peerDependencies": {
40
41
  "@wdio/cli": "^5.0.0 || ^6.0.0 || ^7.0.0"
@@ -43,5 +44,5 @@
43
44
  "access": "public"
44
45
  },
45
46
  "types": "./build/index.d.ts",
46
- "gitHead": "8a5e729270f4d2acda44cefa30b7db7ba837ea2c"
47
+ "gitHead": "9a1640148030bbadd646deb582c24a54fede12a3"
47
48
  }