@wdio/browserstack-service 8.16.6 → 8.16.7

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.
@@ -0,0 +1,38 @@
1
+ import type { Capabilities, Frameworks } from '@wdio/types';
2
+ import type { ITestCaseHookParameter } from './cucumber-types.js';
3
+ declare class _AccessibilityHandler {
4
+ private _browser;
5
+ private _capabilities;
6
+ private _framework?;
7
+ private _accessibilityAutomation?;
8
+ private _accessibilityOpts?;
9
+ private _platformA11yMeta;
10
+ private _caps;
11
+ private _suiteFile?;
12
+ private _accessibility?;
13
+ private _accessibilityOptions?;
14
+ private _testMetadata;
15
+ constructor(_browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser, _capabilities: Capabilities.RemoteCapability, isAppAutomate?: boolean, _framework?: string | undefined, _accessibilityAutomation?: string | boolean | undefined, _accessibilityOpts?: {
16
+ [key: string]: any;
17
+ } | undefined);
18
+ setSuiteFile(filename: string): void;
19
+ _getCapabilityValue(caps: Capabilities.RemoteCapability, capType: string, legacyCapType: string): WebdriverIO.SafaridriverOptions | undefined;
20
+ before(): Promise<void>;
21
+ beforeTest(suiteTitle: string | undefined, test: Frameworks.Test): Promise<void>;
22
+ afterTest(suiteTitle: string | undefined, test: Frameworks.Test): Promise<void>;
23
+ /**
24
+ * Cucumber Only
25
+ */
26
+ beforeScenario(world: ITestCaseHookParameter): Promise<void>;
27
+ afterScenario(world: ITestCaseHookParameter): Promise<void>;
28
+ private sendTestStartEvent;
29
+ private sendTestForceStopEvent;
30
+ private sendTestStopEvent;
31
+ private getIdentifier;
32
+ private shouldRunTestHooks;
33
+ private checkIfPageOpened;
34
+ }
35
+ declare const AccessibilityHandler: typeof _AccessibilityHandler;
36
+ type AccessibilityHandler = _AccessibilityHandler;
37
+ export default AccessibilityHandler;
38
+ //# sourceMappingURL=accessibility-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessibility-handler.d.ts","sourceRoot":"","sources":["../src/accessibility-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE3D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAkBjE,cAAM,qBAAqB;IASnB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,aAAa;IAErB,OAAO,CAAC,UAAU,CAAC;IACnB,OAAO,CAAC,wBAAwB,CAAC;IACjC,OAAO,CAAC,kBAAkB,CAAC;IAb/B,OAAO,CAAC,iBAAiB,CAAyB;IAClD,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,qBAAqB,CAAC,CAAyB;IACvD,OAAO,CAAC,aAAa,CAA8B;gBAGvC,QAAQ,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,kBAAkB,EAC9D,aAAa,EAAE,YAAY,CAAC,gBAAgB,EACpD,aAAa,CAAC,EAAE,OAAO,EACf,UAAU,CAAC,oBAAQ,EACnB,wBAAwB,CAAC,8BAAkB,EAC3C,kBAAkB,CAAC;;iBAAyB;IAgBxD,YAAY,CAAC,QAAQ,EAAE,MAAM;IAI7B,mBAAmB,CAAC,IAAI,EAAE,YAAY,CAAC,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;IA6BzF,MAAM;IAmBN,UAAU,CAAE,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI;IAiCjE,SAAS,CAAE,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI;IA0CtE;;MAEE;IACI,cAAc,CAAE,KAAK,EAAE,sBAAsB;IAiC7C,aAAa,CAAE,KAAK,EAAE,sBAAsB;IA8ClD,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,sBAAsB;IAI9B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,kBAAkB;YAOZ,iBAAiB;CAiBlC;AAGD,QAAA,MAAM,oBAAoB,EAAE,OAAO,qBAAoE,CAAA;AACvG,KAAK,oBAAoB,GAAG,qBAAqB,CAAA;AAEjD,eAAe,oBAAoB,CAAA"}
@@ -0,0 +1,260 @@
1
+ import logger from '@wdio/logger';
2
+ import { getA11yResultsSummary, getA11yResults, getUniqueIdentifier, getUniqueIdentifierForCucumber, isAccessibilityAutomationSession, isBrowserstackSession, o11yClassErrorHandler, shouldScanTestForAccessibility, validateCapsWithA11y, isTrue, } from './util.js';
3
+ import { testForceStop, testStartEvent, testStop } from './scripts/test-event-scripts.js';
4
+ const log = logger('@wdio/browserstack-service');
5
+ class _AccessibilityHandler {
6
+ _browser;
7
+ _capabilities;
8
+ _framework;
9
+ _accessibilityAutomation;
10
+ _accessibilityOpts;
11
+ _platformA11yMeta;
12
+ _caps;
13
+ _suiteFile;
14
+ _accessibility;
15
+ _accessibilityOptions;
16
+ _testMetadata = {};
17
+ constructor(_browser, _capabilities, isAppAutomate, _framework, _accessibilityAutomation, _accessibilityOpts) {
18
+ this._browser = _browser;
19
+ this._capabilities = _capabilities;
20
+ this._framework = _framework;
21
+ this._accessibilityAutomation = _accessibilityAutomation;
22
+ this._accessibilityOpts = _accessibilityOpts;
23
+ const caps = this._browser.capabilities;
24
+ this._platformA11yMeta = {
25
+ browser_name: caps.browserName,
26
+ browser_version: caps?.browserVersion || caps?.version || 'latest',
27
+ os_name: this._getCapabilityValue(_capabilities, 'os', 'os'),
28
+ os_version: this._getCapabilityValue(_capabilities, 'osVersion', 'os_version')
29
+ };
30
+ this._caps = _capabilities;
31
+ this._accessibility = isTrue(_accessibilityAutomation);
32
+ this._accessibilityOptions = _accessibilityOpts;
33
+ }
34
+ setSuiteFile(filename) {
35
+ this._suiteFile = filename;
36
+ }
37
+ _getCapabilityValue(caps, capType, legacyCapType) {
38
+ if (caps) {
39
+ if (capType === 'accessibility') {
40
+ if (caps['bstack:options'] && (isTrue(caps['bstack:options']?.accessibility))) {
41
+ return caps['bstack:options']?.accessibility;
42
+ }
43
+ else if (isTrue(caps['browserstack.accessibility'])) {
44
+ return caps['browserstack.accessibility'];
45
+ }
46
+ }
47
+ else if (capType === 'deviceName') {
48
+ if (caps['bstack:options'] && caps['bstack:options']?.deviceName) {
49
+ return caps['bstack:options']?.deviceName;
50
+ }
51
+ else if (caps['bstack:options'] && caps['bstack:options']?.device) {
52
+ return caps['bstack:options']?.device;
53
+ }
54
+ else if (caps['appium:deviceName']) {
55
+ return caps['appium:deviceName'];
56
+ }
57
+ }
58
+ else if (capType === 'goog:chromeOptions' && caps['goog:chromeOptions']) {
59
+ return caps['goog:chromeOptions'];
60
+ }
61
+ else {
62
+ const bstackOptions = caps['bstack:options'];
63
+ if (bstackOptions && bstackOptions?.[capType]) {
64
+ return bstackOptions?.[capType];
65
+ }
66
+ else if (caps[legacyCapType]) {
67
+ return caps[legacyCapType];
68
+ }
69
+ }
70
+ }
71
+ }
72
+ async before() {
73
+ this._accessibility = isTrue(this._getCapabilityValue(this._caps, 'accessibility', 'browserstack.accessibility'));
74
+ if (isBrowserstackSession(this._browser) && isAccessibilityAutomationSession(this._accessibility)) {
75
+ const deviceName = this._getCapabilityValue(this._caps, 'deviceName', 'device');
76
+ const chromeOptions = this._getCapabilityValue(this._caps, 'goog:chromeOptions', '');
77
+ this._accessibility = validateCapsWithA11y(deviceName, this._platformA11yMeta, chromeOptions);
78
+ }
79
+ this._browser.getAccessibilityResultsSummary = async () => {
80
+ return await getA11yResultsSummary(this._browser, isBrowserstackSession(this._browser), this._accessibility);
81
+ };
82
+ this._browser.getAccessibilityResults = async () => {
83
+ return await getA11yResults(this._browser, isBrowserstackSession(this._browser), this._accessibility);
84
+ };
85
+ }
86
+ async beforeTest(suiteTitle, test) {
87
+ if (this._framework !== 'mocha' ||
88
+ !this.shouldRunTestHooks(this._browser, this._accessibility)) {
89
+ return;
90
+ }
91
+ const shouldScanTest = shouldScanTestForAccessibility(suiteTitle, test.title, this._accessibilityOptions);
92
+ const testIdentifier = this.getIdentifier(test);
93
+ const isPageOpened = await this.checkIfPageOpened(this._browser, testIdentifier, shouldScanTest);
94
+ if (!isPageOpened) {
95
+ return;
96
+ }
97
+ try {
98
+ if (shouldScanTest) {
99
+ log.info('Setup for Accessibility testing has started. Automate test case execution will begin momentarily.');
100
+ await this.sendTestStartEvent(this._browser);
101
+ }
102
+ else {
103
+ await this.sendTestForceStopEvent(this._browser);
104
+ }
105
+ this._testMetadata[testIdentifier].accessibilityScanStarted = shouldScanTest;
106
+ if (shouldScanTest) {
107
+ log.info('Automate test case execution has started.');
108
+ }
109
+ }
110
+ catch (error) {
111
+ log.error(`Exception in starting accessibility automation scan for this test case ${error}`);
112
+ }
113
+ }
114
+ async afterTest(suiteTitle, test) {
115
+ if (this._framework !== 'mocha' ||
116
+ !this.shouldRunTestHooks(this._browser, this._accessibility)) {
117
+ return;
118
+ }
119
+ try {
120
+ const testIdentifier = this.getIdentifier(test);
121
+ const accessibilityScanStarted = this._testMetadata[testIdentifier]?.accessibilityScanStarted;
122
+ const shouldScanTestForAccessibility = this._testMetadata[testIdentifier]?.scanTestForAccessibility;
123
+ if (!accessibilityScanStarted) {
124
+ return;
125
+ }
126
+ if (shouldScanTestForAccessibility) {
127
+ log.info('Automate test case execution has ended. Processing for accessibility testing is underway. ');
128
+ }
129
+ const dataForExtension = {
130
+ saveResults: shouldScanTestForAccessibility,
131
+ testDetails: {
132
+ 'name': test.title,
133
+ 'testRunId': process.env.BS_A11Y_TEST_RUN_ID,
134
+ 'filePath': this._suiteFile,
135
+ 'scopeList': [suiteTitle, test.title]
136
+ },
137
+ platform: this._platformA11yMeta
138
+ };
139
+ await this.sendTestStopEvent(this._browser, dataForExtension);
140
+ if (shouldScanTestForAccessibility) {
141
+ log.info('Accessibility testing for this test case has ended.');
142
+ }
143
+ }
144
+ catch (error) {
145
+ log.error(`Accessibility results could not be processed for the test case ${test.title}. Error :`, error);
146
+ }
147
+ }
148
+ /**
149
+ * Cucumber Only
150
+ */
151
+ async beforeScenario(world) {
152
+ if (!this.shouldRunTestHooks(this._browser, this._accessibility)) {
153
+ return;
154
+ }
155
+ const pickleData = world.pickle;
156
+ const gherkinDocument = world.gherkinDocument;
157
+ const featureData = gherkinDocument.feature;
158
+ const uniqueId = getUniqueIdentifierForCucumber(world);
159
+ const shouldScanScenario = shouldScanTestForAccessibility(featureData?.name, pickleData.name, this._accessibilityOptions);
160
+ const isPageOpened = await this.checkIfPageOpened(this._browser, uniqueId, shouldScanScenario);
161
+ if (!isPageOpened) {
162
+ return;
163
+ }
164
+ try {
165
+ if (shouldScanScenario) {
166
+ log.info('Setup for Accessibility testing has started. Automate test case execution will begin momentarily.');
167
+ await this.sendTestStartEvent(this._browser);
168
+ }
169
+ else {
170
+ await this.sendTestForceStopEvent(this._browser);
171
+ }
172
+ this._testMetadata[uniqueId].accessibilityScanStarted = shouldScanScenario;
173
+ if (shouldScanScenario) {
174
+ log.info('Automate test case execution has started.');
175
+ }
176
+ }
177
+ catch (error) {
178
+ log.error(`Exception in starting accessibility automation scan for this test case ${error}`);
179
+ }
180
+ }
181
+ async afterScenario(world) {
182
+ if (!this.shouldRunTestHooks(this._browser, this._accessibility)) {
183
+ return;
184
+ }
185
+ const pickleData = world.pickle;
186
+ try {
187
+ const gherkinDocument = world.gherkinDocument;
188
+ const featureData = gherkinDocument.feature;
189
+ const uniqueId = getUniqueIdentifierForCucumber(world);
190
+ const accessibilityScanStarted = this._testMetadata[uniqueId]?.accessibilityScanStarted;
191
+ const shouldScanTestForAccessibility = this._testMetadata[uniqueId]?.scanTestForAccessibility;
192
+ if (!accessibilityScanStarted) {
193
+ return;
194
+ }
195
+ if (shouldScanTestForAccessibility) {
196
+ log.info('Automate test case execution has ended. Processing for accessibility testing is underway. ');
197
+ }
198
+ const dataForExtension = {
199
+ saveResults: shouldScanTestForAccessibility,
200
+ testDetails: {
201
+ 'name': pickleData.name,
202
+ 'testRunId': process.env.BS_A11Y_TEST_RUN_ID,
203
+ 'filePath': gherkinDocument.uri,
204
+ 'scopeList': [featureData?.name, pickleData.name]
205
+ },
206
+ platform: this._platformA11yMeta
207
+ };
208
+ await this.sendTestStopEvent(this._browser, dataForExtension);
209
+ if (shouldScanTestForAccessibility) {
210
+ log.info('Accessibility testing for this test case has ended.');
211
+ }
212
+ }
213
+ catch (error) {
214
+ log.error(`Accessibility results could not be processed for the test case ${pickleData.name}. Error :`, error);
215
+ }
216
+ }
217
+ /*
218
+ * private methods
219
+ */
220
+ sendTestStartEvent(browser) {
221
+ return browser.executeAsync(testStartEvent);
222
+ }
223
+ sendTestForceStopEvent(browser) {
224
+ return browser.execute(testForceStop);
225
+ }
226
+ sendTestStopEvent(browser, dataForExtension) {
227
+ return browser.executeAsync(testStop, dataForExtension);
228
+ }
229
+ getIdentifier(test) {
230
+ if ('pickle' in test) {
231
+ return getUniqueIdentifierForCucumber(test);
232
+ }
233
+ return getUniqueIdentifier(test, this._framework);
234
+ }
235
+ shouldRunTestHooks(browser, isAccessibility) {
236
+ if (!browser) {
237
+ return false;
238
+ }
239
+ return isBrowserstackSession(browser) && isAccessibilityAutomationSession(isAccessibility);
240
+ }
241
+ async checkIfPageOpened(browser, testIdentifier, shouldScanTest) {
242
+ let pageOpen = false;
243
+ this._testMetadata[testIdentifier] = {
244
+ scanTestForAccessibility: shouldScanTest,
245
+ accessibilityScanStarted: true
246
+ };
247
+ try {
248
+ const currentURL = await browser.getUrl();
249
+ const url = new URL(currentURL);
250
+ pageOpen = url?.protocol === 'http:' || url?.protocol === 'https:';
251
+ }
252
+ catch (e) {
253
+ pageOpen = false;
254
+ }
255
+ return pageOpen;
256
+ }
257
+ }
258
+ // https://github.com/microsoft/TypeScript/issues/6543
259
+ const AccessibilityHandler = o11yClassErrorHandler(_AccessibilityHandler);
260
+ export default AccessibilityHandler;
@@ -13,4 +13,6 @@ export declare const BATCH_EVENT_TYPES: string[];
13
13
  export declare const DEFAULT_WAIT_TIMEOUT_FOR_PENDING_UPLOADS = 5000;
