@wdio/browserstack-service 7.32.4 → 7.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 (41) 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/constants.d.ts +3 -0
  5. package/build/constants.d.ts.map +1 -1
  6. package/build/constants.js +6 -2
  7. package/build/cucumber-types.d.ts +17 -0
  8. package/build/cucumber-types.d.ts.map +1 -1
  9. package/build/index.d.ts +5 -0
  10. package/build/index.d.ts.map +1 -1
  11. package/build/index.js +5 -1
  12. package/build/insights-handler.d.ts +19 -3
  13. package/build/insights-handler.d.ts.map +1 -1
  14. package/build/insights-handler.js +274 -17
  15. package/build/launcher.d.ts +4 -0
  16. package/build/launcher.d.ts.map +1 -1
  17. package/build/launcher.js +152 -0
  18. package/build/log4jsAppender.d.ts +2 -0
  19. package/build/log4jsAppender.d.ts.map +1 -0
  20. package/build/log4jsAppender.js +26 -0
  21. package/build/logPatcher.d.ts +13 -0
  22. package/build/logPatcher.d.ts.map +1 -0
  23. package/build/logPatcher.js +43 -0
  24. package/build/logReportingAPI.d.ts +12 -0
  25. package/build/logReportingAPI.d.ts.map +1 -0
  26. package/build/logReportingAPI.js +61 -0
  27. package/build/reporter.d.ts +6 -1
  28. package/build/reporter.d.ts.map +1 -1
  29. package/build/reporter.js +42 -1
  30. package/build/scripts/test-event-scripts.d.ts +10 -0
  31. package/build/scripts/test-event-scripts.d.ts.map +1 -0
  32. package/build/scripts/test-event-scripts.js +73 -0
  33. package/build/service.d.ts +5 -3
  34. package/build/service.d.ts.map +1 -1
  35. package/build/service.js +24 -4
  36. package/build/types.d.ts +34 -1
  37. package/build/types.d.ts.map +1 -1
  38. package/build/util.d.ts +32 -0
  39. package/build/util.d.ts.map +1 -1
  40. package/build/util.js +313 -2
  41. package/package.json +6 -5
@@ -4,11 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const path_1 = __importDefault(require("path"));
7
+ const logger_1 = __importDefault(require("@wdio/logger"));
7
8
  const uuid_1 = require("uuid");
8
9
  const reporter_1 = __importDefault(require("./reporter"));
9
10
  const util_1 = require("./util");
10
11
  const request_handler_1 = __importDefault(require("./request-handler"));
11
12
  const constants_1 = require("./constants");