14
14
  export declare const DEFAULT_WAIT_INTERVAL_FOR_PENDING_UPLOADS = 100;
15
15
  export declare const BSTACK_SERVICE_VERSION: any;
16
+ export declare const ACCESSIBILITY_API_URL = "https://accessibility.browserstack.com/api";
17
+ export declare const NOT_ALLOWED_KEYS_IN_CAPS: string[];
16
18
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAKpD,eAAO,MAAM,mBAAmB,qHAStB,CAAA;AAEV,eAAO,MAAM,mBAAmB,UAI/B,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,kBAAkB,CAIvD,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,OAAO,OAAoC,CAAA;AAEvE,eAAO,MAAM,aAAa,qDAAqD,CAAA;AAC/E,eAAO,MAAM,mBAAmB,iBAAiB,CAAA;AACjD,eAAO,MAAM,mBAAmB,iBAAiB,CAAA;AACjD,eAAO,MAAM,wBAAwB,uBAAuB,CAAA;AAC5D,eAAO,MAAM,eAAe,OAAO,CAAA;AACnC,eAAO,MAAM,mBAAmB,OAAO,CAAA;AACvC,eAAO,MAAM,iBAAiB,UAAgH,CAAA;AAC9I,eAAO,MAAM,wCAAwC,OAAO,CAAA;AAC5D,eAAO,MAAM,yCAAyC,MAAM,CAAA;AAC5D,eAAO,MAAM,sBAAsB,KAAuB,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAKpD,eAAO,MAAM,mBAAmB,qHAStB,CAAA;AAEV,eAAO,MAAM,mBAAmB,UAI/B,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,kBAAkB,CAKvD,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,OAAO,OAAoC,CAAA;AAEvE,eAAO,MAAM,aAAa,qDAAqD,CAAA;AAC/E,eAAO,MAAM,mBAAmB,iBAAiB,CAAA;AACjD,eAAO,MAAM,mBAAmB,iBAAiB,CAAA;AACjD,eAAO,MAAM,wBAAwB,uBAAuB,CAAA;AAC5D,eAAO,MAAM,eAAe,OAAO,CAAA;AACnC,eAAO,MAAM,mBAAmB,OAAO,CAAA;AACvC,eAAO,MAAM,iBAAiB,UAAgH,CAAA;AAC9I,eAAO,MAAM,wCAAwC,OAAO,CAAA;AAC5D,eAAO,MAAM,yCAAyC,MAAM,CAAA;AAC5D,eAAO,MAAM,sBAAsB,KAAuB,CAAA;AAE1D,eAAO,MAAM,qBAAqB,+CAA+C,CAAA;AACjF,eAAO,MAAM,wBAAwB,UAA6D,CAAA"}
@@ -19,7 +19,8 @@ export const VALID_APP_EXTENSION = [
19
19
  export const DEFAULT_OPTIONS = {
20
20
  setSessionName: true,
21
21
  setSessionStatus: true,
22
- testObservability: true
22
+ testObservability: true,
23
+ accessibility: false
23
24
  };
24
25
  export const consoleHolder = Object.assign({}, console);
25
26
  export const DATA_ENDPOINT = 'https://collector-observability.browserstack.com';
@@ -32,3 +33,5 @@ export const BATCH_EVENT_TYPES = ['LogCreated', 'TestRunStarted', 'TestRunFinish
32
33
  export const DEFAULT_WAIT_TIMEOUT_FOR_PENDING_UPLOADS = 5000; // 5s
33
34
  export const DEFAULT_WAIT_INTERVAL_FOR_PENDING_UPLOADS = 100; // 100ms
34
35
  export const BSTACK_SERVICE_VERSION = bstackServiceVersion;
36
+ export const ACCESSIBILITY_API_URL = 'https://accessibility.browserstack.com/api';
37
+ export const NOT_ALLOWED_KEYS_IN_CAPS = ['includeTagsInTestingScope', 'excludeTagsInTestingScope'];
@@ -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;AAG/D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAGlE,OAAO,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAavF,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;IAgFjC,SAAS,CAAE,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IA0GtF,UAAU;IAsDV,UAAU,CAAC,GAAG,EAAC,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAsBrD;;;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;IA4F3F,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;AAG/D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAGlE,OAAO,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAkBvF,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;IAwGjC,SAAS,CAAE,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IA8ItF,UAAU;IA4DV,UAAU,CAAC,GAAG,EAAC,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAsBrD;;;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,EAAE,MAAM;IA4F5F,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
@@ -9,8 +9,8 @@ import os from 'node:os';
9
9
  import * as BrowserstackLocalLauncher from 'browserstack-local';
10
10
  import logger from '@wdio/logger';
11
11
  import PerformanceTester from './performance-tester.js';
12
- import { BSTACK_SERVICE_VERSION, VALID_APP_EXTENSION } from './constants.js';
13
- import { launchTestSession, shouldAddServiceVersion, stopBuildUpstream, getCiInfo, isBStackSession, } from './util.js';
12
+ import { BSTACK_SERVICE_VERSION, NOT_ALLOWED_KEYS_IN_CAPS, VALID_APP_EXTENSION } from './constants.js';
13
+ import { launchTestSession, createAccessibilityTestRun, shouldAddServiceVersion, stopBuildUpstream, getCiInfo, isBStackSession, isUndefined, isAccessibilityAutomationSession, stopAccessibilityTestRun, isTrue } from './util.js';
14
14
  import CrashReporter from './crash-reporter.js';
15
15
  const log = logger('@wdio/browserstack-service');
16
16
  export default class BrowserstackLauncherService {
@@ -21,6 +21,7 @@ export default class BrowserstackLauncherService {
21
21
  _projectName;
22
22
  _buildTag;
23
23
  _buildIdentifier;
24
+ _accessibilityAutomation;
24
25
  constructor(_options, capabilities, _config) {
25
26
  this._options = _options;
26
27
  this._config = _config;
@@ -41,6 +42,12 @@ export default class BrowserstackLauncherService {
41
42
  const extensionCaps = Object.keys(capability).filter((cap) => cap.includes(':'));
42
43
  if (extensionCaps.length) {
43
44
  capability['bstack:options'] = { wdioService: BSTACK_SERVICE_VERSION };
45
+ if (!isUndefined(capability['browserstack.accessibility'])) {
46
+ this._accessibilityAutomation ||= isTrue(capability['browserstack.accessibility']);
47
+ }
48
+ else if (isTrue(this._options.accessibility)) {
49
+ capability['bstack:options'].accessibility = true;
50
+ }
44
51
  }
45
52
  else if (shouldAddServiceVersion(this._config, this._options.testObservability)) {
46
53
  capability['browserstack.wdioService'] = BSTACK_SERVICE_VERSION;
@@ -56,6 +63,12 @@ export default class BrowserstackLauncherService {
56
63
  this._projectName = capability['bstack:options'].projectName;
57
64
  this._buildTag = capability['bstack:options'].buildTag;
58
65
  this._buildIdentifier = capability['bstack:options'].buildIdentifier;
66
+ if (!isUndefined(capability['bstack:options'].accessibility)) {
67
+ this._accessibilityAutomation ||= isTrue(capability['bstack:options'].accessibility);
68
+ }
69
+ else if (isTrue(this._options.accessibility)) {
70
+ capability['bstack:options'].accessibility = (isTrue(this._options.accessibility));
71
+ }
59
72
  }
60
73
  });
61
74
  }
@@ -66,6 +79,12 @@ export default class BrowserstackLauncherService {
66
79
  const extensionCaps = Object.keys(caps.capabilities).filter((cap) => cap.includes(':'));
67
80
  if (extensionCaps.length) {
68
81
  caps.capabilities['bstack:options'] = { wdioService: BSTACK_SERVICE_VERSION };
82
+ if (!isUndefined(caps.capabilities['browserstack.accessibility'])) {
83
+ this._accessibilityAutomation ||= isTrue(caps.capabilities['browserstack.accessibility']);
84
+ }
85
+ else if (isTrue(this._options.accessibility)) {
86
+ caps.capabilities['bstack:options'] = { wdioService: BSTACK_SERVICE_VERSION, accessibility: (isTrue(this._options.accessibility)) };
87
+ }
69
88
  }
70
89
  else if (shouldAddServiceVersion(this._config, this._options.testObservability)) {
71
90
  caps.capabilities['browserstack.wdioService'] = BSTACK_SERVICE_VERSION;
@@ -80,12 +99,20 @@ export default class BrowserstackLauncherService {
80
99
  this._projectName = bstackOptions.projectName;
81
100
  this._buildTag = bstackOptions.buildTag;
82
101
  this._buildIdentifier = bstackOptions.buildIdentifier;
102
+ if (!isUndefined(bstackOptions.accessibility)) {
103
+ this._accessibilityAutomation ||= isTrue(bstackOptions.accessibility);
104
+ }
105
+ else if (isTrue(this._options.accessibility)) {
106
+ bstackOptions.accessibility = isTrue(this._options.accessibility);
107
+ }
83
108
  }
84
109
  });
85
110
  }
86
111
  if (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT) {
87
112
  PerformanceTester.startMonitoring('performance-report-launcher.csv');
88
113
  }
114
+ this._accessibilityAutomation ||= isTrue(this._options.accessibility);
115
+ this._options.accessibility = this._accessibilityAutomation;
89
116
  // by default observability will be true unless specified as false
90
117
  this._options.testObservability = this._options.testObservability === false ? false : true;
91
118
  if (this._options.testObservability
@@ -146,6 +173,38 @@ export default class BrowserstackLauncherService {
146
173
  * e.g., ${BUILD_NUMBER} and ${DATE_TIME}
147
174
  */
148
175
  this._handleBuildIdentifier(capabilities);
176
+ // remove accessibilityOptions from the capabilities if present
177
+ this._updateObjectTypeCaps(capabilities, 'accessibilityOptions');
178
+ if (this._accessibilityAutomation) {
179
+ const scannerVersion = await createAccessibilityTestRun(this._options, this._config, {
180
+ projectName: this._projectName,
181
+ buildName: this._buildName,
182
+ buildTag: this._buildTag,
183
+ bstackServiceVersion: BSTACK_SERVICE_VERSION,
184
+ buildIdentifier: this._buildIdentifier,
185
+ accessibilityOptions: this._options.accessibilityOptions
186
+ });
187
+ if (scannerVersion) {
188
+ process.env.BSTACK_A11Y_SCANNER_VERSION = scannerVersion;
189
+ }
190
+ log.debug(`Accessibility scannerVersion ${scannerVersion}`);
191
+ }
192
+ if (this._options.accessibilityOptions) {
193
+ const filteredOpts = Object.keys(this._options.accessibilityOptions)
194
+ .filter(key => !NOT_ALLOWED_KEYS_IN_CAPS.includes(key))
195
+ .reduce((opts, key) => {
196
+ return {
197
+ ...opts,
198
+ [key]: this._options.accessibilityOptions?.[key]
199
+ };
200
+ }, {});
201
+ if (Object.keys(filteredOpts).length > 0) {
202
+ this._updateObjectTypeCaps(capabilities, 'accessibilityOptions', filteredOpts);
203
+ }
204
+ }
205
+ else if (isAccessibilityAutomationSession(this._accessibilityAutomation)) {
206
+ this._updateObjectTypeCaps(capabilities, 'accessibilityOptions', {});
207
+ }
149
208
  if (this._options.testObservability) {
150
209
  log.debug('Sending launch start event');
151
210
  await launchTestSession(this._options, this._config, {
@@ -197,6 +256,11 @@ export default class BrowserstackLauncherService {
197
256
  });
198
257
  }
199
258
  async onComplete() {
259
+ if (isAccessibilityAutomationSession(this._accessibilityAutomation)) {
260
+ await stopAccessibilityTestRun().catch((error) => {
261
+ log.error(`Exception in stop accessibility test run: ${error}`);
262
+ });
263
+ }
200
264
  if (this._options.testObservability) {
201
265
  log.debug('Sending stop launch event');
202
266
  await stopBuildUpstream();
@@ -285,6 +349,96 @@ export default class BrowserstackLauncherService {
285
349
  }
286
350
  return app;
287
351
  }
352
+ _updateObjectTypeCaps(capabilities, capType, value) {
353
+ try {
354
+ if (Array.isArray(capabilities)) {
355
+ capabilities
356
+ .flatMap((c) => {
357
+ if (Object.values(c).length > 0 && Object.values(c).every(c => typeof c === 'object' && c.capabilities)) {
358
+ return Object.values(c).map((o) => o.capabilities);
359
+ }
360
+ return c;
361
+ })
362
+ .forEach((capability) => {
363
+ if (!capability['bstack:options']) {
364
+ const extensionCaps = Object.keys(capability).filter((cap) => cap.includes(':'));
365
+ if (extensionCaps.length) {
366
+ if (capType === 'accessibilityOptions' && value) {
367
+ capability['bstack:options'] = { accessibilityOptions: value };
368
+ }
369
+ }
370
+ else if (capType === 'accessibilityOptions') {
371
+ if (value) {
372
+ const accessibilityOpts = { ...value };
373
+ if (capability?.accessibility) {
374
+ accessibilityOpts.authToken = process.env.BSTACK_A11Y_JWT;
375
+ accessibilityOpts.scannerVersion = process.env.BSTACK_A11Y_SCANNER_VERSION;
376
+ }
377
+ capability['browserstack.accessibilityOptions'] = accessibilityOpts;
378
+ }
379
+ else {
380
+ delete capability['browserstack.accessibilityOptions'];
381
+ }
382
+ }
383
+ }
384
+ else if (capType === 'accessibilityOptions') {
385
+ if (value) {
386
+ const accessibilityOpts = { ...value };
387
+ if (capability['bstack:options'].accessibility) {
388
+ accessibilityOpts.authToken = process.env.BSTACK_A11Y_JWT;
389
+ accessibilityOpts.scannerVersion = process.env.BSTACK_A11Y_SCANNER_VERSION;
390
+ }
391
+ capability['bstack:options'].accessibilityOptions = accessibilityOpts;
392
+ }
393
+ else {
394
+ delete capability['bstack:options'].accessibilityOptions;
395
+ }
396
+ }
397
+ });
398
+ }
399
+ else if (typeof capabilities === 'object') {
400
+ Object.entries(capabilities).forEach(([, caps]) => {
401
+ if (!caps.capabilities['bstack:options']) {
402
+ const extensionCaps = Object.keys(caps.capabilities).filter((cap) => cap.includes(':'));
403
+ if (extensionCaps.length) {
404
+ if (capType === 'accessibilityOptions' && value) {
405
+ caps.capabilities['bstack:options'] = { accessibilityOptions: value };
406
+ }
407
+ }
408
+ else if (capType === 'accessibilityOptions') {
409
+ if (value) {
410
+ const accessibilityOpts = { ...value };
411
+ if (caps.capabilities['browserstack.accessibility']) {
412
+ accessibilityOpts.authToken = process.env.BSTACK_A11Y_JWT;
413
+ accessibilityOpts.scannerVersion = process.env.BSTACK_A11Y_SCANNER_VERSION;
414
+ }
415
+ caps.capabilities['browserstack.accessibilityOptions'] = accessibilityOpts;
416
+ }
417
+ else {
418
+ delete caps.capabilities['browserstack.accessibilityOptions'];
419
+ }
420
+ }
421
+ }
422
+ else if (capType === 'accessibilityOptions') {
423
+ if (value) {
424
+ const accessibilityOpts = { ...value };
425
+ if (caps.capabilities['bstack:options'].accessibility) {
426
+ accessibilityOpts.authToken = process.env.BSTACK_A11Y_JWT;
427
+ accessibilityOpts.scannerVersion = process.env.BSTACK_A11Y_SCANNER_VERSION;
428
+ }
429
+ caps.capabilities['bstack:options'].accessibilityOptions = accessibilityOpts;
430
+ }
431
+ else {
432
+ delete caps.capabilities['bstack:options'].accessibilityOptions;
433
+ }
434
+ }
435
+ });
436
+ }
437
+ }
438
+ catch (error) {
439
+ log.debug(`Exception while retrieving capability value. Error - ${error}`);
440
+ }
441
+ }
288
442
  _updateCaps(capabilities, capType, value) {
289
443
  if (Array.isArray(capabilities)) {
290
444
  capabilities
@@ -0,0 +1,10 @@
1
+ export declare function testStartEvent(): void;
2
+ export declare function testForceStop(): void;
3
+ export declare function testStop(this: any): void;
4
+ export declare function accessibilityResults(): Promise<Array<{
5
+ [key: string]: any;
6
+ }>>;
7
+ export declare function accessibilityResultsSummary(): Promise<{
8
+ [key: string]: any;
9
+ }>;
10
+ //# sourceMappingURL=test-event-scripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-event-scripts.d.ts","sourceRoot":"","sources":["../../src/scripts/test-event-scripts.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,SAY7B;AAED,wBAAgB,aAAa,SAG5B;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,GAAG,QAgBjC;AAED,wBAAgB,oBAAoB,IAAK,OAAO,CAAC,KAAK,CAAC;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CAAE,CAAC,CAAC,CAc/E;AAED,wBAAgB,2BAA2B,IAAK,OAAO,CAAC;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CAAE,CAAC,CAc/E"}
@@ -0,0 +1,65 @@
1
+ export function testStartEvent() {
2
+ const callback = arguments[arguments.length - 1];
3
+ const fn = () => {
4
+ window.addEventListener('A11Y_TAP_STARTED', fn2);
5
+ const e = new CustomEvent('A11Y_FORCE_START');
6
+ window.dispatchEvent(e);
7
+ };
8
+ const fn2 = () => {
9
+ window.removeEventListener('A11Y_TAP_STARTED', fn);
10
+ callback();
11
+ };
12
+ fn();
13
+ }
14
+ export function testForceStop() {
15
+ const e = new CustomEvent('A11Y_FORCE_STOP');
16
+ window.dispatchEvent(e);
17
+ }
18
+ export function testStop() {
19
+ const callback = arguments[arguments.length - 1];
20
+ this.res = null;
21
+ if (arguments[0].saveResults) {
22
+ window.addEventListener('A11Y_TAP_TRANSPORTER', (event) => {
23
+ window.tapTransporterData = event.detail;
24
+ this.res = window.tapTransporterData;
25
+ callback(this.res);
26
+ });
27
+ }
28
+ const e = new CustomEvent('A11Y_TEST_END', { detail: arguments[0] });
29
+ window.dispatchEvent(e);
30
+ if (arguments[0].saveResults !== true) {
31
+ callback();
32
+ }
33
+ }
34
+ export function accessibilityResults() {
35
+ return new Promise(function (resolve, reject) {
36
+ try {
37
+ const event = new CustomEvent('A11Y_TAP_GET_RESULTS');
38
+ const fn = function (event) {
39
+ window.removeEventListener('A11Y_RESULTS_RESPONSE', fn);
40
+ resolve(event.detail.data);
41
+ };
42
+ window.addEventListener('A11Y_RESULTS_RESPONSE', fn);
43
+ window.dispatchEvent(event);
44
+ }
45
+ catch {
46
+ reject();
47
+ }
48
+ });
49
+ }
50
+ export function accessibilityResultsSummary() {
51
+ return new Promise(function (resolve, reject) {
52
+ try {
53
+ const event = new CustomEvent('A11Y_TAP_GET_RESULTS_SUMMARY');
54
+ const fn = function (event) {
55
+ window.removeEventListener('A11Y_RESULTS_SUMMARY_RESPONSE', fn);
56
+ resolve(event.detail.summary);
57
+ };
58
+ window.addEventListener('A11Y_RESULTS_SUMMARY_RESPONSE', fn);
59
+ window.dispatchEvent(event);
60
+ }
61
+ catch {
62
+ reject();
63
+ }
64
+ });
65
+ }
@@ -17,6 +17,8 @@ export default class BrowserstackService implements Services.ServiceInstance {
17
17
  private _observability;
18
18
  private _currentTest?;
19
19
  private _insightsHandler?;
20
+ private _accessibility;
21
+ private _accessibilityHandler?;
20
22
  constructor(options: BrowserstackConfig & Options.Testrunner, _caps: Capabilities.RemoteCapability, _config: Options.Testrunner);
21
23
  _updateCaps(fn: (caps: Capabilities.Capabilities | Capabilities.DesiredCapabilities) => void): void;
22
24
  beforeSession(config: Omit<Options.Testrunner, 'capabilities'>): void;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAW9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAmB,MAAM,YAAY,CAAA;AACxF,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAQhG,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,QAAQ,CAAC,eAAe;IAiBpE,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,OAAO;IAjBnB,OAAO,CAAC,eAAe,CAAmD;IAC1E,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,iBAAiB,CAAe;IACxC,OAAO,CAAC,gBAAgB,CAA4D;IACpF,OAAO,CAAC,QAAQ,CAAC,CAAqB;IACtC,OAAO,CAAC,WAAW,CAAC,CAAQ;IAC5B,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,QAAQ,CAAyC;IACzD,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,cAAc,CAAA;IACtB,OAAO,CAAC,YAAY,CAAC,CAA0C;IAC/D,OAAO,CAAC,gBAAgB,CAAC,CAAiB;gBAGtC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EACxC,KAAK,EAAE,YAAY,CAAC,gBAAgB,EACpC,OAAO,EAAE,OAAO,CAAC,UAAU;IAqBvC,WAAW,CAAE,EAAE,EAAE,CAAC,IAAI,EAAE,YAAY,CAAC,YAAY,GAAG,YAAY,CAAC,mBAAmB,KAAK,IAAI;IAU7F,aAAa,CAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC;IAgBzD,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO;IA+C/F;;;;;;OAMG;IACG,WAAW,CAAE,KAAK,EAAE,UAAU,CAAC,KAAK;IASpC,UAAU,CAAE,IAAI,EAAE,UAAU,CAAC,IAAI,GAAC,YAAY,EAAE,OAAO,EAAE,GAAG;IAO5D,SAAS,CAAE,IAAI,EAAE,UAAU,CAAC,IAAI,GAAC,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,UAAU;IAI9F,UAAU,CAAE,IAAI,EAAE,UAAU,CAAC,IAAI;IAoBjC,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,UAAU;IAS/E,KAAK,CAAE,MAAM,EAAE,MAAM;IA+B3B;;OAEG;IAEG,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAOjD;;;OAGG;IACG,cAAc,CAAE,KAAK,EAAE,sBAAsB;IAO7C,aAAa,CAAE,KAAK,EAAE,sBAAsB;IAsB5C,UAAU,CAAE,IAAI,EAAE,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM;IAKzD,SAAS,CAAE,IAAI,EAAE,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,YAAY;IAIzF,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAgCzD,cAAc,IAAI,OAAO;IAMzB,UAAU,CAAE,WAAW,EAAE,GAAG;IAU5B,kBAAkB,CAAE,MAAM,EAAE,iBAAiB;IAqB7C,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG;IAarC,gBAAgB;YAuBR,eAAe;IA0B7B,OAAO,CAAC,cAAc;YAIR,eAAe;CAqBhC"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
package/build/service.js CHANGED
@@ -6,6 +6,7 @@ import InsightsHandler from './insights-handler.js';
6
6
  import TestReporter from './reporter.js';
7
7
  import { DEFAULT_OPTIONS } from './constants.js';
8
8
  import CrashReporter from './crash-reporter.js';
9
+ import AccessibilityHandler from './accessibility-handler.js';
9
10
  const log = logger('@wdio/browserstack-service');
10
11
  export default class BrowserstackService {
11
12
  _caps;
@@ -23,6 +24,8 @@ export default class BrowserstackService {
23
24
  _observability;
24
25
  _currentTest;
25
26
  _insightsHandler;
27
+ _accessibility;
28
+ _accessibilityHandler;
26
29
  constructor(options, _caps, _config) {
27
30
  this._caps = _caps;
28
31
  this._config = _config;
@@ -30,6 +33,7 @@ export default class BrowserstackService {
30
33
  // added to maintain backward compatibility with webdriverIO v5
31
34
  this._config || (this._config = this._options);
32
35
  this._observability = this._options.testObservability;
36
+ this._accessibility = this._options.accessibility;
33
37
  if (this._observability) {
34
38
  this._config.reporters?.push(TestReporter);
35
39
  if (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT) {
@@ -91,6 +95,15 @@ export default class BrowserstackService {
91
95
  CrashReporter.uploadCrashReport(`Error in service class before function: ${err}`, err && err.stack);
92
96
  }
93
97
  }
98
+ if (this._browser && isBrowserstackSession(this._browser)) {
99
+ try {
100
+ this._accessibilityHandler = new AccessibilityHandler(this._browser, this._caps, this._isAppAutomate(), this._config.framework, this._accessibility, this._options.accessibilityOptions);
101
+ await this._accessibilityHandler.before();
102
+ }
103
+ catch (err) {
104
+ log.error(`[Accessibility Test Run] Error in service class before function: ${err}`);
105
+ }
106
+ }
94
107
  return await this._printSessionURL();
95
108
  }
96
109
  /**
@@ -103,6 +116,7 @@ export default class BrowserstackService {
103
116
  async beforeSuite(suite) {
104
117
  this._suiteTitle = suite.title;
105
118
  this._insightsHandler?.setSuiteFile(suite.file);
119
+ this._accessibilityHandler?.setSuiteFile(suite.file);
106
120
  if (suite.title && suite.title !== 'Jasmine__TopLevel__Suite') {
107
121
  await this._setSessionName(suite.title);
108
122
  }
@@ -133,6 +147,7 @@ export default class BrowserstackService {
133
147
  await this._setSessionName(suiteTitle, test);
134
148
  await this._setAnnotation(`Test: ${test.fullName ?? test.title}`);
135
149
  await this._insightsHandler?.beforeTest(test);
150
+ await this._accessibilityHandler?.beforeTest(suiteTitle, test);
136
151
  }
137
152
  async afterTest(test, context, results) {
138
153
  this._specsRan = true;
@@ -141,6 +156,7 @@ export default class BrowserstackService {
141
156
  this._failReasons.push((error && error.message) || 'Unknown Error');
142
157
  }
143
158
  await this._insightsHandler?.afterTest(test, results);
159
+ await this._accessibilityHandler?.afterTest(this._suiteTitle, test);
144
160
  }
145
161
  async after(result) {
146
162
  const { preferScenarioName, setSessionName, setSessionStatus } = this._options;
@@ -185,6 +201,7 @@ export default class BrowserstackService {
185
201
  async beforeScenario(world) {
186
202
  this._currentTest = world;
187
203
  await this._insightsHandler?.beforeScenario(world);
204
+ await this._accessibilityHandler?.beforeScenario(world);
188
205
  const scenarioName = world.pickle.name || 'unknown scenario';
189
206
  await this._setAnnotation(`Scenario: ${scenarioName}`);
190
207
  }
@@ -202,6 +219,7 @@ export default class BrowserstackService {
202
219
  this._failReasons.push(exception);
203
220
  }
204
221
  await this._insightsHandler?.afterScenario(world);
222
+ await this._accessibilityHandler?.afterScenario(world);
205
223
  }
206
224
  async beforeStep(step, scenario) {
207
225
  await this._insightsHandler?.beforeStep(step, scenario);
package/build/types.d.ts CHANGED
@@ -48,6 +48,20 @@ export interface BrowserstackConfig {
48
48
  * For e.g. buildName, projectName, BrowserStack access credentials, etc.
49
49
  */
50
50
  testObservabilityOptions?: TestObservabilityOptions;
51
+ /**
52
+ * Set this to true to enable BrowserStack Accessibility Automation which will
53
+ * automically conduct accessibility testing on your pre-existing test builds
54
+ * and generate health reports which can be viewed in the Accessibility dashboard.
55
+ * @default false
56
+ */
57
+ accessibility?: boolean;
58
+ /**
59
+ * Customise the Accessibility-related config options under this key.
60
+ * For e.g. wcagVersion, bestPractice issues, needsReview issues etc.
61
+ */
62
+ accessibilityOptions?: {
63
+ [key: string]: any;
64
+ };
51
65
  /**
52
66
  * Set this with app file path present locally on your device or
53
67
  * app hashed id returned after uploading app to BrowserStack or
@@ -185,6 +199,9 @@ export interface UserConfig {
185
199
  buildTag?: string;
186
200
  bstackServiceVersion?: string;
187
201
  buildIdentifier?: string;
202
+ accessibilityOptions?: {
203
+ [key: string]: any;
204
+ };
188
205
  }
189
206
  export interface UploadType {
190
207
  event_type: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/build/util.d.ts CHANGED
@@ -4,6 +4,7 @@ import http from 'node:http';
4
4
  import https from 'node:https';
5
5
  import type { Capabilities, Frameworks, Options } from '@wdio/types';
6
6
  import type { BeforeCommandArgs, AfterCommandArgs } from '@wdio/reporter';
7
+ import type { Method } from 'got';
7
8
  import type { UploadType, BrowserstackConfig } from './types.js';
8
9
  import type { ITestCaseHookParameter } from './cucumber-types.js';
9
10
  import RequestQueueHandler from './request-handler.js';
@@ -36,11 +37,28 @@ export declare function getBrowserCapabilities(browser: WebdriverIO.Browser | We
36
37
  export declare function isBrowserstackCapability(cap?: Capabilities.Capabilities): boolean;
37
38
  export declare function getParentSuiteName(fullTitle: string, testSuiteTitle: string): string;
38
39
  export declare function o11yErrorHandler(fn: Function): (...args: any) => any;
40
+ export declare function errorHandler(fn: Function): (...args: any) => any;
41
+ export declare function nodeRequest(requestType: Method, apiEndpoint: string, options: any, apiUrl: string, timeout?: number): Promise<Object>;
39
42
  type ClassType = {
40
43
  new (...args: any[]): any;
41
44
  };
42
45
  export declare function o11yClassErrorHandler<T extends ClassType>(errorClass: T): T;
43
46
  export declare const launchTestSession: (...args: any) => any;
47
+ export declare const validateCapsWithA11y: (deviceName?: any, platformMeta?: {
48
+ [key: string]: any;
49
+ } | undefined, chromeOptions?: any) => boolean;
50
+ export declare const shouldScanTestForAccessibility: (suiteTitle: string | undefined, testTitle: string, accessibilityOptions?: {
51
+ [key: string]: any;
52
+ } | undefined) => boolean | undefined;
53
+ export declare const isAccessibilityAutomationSession: (accessibilityFlag?: boolean | string) => boolean | "" | undefined;
54
+ export declare const createAccessibilityTestRun: (...args: any) => any;
55
+ export declare const getA11yResults: (browser: WebdriverIO.Browser, isBrowserStackSession?: boolean, isAccessibility?: boolean | string) => Promise<{
56
+ [key: string]: any;
57
+ }[]>;
58
+ export declare const getA11yResultsSummary: (browser: WebdriverIO.Browser, isBrowserStackSession?: boolean, isAccessibility?: boolean | string) => Promise<{
59
+ [key: string]: any;
60
+ }>;
61
+ export declare const stopAccessibilityTestRun: (...args: any) => any;
44
62
  export declare const stopBuildUpstream: (...args: any) => any;
45
63
  export declare function getCiInfo(): {
46
64
  name: string;
@@ -101,6 +119,10 @@ export declare function getObservabilityKey(options: BrowserstackConfig & Option
101
119
  export declare function getObservabilityProject(options: BrowserstackConfig & Options.Testrunner, bstackProjectName?: string): string | undefined;
102
120
  export declare function getObservabilityBuild(options: BrowserstackConfig & Options.Testrunner, bstackBuildName?: string): string;
103
121
  export declare function getObservabilityBuildTags(options: BrowserstackConfig & Options.Testrunner, bstackBuildTag?: string): string[];
122
+ export declare function getBrowserStackUser(config: Options.Testrunner): string | undefined;
123
+ export declare function getBrowserStackKey(config: Options.Testrunner): string | undefined;
124
+ export declare function isUndefined(value: any): boolean;
125
+ export declare function isTrue(value?: any): boolean;
104
126
  export declare function frameworkSupportsHook(hook: string, framework?: string): boolean;
105
127
  export declare function patchConsoleLogs(): void;
106
128
  export declare function getFailureObject(error: string | Error): {
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAEA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,KAAK,MAAM,YAAY,CAAA;AAI9B,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAIzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAOjC,OAAO,KAAK,EAAc,UAAU,EAAkB,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC5F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAEjE,OAAO,mBAAmB,MAAM,sBAAsB,CAAA;AAOtD,eAAO,MAAM,sBAAsB;;;;;;;;;CASlC,CAAA;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,CAAC,mBAAmB,UAa1E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,kBAAkB,EAAE,IAAI,CAAC,EAAE,YAAY,CAAC,gBAAgB,EAAE,WAAW,CAAC,EAAE,MAAM,6BAS/J;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,YAAY,WAWvE;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAUpF;AAaD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,aACf,GAAG,SAehC;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,aACX,GAAG,SAYhC;AAED,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAAe,mBAyBjI;AAOD,KAAK,SAAS,GAAG;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;CAAE,CAAC;AAC/C,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,SAAS,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,CA8B3E;AAED,eAAO,MAAM,iBAAiB,YAjGA,GAAG,QA4K/B,CAAA;AAEF,eAAO,MAAM,oBAAoB,gBAAiB,GAAG;;+BAA0D,GAAG,YA0BjH,CAAA;AAED,eAAO,MAAM,8BAA8B,eAAgB,MAAM,GAAG,SAAS,aAAa,MAAM;;qCAc/F,CAAA;AAED,eAAO,MAAM,gCAAgC,uBAAwB,OAAO,GAAG,MAAM,6BAQpF,CAAA;AAED,eAAO,MAAM,0BAA0B,YAlNT,GAAG,QAsS/B,CAAA;AAEF,eAAO,MAAM,cAAc,YAAmB,YAAY,OAAO,0BAA0B,OAAO,oBAAoB,OAAO,GAAG,MAAM;;IAkBrI,CAAA;AAED,eAAO,MAAM,qBAAqB,YAAmB,YAAY,OAAO,0BAA0B,OAAO,oBAAoB,OAAO,GAAG,MAAM;;EAiB5I,CAAA;AAED,eAAO,MAAM,wBAAwB,YA/UP,GAAG,QA4X/B,CAAA;AAEF,eAAO,MAAM,iBAAiB,YAhZA,GAAG,QAqb/B,CAAA;AAEF,wBAAgB,SAAS;;;;;;;;;;;;;;;SA8FxB;AAED,wBAAsB,cAAc;;;;;;;;;;;;;;;;;;;;eAyBnC;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAWrF;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAEpF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,kBAAkB,GAAG,MAAM,CAKtG;AAED,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,kBAAkB,uBAEnG;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,sBAAsB,wBAsChE;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAWnD;AAED,wBAAsB,eAAe,CAAE,SAAS,EAAE,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,EAAE,QAAQ,GAAE,MAA4B;;;eAuCvH;AAGD,wBAAgB,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,YAK9C;AAED,wBAAgB,WAAW,CAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWrD;AAED,wBAAgB,mBAAmB,CAAE,IAAI,EAAE,iBAAiB,GAAG,gBAAgB,4BAE9E;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,WAKzD;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,OAAO,CAKxG;AAED,wBAAsB,kBAAkB,CAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,iBAmB3F;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,sBAQhH;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,sBAQ/G;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC,EAAE,MAAM,sBAQnH;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,UAQ/G;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAW7H;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,sBAK7D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,sBAK5D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,GAAG,WAErC;AAED,wBAAgB,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,WAEjC;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,WAUrE;AAED,wBAAgB,gBAAgB,SAU/B;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAC,KAAK;;;;;;EAUnD;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,mBAAmB,GAAE,mBAAmB,GAAC,SAAqB,iBAQrH;AAED,eAAO,MAAM,KAAK,mCAAkE,CAAA"}
package/build/util.js CHANGED
@@ -10,9 +10,10 @@ import gitRepoInfo from 'git-repo-info';
10
10
  import gitconfig from 'gitconfiglocal';
11
11
  import logPatcher from './logPatcher.js';
12
12
  import PerformanceTester from './performance-tester.js';
13
- import { BROWSER_DESCRIPTION, DATA_ENDPOINT, DATA_EVENT_ENDPOINT, DATA_SCREENSHOT_ENDPOINT, consoleHolder } from './constants.js';
13
+ import { ACCESSIBILITY_API_URL, BROWSER_DESCRIPTION, DATA_ENDPOINT, DATA_EVENT_ENDPOINT, DATA_SCREENSHOT_ENDPOINT, consoleHolder } from './constants.js';
14
14
  import RequestQueueHandler from './request-handler.js';
15
15
  import CrashReporter from './crash-reporter.js';
16
+ import { accessibilityResults, accessibilityResultsSummary } from './scripts/test-event-scripts.js';
16
17
  const pGitconfig = promisify(gitconfig);
17
18
  const log = logger('@wdio/browserstack-service');
18
19
  export const DEFAULT_REQUEST_CONFIG = {
@@ -109,6 +110,50 @@ export function o11yErrorHandler(fn) {
109
110
  }
110
111
  };
111
112
  }
113
+ export function errorHandler(fn) {
114
+ return function (...args) {
115
+ try {
116
+ const functionToHandle = fn;
117
+ const result = functionToHandle(...args);
118
+ if (result instanceof Promise) {
119
+ return result.catch(error => log.error(`Error in executing ${fn.name} with args ${args}: ${error}`));
120
+ }
121
+ return result;
122
+ }
123
+ catch (error) {
124
+ log.error(`Error in executing ${fn.name} with args ${args}: ${error}`);
125
+ }
126
+ };
127
+ }
128
+ export async function nodeRequest(requestType, apiEndpoint, options, apiUrl, timeout = 120000) {
129
+ try {
130
+ const response = await got(`${apiUrl}/${apiEndpoint}`, {
131
+ method: requestType,
132
+ timeout: {
133
+ request: timeout
134
+ },
135
+ ...options
136
+ }).json();
137
+ return response;
138
+ }
139
+ catch (error) {
140
+ if (error instanceof HTTPError && error.response) {
141
+ const errorMessageJson = error.response.body ? JSON.parse(error.response.body.toString()) : null;
142
+ const errorMessage = errorMessageJson ? errorMessageJson.message : null;
143
+ if (errorMessage) {
144
+ log.error(`${errorMessage} - ${error.stack}`);
145
+ }
146
+ else {
147
+ log.error(`${error.stack}`);
148
+ }
149
+ throw error;
150
+ }
151
+ else {
152
+ log.error(`Failed to fire api request due to ${error} - ${error.stack}`);
153
+ throw error;
154
+ }
155
+ }
156
+ }
112
157
  export function o11yClassErrorHandler(errorClass) {
113
158
  const prototype = errorClass.prototype;
114
159
  if (Object.getOwnPropertyNames(prototype).length < 2) {
@@ -214,6 +259,201 @@ export const launchTestSession = o11yErrorHandler(async function launchTestSessi
214
259
  }
215
260
  }
216
261
  });
262
+ export const validateCapsWithA11y = (deviceName, platformMeta, chromeOptions) => {
263
+ try {
264
+ if (deviceName) {
265
+ log.warn('Accessibility Automation will run only on Desktop browsers.');
266
+ return false;
267
+ }
268
+ if (platformMeta?.browser_name?.toLowerCase() !== 'chrome') {
269
+ log.warn('Accessibility Automation will run only on Chrome browsers.');
270
+ return false;
271
+ }
272
+ const browserVersion = platformMeta?.browser_version;
273
+ if (!isUndefined(browserVersion) && !(browserVersion === 'latest' || parseFloat(browserVersion + '') > 94)) {
274
+ log.warn('Accessibility Automation will run only on Chrome browser version greater than 94.');
275
+ return false;
276
+ }
277
+ if (chromeOptions?.args?.includes('--headless')) {
278
+ log.warn('Accessibility Automation will not run on legacy headless mode. Switch to new headless mode or avoid using headless mode.');
279
+ return false;
280
+ }
281
+ return true;
282
+ }
283
+ catch (error) {
284
+ log.debug(`Exception in checking capabilities compatibility with Accessibility. Error: ${error}`);
285
+ }
286
+ return false;
287
+ };
288
+ export const shouldScanTestForAccessibility = (suiteTitle, testTitle, accessibilityOptions) => {
289
+ try {
290
+ const includeTags = Array.isArray(accessibilityOptions?.includeTagsInTestingScope) ? accessibilityOptions?.includeTagsInTestingScope : [];
291
+ const excludeTags = Array.isArray(accessibilityOptions?.excludeTagsInTestingScope) ? accessibilityOptions?.excludeTagsInTestingScope : [];
292
+ const fullTestName = suiteTitle + ' ' + testTitle;
293
+ const excluded = excludeTags?.some((exclude) => fullTestName.includes(exclude));
294
+ const included = includeTags?.length === 0 || includeTags?.some((include) => fullTestName.includes(include));
295
+ return !excluded && included;
296
+ }
297
+ catch (error) {
298
+ log.debug('Error while validating test case for accessibility before scanning. Error : ', error);
299
+ }
300
+ return false;
301
+ };
302
+ export const isAccessibilityAutomationSession = (accessibilityFlag) => {
303
+ try {
304
+ 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';
305
+ return accessibilityFlag && hasA11yJwtToken;
306
+ }
307
+ catch (error) {
308
+ log.debug(`Exception in verifying the Accessibility session with error : ${error}`);
309
+ }
310
+ return false;
311
+ };
312
+ export const createAccessibilityTestRun = errorHandler(async function createAccessibilityTestRun(options, config, bsConfig) {
313
+ const userName = getBrowserStackUser(config);
314
+ const accessKey = getBrowserStackKey(config);
315
+ if (isUndefined(userName) || isUndefined(accessKey)) {
316
+ log.error('Exception while creating test run for BrowserStack Accessibility Automation: Missing BrowserStack credentials');
317
+ return null;
318
+ }
319
+ const data = {
320
+ 'projectName': bsConfig.projectName,
321
+ 'buildName': bsConfig.buildName ||
322
+ path.basename(path.resolve(process.cwd())),
323
+ 'startTime': (new Date()).toISOString(),
324
+ 'description': '',
325
+ 'source': {
326
+ frameworkName: 'WebdriverIO-' + config.framework,
327
+ frameworkVersion: bsConfig.bstackServiceVersion,
328
+ sdkVersion: bsConfig.bstackServiceVersion
329
+ },
330
+ 'settings': bsConfig.accessibilityOptions || {},
331
+ 'versionControl': await getGitMetaData(),
332
+ 'ciInfo': getCiInfo(),
333
+ 'hostInfo': {
334
+ hostname: hostname(),
335
+ platform: platform(),
336
+ type: type(),
337
+ version: version(),
338
+ arch: arch()
339
+ },
340
+ 'browserstackAutomation': true,
341
+ };
342
+ const requestOptions = {
343
+ json: data,
344
+ username: getBrowserStackUser(config),
345
+ password: getBrowserStackKey(config),
346
+ };
347
+ try {
348
+ const response = await nodeRequest('POST', 'test_runs', requestOptions, ACCESSIBILITY_API_URL);
349
+ log.debug(`[Create Accessibility Test Run] Success response: ${JSON.stringify(response)}`);
350
+ if (response.data.accessibilityToken) {
351
+ process.env.BSTACK_A11Y_JWT = response.data.accessibilityToken;
352
+ }
353
+ if (response.data.id) {
354
+ process.env.BS_A11Y_TEST_RUN_ID = response.data.id;
355
+ }
356
+ log.debug(`BrowserStack Accessibility Automation Test Run ID: ${response.data.id}`);
357
+ return response.data.scannerVersion;
358
+ }
359
+ catch (error) {
360
+ if (error.response) {
361
+ log.error(`Exception while creating test run for BrowserStack Accessibility Automation: ${error.response.status} ${error.response.statusText} ${JSON.stringify(error.response.data)}`);
362
+ }
363
+ else {
364
+ const errorMessage = error.message;
365
+ if (errorMessage === 'Invalid configuration passed.') {
366
+ log.error(`Exception while creating test run for BrowserStack Accessibility Automation: ${errorMessage || error.stack}`);
367
+ for (const errorkey of error.errors) {
368
+ log.error(errorkey.message);
369
+ }
370
+ }
371
+ else {
372
+ log.error(`Exception while creating test run for BrowserStack Accessibility Automation: ${errorMessage || error.stack}`);
373
+ }
374
+ }
375
+ return null;
376
+ }
377
+ });
378
+ export const getA11yResults = async (browser, isBrowserStackSession, isAccessibility) => {
379
+ if (!isBrowserStackSession) {
380
+ log.warn('Not a BrowserStack Automate session, cannot retrieve Accessibility results.');
381
+ return []; // since we are running only on Automate as of now
382
+ }
383
+ if (!isAccessibilityAutomationSession(isAccessibility)) {
384
+ log.warn('Not an Accessibility Automation session, cannot retrieve Accessibility results.');
385
+ return [];
386
+ }
387
+ try {
388
+ const results = await browser.execute(accessibilityResults);
389
+ return results;
390
+ }
391
+ catch {
392
+ log.error('No accessibility results were found.');
393
+ return [];
394
+ }
395
+ };
396
+ export const getA11yResultsSummary = async (browser, isBrowserStackSession, isAccessibility) => {
397
+ if (!isBrowserStackSession) {
398
+ return {}; // since we are running only on Automate as of now
399
+ }
400
+ if (!isAccessibilityAutomationSession(isAccessibility)) {
401
+ log.warn('Not an Accessibility Automation session, cannot retrieve Accessibility results summary.');
402
+ return {};
403
+ }
404
+ try {
405
+ const summaryResults = await browser.execute(accessibilityResultsSummary);
406
+ return summaryResults;
407
+ }
408
+ catch {
409
+ log.error('No accessibility summary was found.');
410
+ return {};
411
+ }
412
+ };
413
+ export const stopAccessibilityTestRun = errorHandler(async function stopAccessibilityTestRun() {
414
+ 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';
415
+ if (!hasA11yJwtToken) {
416
+ return {
417
+ status: 'error',
418
+ message: 'Build creation had failed.'
419
+ };
420
+ }
421
+ const data = {
422
+ 'endTime': (new Date()).toISOString(),
423
+ };
424
+ const requestOptions = { ...{
425
+ json: data,
426
+ headers: {
427
+ 'Authorization': `Bearer ${process.env.BSTACK_A11Y_JWT}`,
428
+ }
429
+ } };
430
+ try {
431
+ const response = await nodeRequest('PUT', 'test_runs/stop', requestOptions, ACCESSIBILITY_API_URL);
432
+ if (response.data && response.data.error) {
433
+ throw new Error('Invalid request: ' + response.data.error);
434
+ }
435
+ else if (response.error) {
436
+ throw new Error('Invalid request: ' + response.error);
437
+ }
438
+ else {
439
+ log.info(`BrowserStack Accessibility Automation Test Run marked as completed at ${new Date().toISOString()}`);
440
+ return { status: 'success', message: '' };
441
+ }
442
+ }
443
+ catch (error) {
444
+ if (error.response && error.response.status && error.response.statusText && error.response.data) {
445
+ log.error(`Exception while marking completion of BrowserStack Accessibility Automation Test Run: ${error.response.status} ${error.response.statusText} ${JSON.stringify(error.response.data)}`);
446
+ }
447
+ else {
448
+ log.error(`Exception while marking completion of BrowserStack Accessibility Automation Test Run: ${error.message || util.format(error)}`);
449
+ }
450
+ return {
451
+ status: 'error',
452
+ message: error.message ||
453
+ (error.response ? `${error.response.status}:${error.response.statusText}` : error)
454
+ };
455
+ }
456
+ });
217
457
  export const stopBuildUpstream = o11yErrorHandler(async function stopBuildUpstream() {
218
458
  if (!process.env.BS_TESTOPS_BUILD_COMPLETED) {
219
459
  return;
@@ -593,6 +833,24 @@ export function getObservabilityBuildTags(options, bstackBuildTag) {
593
833
  }
594
834
  return [];
595
835
  }
836
+ export function getBrowserStackUser(config) {
837
+ if (process.env.BROWSERSTACK_USERNAME) {
838
+ return process.env.BROWSERSTACK_USERNAME;
839
+ }
840
+ return config.user;
841
+ }
842
+ export function getBrowserStackKey(config) {
843
+ if (process.env.BROWSERSTACK_ACCESS_KEY) {
844
+ return process.env.BROWSERSTACK_ACCESS_KEY;
845
+ }
846
+ return config.key;
847
+ }
848
+ export function isUndefined(value) {
849
+ return value === undefined || value === null;
850
+ }
851
+ export function isTrue(value) {
852
+ return (value + '') === 'true';
853
+ }
596
854
  export function frameworkSupportsHook(hook, framework) {
597
855
  if (framework === 'mocha' && (hook === 'before' || hook === 'after' || hook === 'beforeEach' || hook === 'afterEach')) {
598
856
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wdio/browserstack-service",
3
- "version": "8.16.6",
3
+ "version": "8.16.7",
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",
@@ -32,8 +32,8 @@
32
32
  "dependencies": {
33
33
  "@types/gitconfiglocal": "^2.0.1",
34
34
  "@wdio/logger": "8.11.0",
35
- "@wdio/reporter": "8.16.3",
36
- "@wdio/types": "8.16.3",
35
+ "@wdio/reporter": "8.16.7",
36
+ "@wdio/types": "8.16.7",
37
37
  "browserstack-local": "^1.5.1",
38
38
  "csv-writer": "^1.6.0",
39
39
  "form-data": "^4.0.0",
@@ -41,17 +41,18 @@
41
41
  "gitconfiglocal": "^2.1.0",
42
42
  "got": "^ 12.6.1",
43
43
  "uuid": "^9.0.0",
44
- "webdriverio": "8.16.6",
44
+ "webdriverio": "8.16.7",
45
45
  "winston-transport": "^4.5.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "@wdio/cli": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@types/node": "^20.1.0"
51
+ "@types/node": "^20.1.0",
52
+ "@wdio/globals": "8.16.7"
52
53
  },
53
54
  "publishConfig": {
54
55
  "access": "public"
55
56
  },
56
- "gitHead": "aa35c291fb496b80350766d674385ea7b4d1516a"
57
+ "gitHead": "15f7f225e6a81ea0e5e7a9ba8067ca59007f09c2"
57
58
  }