13
+ const log = (0, logger_1.default)('@wdio/browserstack-service');
12
14
  class _InsightsHandler {
13
15
  constructor(_browser, browserCaps, isAppAutomate, sessionId, _framework) {
14
16
  this._browser = _browser;
@@ -17,6 +19,32 @@ class _InsightsHandler {
17
19
  this._hooks = {};
18
20
  this._commands = {};
19
21
  this._requestQueueHandler = request_handler_1.default.getInstance();
22
+ this._currentTest = {};
23
+ this._currentHook = {};
24
+ this._cucumberData = {
25
+ stepsStarted: false,
26
+ scenariosStarted: false,
27
+ steps: []
28
+ };
29
+ this.appendTestItemLog = async (stdLog) => {
30
+ try {
31
+ if (this._currentHook.uuid && !this._currentHook.finished && (this._framework === 'mocha' || this._framework === 'cucumber')) {
32
+ stdLog.hook_run_uuid = this._currentHook.uuid;
33
+ }
34
+ else if (this._currentTest.uuid && (this._framework === 'mocha' || this._framework === 'cucumber')) {
35
+ stdLog.test_run_uuid = this._currentTest.uuid;
36
+ }
37
+ if (stdLog.hook_run_uuid || stdLog.test_run_uuid) {
38
+ await (0, util_1.pushDataToQueue)({
39
+ event_type: 'LogCreated',
40
+ logs: [stdLog]
41
+ });
42
+ }
43
+ }
44
+ catch (error) {
45
+ log.debug(`Exception in uploading log data to Observability with error : ${error}`);
46
+ }
47
+ };
20
48
  this._requestQueueHandler.start();
21
49
  this._platformMeta = {
22
50
  browserName: browserCaps === null || browserCaps === void 0 ? void 0 : browserCaps.browserName,
@@ -26,6 +54,14 @@ class _InsightsHandler {
26
54
  sessionId: sessionId,
27
55
  product: isAppAutomate ? 'app-automate' : 'automate'
28
56
  };
57
+ this.registerListeners();
58
+ }
59
+ registerListeners() {
60
+ if (!(this._framework === 'mocha' || this._framework === 'cucumber')) {
61
+ return;
62
+ }
63
+ process.removeAllListeners(`bs:addLog:${process.pid}`);
64
+ process.on(`bs:addLog:${process.pid}`, this.appendTestItemLog.bind(this));
29
65
  }
30
66
  async before() {
31
67
  if ((0, util_1.isBrowserstackSession)(this._browser)) {
@@ -40,19 +76,31 @@ class _InsightsHandler {
40
76
  if (!(0, util_1.frameworkSupportsHook)('before', this._framework)) {
41
77
  return;
42
78
  }
79
+ const hookUUID = (0, uuid_1.v4)();
80
+ if (this._framework === 'cucumber') {
81
+ test = test;
82
+ await this.processCucumberHook(test, { event: 'before', hookUUID });
83
+ return;
84
+ }
85
+ test = test;
43
86
  const fullTitle = (0, util_1.getUniqueIdentifier)(test, this._framework);
44
- const hookId = (0, uuid_1.v4)();
45
87
  this._tests[fullTitle] = {
46
- uuid: hookId,
88
+ uuid: hookUUID,
47
89
  startedAt: (new Date()).toISOString()
48
90
  };
49
- this.attachHookData(context, hookId);
91
+ this.setCurrentHook({ uuid: hookUUID });
92
+ this.attachHookData(context, hookUUID);
50
93
  await this.sendTestRunEvent(test, 'HookRunStarted');
51
94
  }
52
95
  async afterHook(test, result) {
53
96
  if (!(0, util_1.frameworkSupportsHook)('after', this._framework)) {
54
97
  return;
55
98
  }
99
+ if (this._framework === 'cucumber') {
100
+ await this.processCucumberHook(test, { event: 'after' }, result);
101
+ return;
102
+ }
103
+ test = test;
56
104
  const fullTitle = (0, util_1.getUniqueIdentifier)(test, this._framework);
57
105
  if (this._tests[fullTitle]) {
58
106
  this._tests[fullTitle].finishedAt = (new Date()).toISOString();
@@ -62,6 +110,7 @@ class _InsightsHandler {
62
110
  finishedAt: (new Date()).toISOString()
63
111
  };
64
112
  }
113
+ this.setCurrentHook({ uuid: this._tests[fullTitle].uuid, finished: true });
65
114
  await this.sendTestRunEvent(test, 'HookRunFinished', result);
66
115
  const hookType = (0, util_1.getHookType)(test.title);
67
116
  /*
@@ -97,11 +146,15 @@ class _InsightsHandler {
97
146
  }
98
147
  }
99
148
  async beforeTest(test) {
149
+ const uuid = (0, uuid_1.v4)();
150
+ this._currentTest = {
151
+ test, uuid
152
+ };
100
153
  if (this._framework !== 'mocha')
101
154
  return;
102
155
  const fullTitle = (0, util_1.getUniqueIdentifier)(test, this._framework);
103
156
  this._tests[fullTitle] = {
104
- uuid: (0, uuid_1.v4)(),
157
+ uuid: uuid,
105
158
  startedAt: (new Date()).toISOString()
106
159
  };
107
160
  await this.sendTestRunEvent(test, 'TestRunStarted');
@@ -119,13 +172,25 @@ class _InsightsHandler {
119
172
  /**
120
173
  * Cucumber Only
121
174
  */
175
+ async beforeFeature(uri, feature) {
176
+ this._cucumberData.scenariosStarted = false;
177
+ this._cucumberData.feature = feature;
178
+ this._cucumberData.uri = uri;
179
+ }
122
180
  async beforeScenario(world) {
181
+ const uuid = (0, uuid_1.v4)();
182
+ this._currentTest = {
183
+ uuid
184
+ };
185
+ this._cucumberData.scenario = world.pickle;
186
+ this._cucumberData.scenariosStarted = true;
187
+ this._cucumberData.stepsStarted = false;
123
188
  const pickleData = world.pickle;
124
189
  const gherkinDocument = world.gherkinDocument;
125
190
  const featureData = gherkinDocument.feature;
126
191
  const uniqueId = (0, util_1.getUniqueIdentifierForCucumber)(world);
127
192
  let testMetaData = {
128
- uuid: (0, uuid_1.v4)(),
193
+ uuid: uuid,
129
194
  startedAt: (new Date()).toISOString()
130
195
  };
131
196
  if (pickleData) {
@@ -144,10 +209,13 @@ class _InsightsHandler {
144
209
  await this.sendTestRunEventForCucumber(world, 'TestRunStarted');
145
210
  }
146
211
  async afterScenario(world) {
212
+ this._cucumberData.scenario = undefined;
147
213
  await this.sendTestRunEventForCucumber(world, 'TestRunFinished');
148
214
  }
149
215
  async beforeStep(step, scenario) {
150
216
  var _a;
217
+ this._cucumberData.stepsStarted = true;
218
+ this._cucumberData.steps.push(step);
151
219
  const uniqueId = (0, util_1.getUniqueIdentifierForCucumber)({ pickle: scenario });
152
220
  let testMetaData = this._tests[uniqueId];
153
221
  if (!testMetaData) {
@@ -168,6 +236,7 @@ class _InsightsHandler {
168
236
  }
169
237
  async afterStep(step, scenario, result) {
170
238
  var _a;
239
+ this._cucumberData.steps.pop();
171
240
  const uniqueId = (0, util_1.getUniqueIdentifierForCucumber)({ pickle: scenario });
172
241
  let testMetaData = this._tests[uniqueId];
173
242
  if (!testMetaData) {
@@ -195,6 +264,75 @@ class _InsightsHandler {
195
264
  }
196
265
  this._tests[uniqueId] = testMetaData;
197
266
  }
267
+ async sendScenarioObjectSkipped(scenario, feature, uri) {
268
+ const testMetaData = {
269
+ uuid: (0, uuid_1.v4)(),
270
+ startedAt: (new Date()).toISOString(),
271
+ finishedAt: (new Date()).toISOString(),
272
+ scenario: {
273
+ name: scenario.name
274
+ },
275
+ feature: {
276
+ path: uri,
277
+ name: feature.name,
278
+ description: feature.description
279
+ },
280
+ steps: scenario.steps.map((step) => {
281
+ return {
282
+ id: step.id,
283
+ text: step.text,
284
+ keyword: step.keyword,
285
+ result: 'skipped',
286
+ };
287
+ }),
288
+ };
289
+ await this.sendTestRunEventForCucumber(null, 'TestRunSkipped', testMetaData);
290
+ }
291
+ async processCucumberHook(test, params, result) {
292
+ const hookType = this.getCucumberHookType(test);
293
+ if (!hookType) {
294
+ return;
295
+ }
296
+ const { event, hookUUID } = params;
297
+ const hookId = this.getCucumberHookUniqueId(hookType, test);
298
+ if (!hookId) {
299
+ return;
300
+ }
301
+ if (event === 'before') {
302
+ this.setCurrentHook({ uuid: hookUUID });
303
+ const hookMetaData = {
304
+ uuid: hookUUID,
305
+ startedAt: (new Date()).toISOString(),
306
+ testRunId: this._currentTest.uuid,
307
+ hookType: hookType
308
+ };
309
+ this._tests[hookId] = hookMetaData;
310
+ await this.sendHookRunEvent(hookMetaData, 'HookRunStarted');
311
+ }
312
+ else {
313
+ this._tests[hookId].finishedAt = (new Date()).toISOString();
314
+ this.setCurrentHook({ uuid: this._tests[hookId].uuid, finished: true });
315
+ await this.sendHookRunEvent(this._tests[hookId], 'HookRunFinished', result);
316
+ if (hookType === 'BEFORE_ALL' && result && !result.passed) {
317
+ const { feature, uri } = this._cucumberData;
318
+ if (!feature) {
319
+ return;
320
+ }
321
+ feature.children.map(async (childObj) => {
322
+ if (childObj.rule) {
323
+ childObj.rule.children.map(async (scenarioObj) => {
324
+ if (scenarioObj.scenario) {
325
+ await this.sendScenarioObjectSkipped(scenarioObj.scenario, feature, uri);
326
+ }
327
+ });
328
+ }
329
+ else if (childObj.scenario) {
330
+ await this.sendScenarioObjectSkipped(childObj.scenario, feature, uri);
331
+ }
332
+ });
333
+ }
334
+ }
335
+ }
198
336
  //@ts-ignore
199
337
  async uploadPending(waitTimeout = constants_1.DEFAULT_WAIT_TIMEOUT_FOR_PENDING_UPLOADS, waitInterval = constants_1.DEFAULT_WAIT_INTERVAL_FOR_PENDING_UPLOADS) {
200
338
  if (this._requestQueueHandler.pendingUploads <= 0 || waitTimeout <= 0) {
@@ -261,6 +399,12 @@ class _InsightsHandler {
261
399
  /*
262
400
  * private methods
263
401
  */
402
+ async sendData(data) {
403
+ const req = this._requestQueueHandler.add(data);
404
+ if (req.proceed && req.data) {
405
+ await (0, util_1.uploadEventData)(req.data, req.url);
406
+ }
407
+ }
264
408
  attachHookData(context, hookId) {
265
409
  if (context.currentTest && context.currentTest.parent) {
266
410
  const parentTest = `${context.currentTest.parent.title} - ${context.currentTest.title}`;
@@ -294,6 +438,63 @@ class _InsightsHandler {
294
438
  }
295
439
  return false;
296
440
  }
441
+ getCucumberHookType(test) {
442
+ var _a;
443
+ let hookType = null;
444
+ if (!test) {
445
+ hookType = this._cucumberData.scenariosStarted ? 'AFTER_ALL' : 'BEFORE_ALL';
446
+ }
447
+ else if (!this._cucumberData.stepsStarted) {
448
+ hookType = 'BEFORE_EACH';
449
+ }
450
+ else if (((_a = this._cucumberData.steps) === null || _a === void 0 ? void 0 : _a.length) > 0) {
451
+ // beforeStep or afterStep
452
+ }
453
+ else {
454
+ hookType = 'AFTER_EACH';
455
+ }
456
+ return hookType;
457
+ }
458
+ getCucumberHookName(hookType) {
459
+ var _a, _b;
460
+ switch (hookType) {
461
+ case 'BEFORE_EACH':
462
+ case 'AFTER_EACH':
463
+ return `${hookType} for ${(_a = this._cucumberData.scenario) === null || _a === void 0 ? void 0 : _a.name}`;
464
+ case 'BEFORE_ALL':
465
+ case 'AFTER_ALL':
466
+ return `${hookType} for ${(_b = this._cucumberData.feature) === null || _b === void 0 ? void 0 : _b.name}`;
467
+ }
468
+ return '';
469
+ }
470
+ getCucumberHookUniqueId(hookType, hook) {
471
+ switch (hookType) {
472
+ case 'BEFORE_EACH':
473
+ case 'AFTER_EACH':
474
+ return hook.hookId;
475
+ case 'BEFORE_ALL':
476
+ case 'AFTER_ALL':
477
+ // Can only work for single beforeAll or afterAll
478
+ return `${hookType} for ${this.getCucumberFeatureUniqueId()}`;
479
+ }
480
+ return null;
481
+ }
482
+ getCucumberFeatureUniqueId() {
483
+ const { uri, feature } = this._cucumberData;
484
+ return `${uri}:${feature === null || feature === void 0 ? void 0 : feature.name}`;
485
+ }
486
+ setCurrentHook(hookDetails) {
487
+ if (hookDetails.finished) {
488
+ if (this._currentHook.uuid === hookDetails.uuid) {
489
+ this._currentHook.finished = true;
490
+ }
491
+ return;
492
+ }
493
+ this._currentHook = {
494
+ uuid: hookDetails.uuid,
495
+ finished: false
496
+ };
497
+ }
297
498
  /*
298
499
  * Get hierarchy info
299
500
  */
@@ -410,13 +611,19 @@ class _InsightsHandler {
410
611
  await (0, util_1.uploadEventData)(req.data, req.url);
411
612
  }
412
613
  }
413
- async sendTestRunEventForCucumber(world, eventType) {
414
- const uniqueId = (0, util_1.getUniqueIdentifierForCucumber)(world);
415
- const { feature, scenario, steps, uuid, startedAt, finishedAt } = this._tests[uniqueId] || {};
416
- let fullNameWithExamples = world.pickle.name;
417
- const examples = (0, util_1.getScenarioExamples)(world);
418
- if (examples) {
419
- fullNameWithExamples = world.pickle.name + ' (' + examples.join(', ') + ')';
614
+ async sendTestRunEventForCucumber(worldObj, eventType, testMetaData = null) {
615
+ const world = worldObj;
616
+ const dataHub = testMetaData ? testMetaData : (this._tests[(0, util_1.getUniqueIdentifierForCucumber)(world)] || {});
617
+ const { feature, scenario, steps, uuid, startedAt, finishedAt } = dataHub;
618
+ const examples = !testMetaData ? (0, util_1.getScenarioExamples)(world) : undefined;
619
+ let fullNameWithExamples;
620
+ if (!testMetaData) {
621
+ fullNameWithExamples = examples
622
+ ? world.pickle.name + ' (' + examples.join(', ') + ')'
623
+ : world.pickle.name;
624
+ }
625
+ else {
626
+ fullNameWithExamples = (scenario === null || scenario === void 0 ? void 0 : scenario.name) || '';
420
627
  }
421
628
  let testData = {
422
629
  uuid: uuid,
@@ -443,7 +650,7 @@ class _InsightsHandler {
443
650
  examples: examples
444
651
  }
445
652
  };
446
- if (eventType == 'TestRunStarted') {
653
+ if (eventType == 'TestRunStarted' || eventType === 'TestRunSkipped') {
447
654
  testData.integrations = {};
448
655
  if (this._browser && this._platformMeta) {
449
656
  const provider = (0, util_1.getCloudProvider)(this._browser);
@@ -451,7 +658,7 @@ class _InsightsHandler {
451
658
  }
452
659
  }
453
660
  /* istanbul ignore if */
454
- if (world.result) {
661
+ if (world === null || world === void 0 ? void 0 : world.result) {
455
662
  let result = world.result.status.toLowerCase();
456
663
  if (result !== 'passed' && result !== 'failed') {
457
664
  result = 'skipped'; // mark UNKNOWN/UNDEFINED/AMBIGUOUS/PENDING as skipped
@@ -464,8 +671,8 @@ class _InsightsHandler {
464
671
  {
465
672
  'backtrace': [world.result.message ? (0, util_1.removeAnsiColors)(world.result.message) : 'unknown']
466
673
  }
467
- ],
468
- testData.failure_reason = world.result.message ? (0, util_1.removeAnsiColors)(world.result.message) : world.result.message;
674
+ ];
675
+ testData.failure_reason = world.result.message ? (0, util_1.removeAnsiColors)(world.result.message) : world.result.message;
469
676
  if (world.result.message) {
470
677
  testData.failure_type = world.result.message.match(/AssertionError/)
471
678
  ? 'AssertionError'
@@ -473,9 +680,13 @@ class _InsightsHandler {
473
680
  }
474
681
  }
475
682
  }
476
- if (world.pickle) {
683
+ if (world === null || world === void 0 ? void 0 : world.pickle) {
477
684
  testData.tags = world.pickle.tags.map(({ name }) => (name));
478
685
  }
686
+ if (eventType === 'TestRunSkipped') {
687
+ testData.result = 'skipped';
688
+ eventType = 'TestRunFinished';
689
+ }
479
690
  const uploadData = {
480
691
  event_type: eventType,
481
692
  test_run: testData
@@ -485,6 +696,52 @@ class _InsightsHandler {
485
696
  await (0, util_1.uploadEventData)(req.data, req.url);
486
697
  }
487
698
  }
699
+ async sendHookRunEvent(hookData, eventType, result) {
700
+ const { uri, feature } = this._cucumberData;
701
+ const testData = {
702
+ uuid: hookData.uuid,
703
+ type: 'hook',
704
+ name: this.getCucumberHookName(hookData.hookType),
705
+ body: {
706
+ lang: 'webdriverio',
707
+ code: null
708
+ },
709
+ started_at: hookData.startedAt,
710
+ finished_at: hookData.finishedAt,
711
+ hook_type: hookData.hookType,
712
+ test_run_id: hookData.testRunId,
713
+ scope: feature === null || feature === void 0 ? void 0 : feature.name,
714
+ scopes: [(feature === null || feature === void 0 ? void 0 : feature.name) || ''],
715
+ file_name: uri ? path_1.default.relative(process.cwd(), uri) : undefined,
716
+ location: uri ? path_1.default.relative(process.cwd(), uri) : undefined,
717
+ vc_filepath: (this._gitConfigPath && uri) ? path_1.default.relative(this._gitConfigPath, uri) : undefined,
718
+ result: 'pending',
719
+ framework: this._framework
720
+ };
721
+ if (eventType === 'HookRunFinished' && result) {
722
+ testData.result = result.passed ? 'passed' : 'failed';
723
+ testData.retries = result.retries;
724
+ testData.duration_in_ms = result.duration;
725
+ if (!result.passed) {
726
+ Object.assign(testData, (0, util_1.getFailureObject)(result.error));
727
+ }
728
+ }
729
+ if (eventType === 'HookRunStarted') {
730
+ testData.integrations = {};
731
+ if (this._browser && this._platformMeta) {
732
+ const provider = (0, util_1.getCloudProvider)(this._browser);
733
+ testData.integrations[provider] = this.getIntegrationsObject();
734
+ }
735
+ }
736
+ const uploadData = {
737
+ event_type: eventType,
738
+ hook_run: testData
739
+ };
740
+ const req = this._requestQueueHandler.add(uploadData);
741
+ if (req.proceed && req.data) {
742
+ await (0, util_1.uploadEventData)(req.data, req.url);
743
+ }
744
+ }
488
745
  getIntegrationsObject() {
489
746
  var _a, _b, _c, _d, _e, _f;
490
747
  return {
@@ -13,6 +13,7 @@ export default class BrowserstackLauncherService implements Services.ServiceInst
13
13
  private _projectName?;
14
14
  private _buildTag?;
15
15
  private _buildIdentifier?;
16
+ private _accessibilityAutomation?;
16
17
  constructor(_options: BrowserstackConfig & Options.Testrunner, capabilities: Capabilities.RemoteCapability, _config: Options.Testrunner);
17
18
  onPrepare(config?: Options.Testrunner, capabilities?: Capabilities.RemoteCapabilities): Promise<unknown>;
18
19
  onComplete(): Promise<unknown>;
@@ -22,6 +23,9 @@ export default class BrowserstackLauncherService implements Services.ServiceInst
22
23
  * <object>: only "path" and "custom_id" should coexist as multiple properties.
23
24
  */
24
25
  _validateApp(appConfig: AppConfig | string): Promise<App>;
26
+ _updateObjectTypeCaps(capabilities?: Capabilities.RemoteCapabilities, capType?: string, value?: {
27
+ [key: string]: any;
28
+ }): void;
25
29
  _updateCaps(capabilities?: Capabilities.RemoteCapabilities, capType?: string, value?: string): void;
26
30
  _handleBuildIdentifier(capabilities?: Capabilities.RemoteCapabilities): void;
27
31
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,yBAAyB,MAAM,oBAAoB,CAAA;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAKlE,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAapF,KAAK,iBAAiB,GAAG,yBAAyB,CAAC,KAAK,GAAG;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;CAC7C,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,2BAA4B,YAAW,QAAQ,CAAC,eAAe;IAQ5E,OAAO,CAAC,QAAQ;IAEhB,OAAO,CAAC,OAAO;IATnB,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,YAAY,CAAC,CAAQ;IAC7B,OAAO,CAAC,SAAS,CAAC,CAAQ;IAC1B,OAAO,CAAC,gBAAgB,CAAC,CAAQ;gBAGrB,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EACzD,YAAY,EAAE,YAAY,CAAC,gBAAgB,EACnC,OAAO,EAAE,OAAO,CAAC,UAAU;IAqEjC,SAAS,CAAE,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IA2GtF,UAAU;IAsDV,UAAU,CAAC,GAAG,EAAC,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAkBrD;;;OAGG;IACG,YAAY,CAAE,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAyBhE,WAAW,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAC,MAAM;IAoF3F,sBAAsB,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IAyCrE;;;OAGG;IACH,oBAAoB;IA6BpB,sBAAsB,CAAC,QAAQ,CAAC,EAAC,MAAM,EAAE,SAAS,CAAC,EAAC,MAAM,EAAE,eAAe,CAAC,EAAC,MAAM;CAQtF"}
1
+ {"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,yBAAyB,MAAM,oBAAoB,CAAA;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAKlE,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAkBpF,KAAK,iBAAiB,GAAG,yBAAyB,CAAC,KAAK,GAAG;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;CAC7C,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,2BAA4B,YAAW,QAAQ,CAAC,eAAe;IAS5E,OAAO,CAAC,QAAQ;IAEhB,OAAO,CAAC,OAAO;IAVnB,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,YAAY,CAAC,CAAQ;IAC7B,OAAO,CAAC,SAAS,CAAC,CAAQ;IAC1B,OAAO,CAAC,gBAAgB,CAAC,CAAQ;IACjC,OAAO,CAAC,wBAAwB,CAAC,CAAS;gBAG9B,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EACzD,YAAY,EAAE,YAAY,CAAC,gBAAgB,EACnC,OAAO,EAAE,OAAO,CAAC,UAAU;IA8FjC,SAAS,CAAE,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IA4ItF,UAAU;IA4DV,UAAU,CAAC,GAAG,EAAC,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAkBrD;;;OAGG;IACG,YAAY,CAAE,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAyBhE,qBAAqB,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KAAE;IAiFvH,WAAW,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAC,MAAM;IAoF3F,sBAAsB,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IAyCrE;;;OAGG;IACH,oBAAoB;IA6BpB,sBAAsB,CAAC,QAAQ,CAAC,EAAC,MAAM,EAAE,SAAS,CAAC,EAAC,MAAM,EAAE,eAAe,CAAC,EAAC,MAAM;CAQtF"}
package/build/launcher.js CHANGED
@@ -57,6 +57,12 @@ class BrowserstackLauncherService {
57
57
  const extensionCaps = Object.keys(capability).filter((cap) => cap.includes(':'));
58
58
  if (extensionCaps.length) {
59
59
  capability['bstack:options'] = { wdioService: package_json_1.version };
60
+ if (!(0, util_2.isUndefined)(capability['browserstack.accessibility'])) {
61
+ this._accessibilityAutomation || (this._accessibilityAutomation = (0, util_2.isTrue)(capability['browserstack.accessibility']));
62
+ }
63
+ else if ((0, util_2.isTrue)(this._options.accessibility)) {
64
+ capability['bstack:options'].accessibility = true;
65
+ }
60
66
  }
61
67
  else if ((0, util_2.shouldAddServiceVersion)(this._config, this._options.testObservability)) {
62
68
  capability['browserstack.wdioService'] = package_json_1.version;
@@ -71,6 +77,12 @@ class BrowserstackLauncherService {
71
77
  this._projectName = capability['bstack:options'].projectName;
72
78
  this._buildTag = capability['bstack:options'].buildTag;
73
79
  this._buildIdentifier = capability['bstack:options'].buildIdentifier;
80
+ if (!(0, util_2.isUndefined)(capability['bstack:options'].accessibility)) {
81
+ this._accessibilityAutomation || (this._accessibilityAutomation = (0, util_2.isTrue)(capability['bstack:options'].accessibility));
82
+ }
83
+ else if ((0, util_2.isTrue)(this._options.accessibility)) {
84
+ capability['bstack:options'].accessibility = ((0, util_2.isTrue)(this._options.accessibility));
85
+ }
74
86
  }
75
87
  });
76
88
  }
@@ -81,6 +93,12 @@ class BrowserstackLauncherService {
81
93
  const extensionCaps = Object.keys(caps.capabilities).filter((cap) => cap.includes(':'));
82
94
  if (extensionCaps.length) {
83
95
  caps.capabilities['bstack:options'] = { wdioService: package_json_1.version };
96
+ if (!(0, util_2.isUndefined)(caps.capabilities['browserstack.accessibility'])) {
97
+ this._accessibilityAutomation || (this._accessibilityAutomation = (0, util_2.isTrue)(caps.capabilities['browserstack.accessibility']));
98
+ }
99
+ else if ((0, util_2.isTrue)(this._options.accessibility)) {
100
+ caps.capabilities['bstack:options'] = { wdioService: package_json_1.version, accessibility: ((0, util_2.isTrue)(this._options.accessibility)) };
101
+ }
84
102
  }
85
103
  else if ((0, util_2.shouldAddServiceVersion)(this._config, this._options.testObservability)) {
86
104
  caps.capabilities['browserstack.wdioService'] = package_json_1.version;
@@ -95,12 +113,20 @@ class BrowserstackLauncherService {
95
113
  this._projectName = bstackOptions.projectName;
96
114
  this._buildTag = bstackOptions.buildTag;
97
115
  this._buildIdentifier = bstackOptions.buildIdentifier;
116
+ if (!(0, util_2.isUndefined)(bstackOptions.accessibility)) {
117
+ this._accessibilityAutomation || (this._accessibilityAutomation = (0, util_2.isTrue)(bstackOptions.accessibility));
118
+ }
119
+ else if ((0, util_2.isTrue)(this._options.accessibility)) {
120
+ bstackOptions.accessibility = (0, util_2.isTrue)(this._options.accessibility);
121
+ }
98
122
  }
99
123
  });
100
124
  }
101
125
  if (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT) {
102
126
  performance_tester_1.default.startMonitoring('performance-report-launcher.csv');
103
127
  }
128
+ this._accessibilityAutomation || (this._accessibilityAutomation = (0, util_2.isTrue)(this._options.accessibility));
129
+ this._options.accessibility = this._accessibilityAutomation;
104
130
  // by default observability will be true unless specified as false
105
131
  this._options.testObservability = this._options.testObservability == false ? false : true;
106
132
  if (this._options.testObservability &&
@@ -161,6 +187,37 @@ class BrowserstackLauncherService {
161
187
  * e.g., ${BUILD_NUMBER} and ${DATE_TIME}
162
188
  */
163
189
  this._handleBuildIdentifier(capabilities);
190
+ // remove accessibilityOptions from the capabilities if present
191
+ this._updateObjectTypeCaps(capabilities, 'accessibilityOptions');
192
+ if (this._accessibilityAutomation) {
193
+ const scannerVersion = await (0, util_2.createAccessibilityTestRun)(this._options, this._config, {
194
+ projectName: this._projectName,
195
+ buildName: this._buildName,
196
+ buildTag: this._buildTag,
197
+ bstackServiceVersion: package_json_1.version,
198
+ buildIdentifier: this._buildIdentifier,
199
+ accessibilityOptions: this._options.accessibilityOptions
200
+ });
201
+ if (scannerVersion) {
202
+ process.env.BSTACK_A11Y_SCANNER_VERSION = scannerVersion;
203
+ }
204
+ log.debug(`Accessibility scannerVersion ${scannerVersion}`);
205
+ }
206
+ if (this._options.accessibilityOptions) {
207
+ const filteredOpts = Object.keys(this._options.accessibilityOptions)
208
+ .filter(key => !constants_1.NOT_ALLOWED_KEYS_IN_CAPS.includes(key))
209
+ .reduce((opts, key) => {
210
+ var _a;
211
+ return {
212
+ ...opts,
213
+ [key]: (_a = this._options.accessibilityOptions) === null || _a === void 0 ? void 0 : _a[key]
214
+ };
215
+ }, {});
216
+ this._updateObjectTypeCaps(capabilities, 'accessibilityOptions', filteredOpts);
217
+ }
218
+ else if ((0, util_2.isAccessibilityAutomationSession)(this._accessibilityAutomation)) {
219
+ this._updateObjectTypeCaps(capabilities, 'accessibilityOptions', {});
220
+ }
164
221
  if (this._options.testObservability) {
165
222
  log.debug('Sending launch start event');
166
223
  await (0, util_2.launchTestSession)(this._options, this._config, {
@@ -212,6 +269,11 @@ class BrowserstackLauncherService {
212
269
  });
213
270
  }
214
271
  async onComplete() {
272
+ if ((0, util_2.isAccessibilityAutomationSession)(this._accessibilityAutomation)) {
273
+ await (0, util_2.stopAccessibilityTestRun)().catch((error) => {
274
+ log.error(`Exception in stop accessibility test run: ${error}`);
275
+ });
276
+ }
215
277
  if (this._options.testObservability) {
216
278
  log.debug('Sending stop launch event');
217
279
  await (0, util_2.stopBuildUpstream)();
@@ -299,6 +361,96 @@ class BrowserstackLauncherService {
299
361
  }
300
362
  return app;
301
363
  }
364
+ _updateObjectTypeCaps(capabilities, capType, value) {
365
+ try {
366
+ if (Array.isArray(capabilities)) {
367
+ capabilities
368
+ .flatMap((c) => {
369
+ if (Object.values(c).length > 0 && Object.values(c).every(c => typeof c === 'object' && c.capabilities)) {
370
+ return Object.values(c).map((o) => o.capabilities);
371
+ }
372
+ return c;
373
+ })
374
+ .forEach((capability) => {
375
+ if (!capability['bstack:options']) {
376
+ const extensionCaps = Object.keys(capability).filter((cap) => cap.includes(':'));
377
+ if (extensionCaps.length) {
378
+ if (capType === 'accessibilityOptions' && value) {
379
+ capability['bstack:options'] = { accessibilityOptions: value };
380
+ }
381
+ }
382
+ else if (capType === 'accessibilityOptions') {
383
+ if (value) {
384
+ const accessibilityOpts = { ...value };
385
+ if (capability === null || capability === void 0 ? void 0 : capability.accessibility) {
386
+ accessibilityOpts.authToken = process.env.BSTACK_A11Y_JWT;
387
+ accessibilityOpts.scannerVersion = process.env.BSTACK_A11Y_SCANNER_VERSION;
388
+ }
389
+ capability['browserstack.accessibilityOptions'] = accessibilityOpts;
390
+ }
391
+ else {
392
+ delete capability['browserstack.accessibilityOptions'];
393
+ }
394
+ }
395
+ }
396
+ else if (capType === 'accessibilityOptions') {
397
+ if (value) {
398
+ const accessibilityOpts = { ...value };
399
+ if (capability['bstack:options'].accessibility) {
400
+ accessibilityOpts.authToken = process.env.BSTACK_A11Y_JWT;
401
+ accessibilityOpts.scannerVersion = process.env.BSTACK_A11Y_SCANNER_VERSION;
402
+ }
403
+ capability['bstack:options'].accessibilityOptions = accessibilityOpts;
404
+ }
405
+ else {
406
+ delete capability['bstack:options'].accessibilityOptions;
407
+ }
408
+ }
409
+ });
410
+ }
411
+ else if (typeof capabilities === 'object') {
412
+ Object.entries(capabilities).forEach(([, caps]) => {
413
+ if (!caps.capabilities['bstack:options']) {
414
+ const extensionCaps = Object.keys(caps.capabilities).filter((cap) => cap.includes(':'));
415
+ if (extensionCaps.length) {
416
+ if (capType === 'accessibilityOptions' && value) {
417
+ caps.capabilities['bstack:options'] = { accessibilityOptions: value };
418
+ }
419
+ }
420
+ else if (capType === 'accessibilityOptions') {
421
+ if (value) {
422
+ const accessibilityOpts = { ...value };
423
+ if (caps.capabilities['browserstack.accessibility']) {
424
+ accessibilityOpts.authToken = process.env.BSTACK_A11Y_JWT;
425
+ accessibilityOpts.scannerVersion = process.env.BSTACK_A11Y_SCANNER_VERSION;
426
+ }
427
+ caps.capabilities['browserstack.accessibilityOptions'] = accessibilityOpts;
428
+ }
429
+ else {
430
+ delete caps.capabilities['browserstack.accessibilityOptions'];
431
+ }
432
+ }
433
+ }
434
+ else if (capType === 'accessibilityOptions') {
435
+ if (value) {
436
+ const accessibilityOpts = { ...value };
437
+ if (caps.capabilities['bstack:options'].accessibility) {
438
+ accessibilityOpts.authToken = process.env.BSTACK_A11Y_JWT;
439
+ accessibilityOpts.scannerVersion = process.env.BSTACK_A11Y_SCANNER_VERSION;
440
+ }
441
+ caps.capabilities['bstack:options'].accessibilityOptions = accessibilityOpts;
442
+ }
443
+ else {
444
+ delete caps.capabilities['bstack:options'].accessibilityOptions;
445
+ }
446
+ }
447
+ });
448
+ }
449
+ }
450
+ catch (error) {
451
+ log.debug(`Exception while retrieving capability value. Error - ${error}`);
452
+ }
453
+ }
302
454
  _updateCaps(capabilities, capType, value) {
303
455
  if (Array.isArray(capabilities)) {
304
456
  capabilities.forEach((capability) => {
@@ -0,0 +1,2 @@
1
+ export declare const configure: (config: any, layouts: any) => Function;
2
+ //# sourceMappingURL=log4jsAppender.d.ts.map