@wdio/browserstack-service 8.45.0 → 8.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -11
- package/build/Percy/Percy-Handler.d.ts.map +1 -1
- package/build/Percy/Percy-Handler.js +4 -1
- package/build/Percy/Percy.d.ts.map +1 -1
- package/build/Percy/Percy.js +2 -1
- package/build/accessibility-handler.d.ts +9 -3
- package/build/accessibility-handler.d.ts.map +1 -1
- package/build/accessibility-handler.js +52 -11
- package/build/cleanup.js +3 -3
- package/build/cli/apiUtils.d.ts +14 -0
- package/build/cli/apiUtils.d.ts.map +1 -0
- package/build/cli/apiUtils.js +24 -0
- package/build/cli/cliLogger.d.ts +16 -0
- package/build/cli/cliLogger.d.ts.map +1 -0
- package/build/cli/cliLogger.js +70 -0
- package/build/cli/cliUtils.d.ts +46 -0
- package/build/cli/cliUtils.d.ts.map +1 -0
- package/build/cli/cliUtils.js +430 -0
- package/build/cli/eventDispatcher.d.ts +28 -0
- package/build/cli/eventDispatcher.d.ts.map +1 -0
- package/build/cli/eventDispatcher.js +48 -0
- package/build/cli/frameworks/automationFramework.d.ts +89 -0
- package/build/cli/frameworks/automationFramework.d.ts.map +1 -0
- package/build/cli/frameworks/automationFramework.js +131 -0
- package/build/cli/frameworks/constants/automationFrameworkConstants.d.ts +18 -0
- package/build/cli/frameworks/constants/automationFrameworkConstants.d.ts.map +1 -0
- package/build/cli/frameworks/constants/automationFrameworkConstants.js +17 -0
- package/build/cli/frameworks/constants/testFrameworkConstants.d.ts +43 -0
- package/build/cli/frameworks/constants/testFrameworkConstants.d.ts.map +1 -0
- package/build/cli/frameworks/constants/testFrameworkConstants.js +42 -0
- package/build/cli/frameworks/testFramework.d.ts +89 -0
- package/build/cli/frameworks/testFramework.d.ts.map +1 -0
- package/build/cli/frameworks/testFramework.js +125 -0
- package/build/cli/frameworks/wdioAutomationFramework.d.ts +28 -0
- package/build/cli/frameworks/wdioAutomationFramework.d.ts.map +1 -0
- package/build/cli/frameworks/wdioAutomationFramework.js +66 -0
- package/build/cli/frameworks/wdioMochaTestFramework.d.ts +82 -0
- package/build/cli/frameworks/wdioMochaTestFramework.d.ts.map +1 -0
- package/build/cli/frameworks/wdioMochaTestFramework.js +319 -0
- package/build/cli/grpcClient.d.ts +70 -0
- package/build/cli/grpcClient.d.ts.map +1 -0
- package/build/cli/grpcClient.js +419 -0
- package/build/cli/index.d.ts +148 -0
- package/build/cli/index.d.ts.map +1 -0
- package/build/cli/index.js +415 -0
- package/build/cli/instances/automationFrameworkInstance.d.ts +33 -0
- package/build/cli/instances/automationFrameworkInstance.d.ts.map +1 -0
- package/build/cli/instances/automationFrameworkInstance.js +44 -0
- package/build/cli/instances/testFrameworkInstance.d.ts +62 -0
- package/build/cli/instances/testFrameworkInstance.d.ts.map +1 -0
- package/build/cli/instances/testFrameworkInstance.js +96 -0
- package/build/cli/instances/trackedContext.d.ts +32 -0
- package/build/cli/instances/trackedContext.d.ts.map +1 -0
- package/build/cli/instances/trackedContext.js +47 -0
- package/build/cli/instances/trackedInstance.d.ts +40 -0
- package/build/cli/instances/trackedInstance.d.ts.map +1 -0
- package/build/cli/instances/trackedInstance.js +63 -0
- package/build/cli/modules/accessibilityModule.d.ts +33 -0
- package/build/cli/modules/accessibilityModule.d.ts.map +1 -0
- package/build/cli/modules/accessibilityModule.js +347 -0
- package/build/cli/modules/automateModule.d.ts +26 -0
- package/build/cli/modules/automateModule.d.ts.map +1 -0
- package/build/cli/modules/automateModule.js +222 -0
- package/build/cli/modules/baseModule.d.ts +33 -0
- package/build/cli/modules/baseModule.d.ts.map +1 -0
- package/build/cli/modules/baseModule.js +51 -0
- package/build/cli/modules/observabilityModule.d.ts +22 -0
- package/build/cli/modules/observabilityModule.d.ts.map +1 -0
- package/build/cli/modules/observabilityModule.js +45 -0
- package/build/cli/modules/percyModule.d.ts +19 -0
- package/build/cli/modules/percyModule.d.ts.map +1 -0
- package/build/cli/modules/percyModule.js +77 -0
- package/build/cli/modules/testHubModule.d.ts +30 -0
- package/build/cli/modules/testHubModule.d.ts.map +1 -0
- package/build/cli/modules/testHubModule.js +232 -0
- package/build/cli/modules/webdriverIOModule.d.ts +29 -0
- package/build/cli/modules/webdriverIOModule.d.ts.map +1 -0
- package/build/cli/modules/webdriverIOModule.js +128 -0
- package/build/cli/states/automationFrameworkState.d.ts +65 -0
- package/build/cli/states/automationFrameworkState.d.ts.map +1 -0
- package/build/cli/states/automationFrameworkState.js +61 -0
- package/build/cli/states/hookState.d.ts +45 -0
- package/build/cli/states/hookState.d.ts.map +1 -0
- package/build/cli/states/hookState.js +43 -0
- package/build/cli/states/testFrameworkState.d.ts +125 -0
- package/build/cli/states/testFrameworkState.d.ts.map +1 -0
- package/build/cli/states/testFrameworkState.js +115 -0
- package/build/constants.d.ts +13 -0
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +21 -1
- package/build/crash-reporter.d.ts.map +1 -1
- package/build/crash-reporter.js +4 -3
- package/build/exitHandler.d.ts.map +1 -1
- package/build/exitHandler.js +47 -5
- package/build/insights-handler.d.ts +8 -0
- package/build/insights-handler.d.ts.map +1 -1
- package/build/insights-handler.js +57 -1
- package/build/instrumentation/funnelInstrumentation.d.ts.map +1 -1
- package/build/instrumentation/funnelInstrumentation.js +5 -4
- package/build/instrumentation/performance/constants.d.ts +8 -0
- package/build/instrumentation/performance/constants.d.ts.map +1 -1
- package/build/instrumentation/performance/constants.js +9 -1
- package/build/instrumentation/performance/performance-tester.d.ts.map +1 -1
- package/build/instrumentation/performance/performance-tester.js +5 -3
- package/build/launcher.d.ts.map +1 -1
- package/build/launcher.js +94 -51
- package/build/request-handler.js +1 -1
- package/build/service.d.ts +3 -1
- package/build/service.d.ts.map +1 -1
- package/build/service.js +244 -69
- package/build/testOps/requestUtils.js +3 -2
- package/build/types.d.ts +36 -3
- package/build/types.d.ts.map +1 -1
- package/build/util.d.ts +13 -1
- package/build/util.d.ts.map +1 -1
- package/build/util.js +173 -27
- package/package.json +7 -4
- package/tsconfig.prod.tsbuildinfo +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trackedContext.d.ts","sourceRoot":"","sources":["../../../src/cli/instances/trackedContext.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,OAAO,cAAc;;IAM/B;;;;;;KAMC;gBACW,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAOzE;;;KAGC;IACD,WAAW;IAIX;;;KAGC;IACD,YAAY;IAIZ;;;KAGC;IACD,KAAK;IAIL;;;KAGC;IACD,OAAO;CAIV"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export default class TrackedContext {
|
|
2
|
+
#id;
|
|
3
|
+
#threadId;
|
|
4
|
+
#processId;
|
|
5
|
+
#type;
|
|
6
|
+
/**
|
|
7
|
+
* Create TrackedContext
|
|
8
|
+
* @param {number} string - string Id for context - VERIFY
|
|
9
|
+
* @param {number} threadId- Integer Thread Id for context
|
|
10
|
+
* @param {number} processId - Integer Process Id for context
|
|
11
|
+
* @param {string} type
|
|
12
|
+
*/
|
|
13
|
+
constructor(id, threadId, processId, type) {
|
|
14
|
+
this.#id = id;
|
|
15
|
+
this.#threadId = threadId;
|
|
16
|
+
this.#processId = processId;
|
|
17
|
+
this.#type = type;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* get TrackedContext thread id
|
|
21
|
+
* @returns {number} - return thread id of context
|
|
22
|
+
*/
|
|
23
|
+
getThreadId() {
|
|
24
|
+
return this.#threadId;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* get TrackedContext process id
|
|
28
|
+
* @returns {number} - return process id of context
|
|
29
|
+
*/
|
|
30
|
+
getProcessId() {
|
|
31
|
+
return this.#processId;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* get TrackedContext id
|
|
35
|
+
* @returns {string} - returns context id
|
|
36
|
+
*/
|
|
37
|
+
getId() {
|
|
38
|
+
return this.#id;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* get TrackedContext type
|
|
42
|
+
* @returns {string}
|
|
43
|
+
*/
|
|
44
|
+
getType() {
|
|
45
|
+
return this.#type;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import TrackedContext from './trackedContext.js';
|
|
2
|
+
export default class TrackedInstance {
|
|
3
|
+
#private;
|
|
4
|
+
/**
|
|
5
|
+
* create TrackedInstance
|
|
6
|
+
* @param {TrackedContext} context
|
|
7
|
+
*/
|
|
8
|
+
constructor(context: TrackedContext);
|
|
9
|
+
/**
|
|
10
|
+
* get TrackedInstance ref
|
|
11
|
+
* @returns {number} - returns ref id
|
|
12
|
+
*/
|
|
13
|
+
getRef(): string;
|
|
14
|
+
/**
|
|
15
|
+
* get TrackedInstance context
|
|
16
|
+
* @return {TrackedContext} - returns tracked context
|
|
17
|
+
*/
|
|
18
|
+
getContext(): TrackedContext;
|
|
19
|
+
/**
|
|
20
|
+
* get All data of Instance
|
|
21
|
+
* @returns {Map} - returns all data
|
|
22
|
+
*/
|
|
23
|
+
getAllData(): Map<string, any>;
|
|
24
|
+
/**
|
|
25
|
+
* set multiple data in the instance
|
|
26
|
+
* @param {*} key
|
|
27
|
+
* @param {*} value
|
|
28
|
+
*/
|
|
29
|
+
updateMultipleEntries(entries: Record<string, any>): void;
|
|
30
|
+
updateData(key: string, value: any): void;
|
|
31
|
+
/**
|
|
32
|
+
* get Specific data of instance.
|
|
33
|
+
* @param {*} key
|
|
34
|
+
* @returns {*}
|
|
35
|
+
*/
|
|
36
|
+
getData(key: string): any;
|
|
37
|
+
hasData(key: string): boolean;
|
|
38
|
+
static createContext(target: string): TrackedContext;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=trackedInstance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trackedInstance.d.ts","sourceRoot":"","sources":["../../../src/cli/instances/trackedInstance.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,qBAAqB,CAAA;AAIhD,MAAM,CAAC,OAAO,OAAO,eAAe;;IAIhC;;;KAGC;gBACW,OAAO,EAAE,cAAc;IAKnC;;;KAGC;IACD,MAAM;IAIN;;;KAGC;IACD,UAAU;IAIV;;;KAGC;IACD,UAAU;IAIV;;;;KAIC;IACD,qBAAqB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAMlD,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG;IAIlC;;;;KAIC;IACD,OAAO,CAAC,GAAG,EAAE,MAAM;IAInB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI7B,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM;CAQtC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import TrackedContext from './trackedContext.js';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
import { threadId } from 'node:worker_threads';
|
|
4
|
+
export default class TrackedInstance {
|
|
5
|
+
#context;
|
|
6
|
+
#data;
|
|
7
|
+
/**
|
|
8
|
+
* create TrackedInstance
|
|
9
|
+
* @param {TrackedContext} context
|
|
10
|
+
*/
|
|
11
|
+
constructor(context) {
|
|
12
|
+
this.#context = context;
|
|
13
|
+
this.#data = new Map();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* get TrackedInstance ref
|
|
17
|
+
* @returns {number} - returns ref id
|
|
18
|
+
*/
|
|
19
|
+
getRef() {
|
|
20
|
+
return this.#context.getId();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* get TrackedInstance context
|
|
24
|
+
* @return {TrackedContext} - returns tracked context
|
|
25
|
+
*/
|
|
26
|
+
getContext() {
|
|
27
|
+
return this.#context;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* get All data of Instance
|
|
31
|
+
* @returns {Map} - returns all data
|
|
32
|
+
*/
|
|
33
|
+
getAllData() {
|
|
34
|
+
return this.#data;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* set multiple data in the instance
|
|
38
|
+
* @param {*} key
|
|
39
|
+
* @param {*} value
|
|
40
|
+
*/
|
|
41
|
+
updateMultipleEntries(entries) {
|
|
42
|
+
Object.keys(entries).forEach(key => {
|
|
43
|
+
this.#data.set(key, entries[key]);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
updateData(key, value) {
|
|
47
|
+
this.#data.set(key, value);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* get Specific data of instance.
|
|
51
|
+
* @param {*} key
|
|
52
|
+
* @returns {*}
|
|
53
|
+
*/
|
|
54
|
+
getData(key) {
|
|
55
|
+
return this.#data.get(key);
|
|
56
|
+
}
|
|
57
|
+
hasData(key) {
|
|
58
|
+
return this.#data.has(key);
|
|
59
|
+
}
|
|
60
|
+
static createContext(target) {
|
|
61
|
+
return new TrackedContext(crypto.createHash('sha256').update(target).digest('hex'), threadId || 0, process.pid, typeof (target));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import BaseModule from './baseModule.js';
|
|
2
|
+
import { BStackLogger } from '../cliLogger.js';
|
|
3
|
+
import accessibilityScripts from '../../scripts/accessibility-scripts.js';
|
|
4
|
+
import type { Accessibility } from '@browserstack/wdio-browserstack-service';
|
|
5
|
+
export default class AccessibilityModule extends BaseModule {
|
|
6
|
+
logger: typeof BStackLogger;
|
|
7
|
+
name: string;
|
|
8
|
+
scriptInstance: typeof accessibilityScripts;
|
|
9
|
+
accessibility: boolean;
|
|
10
|
+
isAppAccessibility: boolean;
|
|
11
|
+
isNonBstackA11y: boolean;
|
|
12
|
+
accessibilityConfig: Accessibility;
|
|
13
|
+
static MODULE_NAME: string;
|
|
14
|
+
accessibilityMap: Map<number, boolean>;
|
|
15
|
+
LOG_DISABLED_SHOWN: Map<number, boolean>;
|
|
16
|
+
constructor(accessibilityConfig: Accessibility, isNonBstackA11y: boolean);
|
|
17
|
+
onBeforeExecute(): Promise<void>;
|
|
18
|
+
private commandWrapper;
|
|
19
|
+
onBeforeTest(args: any): Promise<void>;
|
|
20
|
+
onAfterTest(): Promise<void>;
|
|
21
|
+
private shouldPatchExecuteScript;
|
|
22
|
+
private getCapability;
|
|
23
|
+
private performScanCli;
|
|
24
|
+
private sendTestStopEvent;
|
|
25
|
+
getA11yResults(browser: WebdriverIO.Browser): Promise<Array<{
|
|
26
|
+
[key: string]: any;
|
|
27
|
+
}>>;
|
|
28
|
+
getA11yResultsSummary(browser: WebdriverIO.Browser): Promise<{
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
}>;
|
|
31
|
+
getDriverExecuteParams(): Promise<any>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=accessibilityModule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibilityModule.d.ts","sourceRoot":"","sources":["../../../src/cli/modules/accessibilityModule.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAQ9C,OAAO,oBAAoB,MAAM,wCAAwC,CAAA;AAIzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAO5E,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,UAAU;IAEvD,MAAM,sBAAe;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,OAAO,oBAAoB,CAAA;IAC3C,aAAa,EAAE,OAAO,CAAQ;IAC9B,kBAAkB,EAAE,OAAO,CAAA;IAC3B,eAAe,EAAE,OAAO,CAAA;IACxB,mBAAmB,EAAE,aAAa,CAAA;IAClC,MAAM,CAAC,WAAW,SAAwB;IAC1C,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;gBAE5B,mBAAmB,EAAE,aAAa,EAAE,eAAe,EAAE,OAAO;IAelE,eAAe;YAsFP,cAAc;IAkCtB,YAAY,CAAC,IAAI,EAAE,GAAG;IAqCtB,WAAW;IA6DjB,OAAO,CAAC,wBAAwB;IAWhC,OAAO,CAAC,aAAa;YAuBP,cAAc;YAkCd,iBAAiB;IAuBzB,cAAc,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KAAE,CAAC,CAAC;IAsBrF,qBAAqB,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,GAAG,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KAAE,CAAC;IAqBrF,sBAAsB;CAa/B"}
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/// <reference path="../../@types/bstack-service-types.d.ts" />
|
|
2
|
+
import BaseModule from './baseModule.js';
|
|
3
|
+
import { BStackLogger } from '../cliLogger.js';
|
|
4
|
+
import TestFramework from '../frameworks/testFramework.js';
|
|
5
|
+
import AutomationFramework from '../frameworks/automationFramework.js';
|
|
6
|
+
import { TestFrameworkState } from '../states/testFrameworkState.js';
|
|
7
|
+
import { AutomationFrameworkState } from '../states/automationFrameworkState.js';
|
|
8
|
+
import { HookState } from '../states/hookState.js';
|
|
9
|
+
import accessibilityScripts from '../../scripts/accessibility-scripts.js';
|
|
10
|
+
import { _getParamsForAppAccessibility, formatString, getAppA11yResults, getAppA11yResultsSummary, shouldScanTestForAccessibility, validateCapsWithA11y, validateCapsWithAppA11y, validateCapsWithNonBstackA11y } from '../../util.js';
|
|
11
|
+
import { AutomationFrameworkConstants } from '../frameworks/constants/automationFrameworkConstants.js';
|
|
12
|
+
import util from 'node:util';
|
|
13
|
+
import PerformanceTester from '../../instrumentation/performance/performance-tester.js';
|
|
14
|
+
import * as PERFORMANCE_SDK_EVENTS from '../../instrumentation/performance/constants.js';
|
|
15
|
+
import { GrpcClient } from '../grpcClient.js';
|
|
16
|
+
export default class AccessibilityModule extends BaseModule {
|
|
17
|
+
logger = BStackLogger;
|
|
18
|
+
name;
|
|
19
|
+
scriptInstance;
|
|
20
|
+
accessibility = false;
|
|
21
|
+
isAppAccessibility;
|
|
22
|
+
isNonBstackA11y;
|
|
23
|
+
accessibilityConfig;
|
|
24
|
+
static MODULE_NAME = 'AccessibilityModule';
|
|
25
|
+
accessibilityMap;
|
|
26
|
+
LOG_DISABLED_SHOWN;
|
|
27
|
+
constructor(accessibilityConfig, isNonBstackA11y) {
|
|
28
|
+
super();
|
|
29
|
+
this.name = 'AccessibilityModule';
|
|
30
|
+
this.accessibilityConfig = accessibilityConfig;
|
|
31
|
+
AutomationFramework.registerObserver(AutomationFrameworkState.CREATE, HookState.POST, this.onBeforeExecute.bind(this));
|
|
32
|
+
TestFramework.registerObserver(TestFrameworkState.TEST, HookState.PRE, this.onBeforeTest.bind(this));
|
|
33
|
+
TestFramework.registerObserver(TestFrameworkState.TEST, HookState.POST, this.onAfterTest.bind(this));
|
|
34
|
+
this.accessibility = true;
|
|
35
|
+
this.scriptInstance = accessibilityScripts;
|
|
36
|
+
this.accessibilityMap = new Map();
|
|
37
|
+
this.LOG_DISABLED_SHOWN = new Map();
|
|
38
|
+
this.isAppAccessibility = accessibilityConfig.isAppAccessibility || false;
|
|
39
|
+
this.isNonBstackA11y = isNonBstackA11y;
|
|
40
|
+
}
|
|
41
|
+
async onBeforeExecute() {
|
|
42
|
+
try {
|
|
43
|
+
const autoInstance = AutomationFramework.getTrackedInstance();
|
|
44
|
+
if (!autoInstance) {
|
|
45
|
+
this.logger.debug('No tracked instances found!');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const browser = AutomationFramework.getDriver(autoInstance);
|
|
49
|
+
if (!browser) {
|
|
50
|
+
this.logger.debug('No browser instance found for command wrapping');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const isBrowserstackSession = AutomationFramework.getState(autoInstance, AutomationFrameworkConstants.KEY_IS_BROWSERSTACK_HUB);
|
|
54
|
+
const browserCaps = AutomationFramework.getState(autoInstance, AutomationFrameworkConstants.KEY_CAPABILITIES);
|
|
55
|
+
const inputCaps = AutomationFramework.getState(autoInstance, AutomationFrameworkConstants.KEY_INPUT_CAPABILITIES);
|
|
56
|
+
const sessionId = AutomationFramework.getState(autoInstance, AutomationFrameworkConstants.KEY_FRAMEWORK_SESSION_ID);
|
|
57
|
+
const platformA11yMeta = {
|
|
58
|
+
browser_name: browserCaps.browserName,
|
|
59
|
+
browser_version: browserCaps?.browserVersion || 'latest',
|
|
60
|
+
platform_name: browserCaps?.platformName,
|
|
61
|
+
platform_version: this.getCapability(browserCaps, 'appium:platformVersion', 'platformVersion'),
|
|
62
|
+
};
|
|
63
|
+
if (this.isAppAccessibility) {
|
|
64
|
+
this.accessibility = validateCapsWithAppA11y(platformA11yMeta);
|
|
65
|
+
}
|
|
66
|
+
else if (this.isNonBstackA11y) {
|
|
67
|
+
if (validateCapsWithNonBstackA11y(platformA11yMeta.browser_name, platformA11yMeta.browser_version)) {
|
|
68
|
+
this.accessibility = true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const device = this.getCapability(inputCaps, 'deviceName');
|
|
73
|
+
const chromeOptions = this.getCapability(inputCaps, 'goog:chromeOptions');
|
|
74
|
+
this.accessibility = validateCapsWithA11y(device, platformA11yMeta, chromeOptions);
|
|
75
|
+
}
|
|
76
|
+
//patching getA11yResultsSummary
|
|
77
|
+
browser.getAccessibilityResultsSummary = async () => {
|
|
78
|
+
if (this.isAppAccessibility) {
|
|
79
|
+
return await getAppA11yResultsSummary(true, browser, isBrowserstackSession, this.accessibility, sessionId);
|
|
80
|
+
}
|
|
81
|
+
return await this.getA11yResultsSummary(browser);
|
|
82
|
+
};
|
|
83
|
+
//patching getA11yResults
|
|
84
|
+
browser.getAccessibilityResults = async () => {
|
|
85
|
+
if (this.isAppAccessibility) {
|
|
86
|
+
return await getAppA11yResults(true, browser, isBrowserstackSession, this.accessibility, sessionId);
|
|
87
|
+
}
|
|
88
|
+
return await this.getA11yResults(browser);
|
|
89
|
+
};
|
|
90
|
+
//patching performScan
|
|
91
|
+
browser.performScan = async () => {
|
|
92
|
+
return await this.performScanCli(browser);
|
|
93
|
+
};
|
|
94
|
+
if (!this.accessibility) {
|
|
95
|
+
this.logger.info('Accessibility automation is disabled for this session.');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (!('overwriteCommand' in browser && Array.isArray(this.scriptInstance.commandsToWrap))) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Wrap commands if accessibility scripts are available
|
|
102
|
+
if (this.scriptInstance.commandsToWrap && this.scriptInstance.commandsToWrap.length > 0) {
|
|
103
|
+
this.scriptInstance.commandsToWrap
|
|
104
|
+
.filter((command) => command.name && command.class)
|
|
105
|
+
.forEach((command) => {
|
|
106
|
+
browser.overwriteCommand(command.name, this.commandWrapper.bind(this, command), command.class === 'Element');
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
this.logger.error(`Error in onBeforeExecute: ${error}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async commandWrapper(command, originFunction, ...args) {
|
|
115
|
+
try {
|
|
116
|
+
const autoInstance = AutomationFramework.getTrackedInstance();
|
|
117
|
+
const sessionId = AutomationFramework.getState(autoInstance, AutomationFrameworkConstants.KEY_FRAMEWORK_SESSION_ID);
|
|
118
|
+
// Check if accessibility is still enabled for this session
|
|
119
|
+
if (sessionId && this.accessibilityMap.get(sessionId)) {
|
|
120
|
+
const browser = AutomationFramework.getDriver(autoInstance);
|
|
121
|
+
// Perform accessibility scan before command if script is available
|
|
122
|
+
if (!command.name.includes('execute') ||
|
|
123
|
+
!this.shouldPatchExecuteScript(args.length ? args[0] : null)) {
|
|
124
|
+
try {
|
|
125
|
+
await this.performScanCli(browser, command.name);
|
|
126
|
+
this.logger.debug(`Accessibility scan performed after ${command.name} command`);
|
|
127
|
+
}
|
|
128
|
+
catch (scanError) {
|
|
129
|
+
this.logger.debug(`Error performing accessibility scan after ${command.name}: ${scanError}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Execute the original command
|
|
134
|
+
const result = await originFunction(...args);
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
this.logger.error(`Error in commandWrapper for ${command.name}: ${error}`);
|
|
139
|
+
// Still execute the original command even if accessibility scan fails
|
|
140
|
+
return await originFunction(...args);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async onBeforeTest(args) {
|
|
144
|
+
try {
|
|
145
|
+
this.logger.debug('Accessibility before test hook. Starting accessibility scan for this test case.');
|
|
146
|
+
const suiteTitle = args.suiteTitle || '';
|
|
147
|
+
const test = args.test || {};
|
|
148
|
+
const autoInstance = AutomationFramework.getTrackedInstance();
|
|
149
|
+
const testInstance = TestFramework.getTrackedInstance();
|
|
150
|
+
const sessionId = AutomationFramework.getState(autoInstance, AutomationFrameworkConstants.KEY_FRAMEWORK_SESSION_ID);
|
|
151
|
+
const accessibilityOptions = this.config.accessibilityOptions;
|
|
152
|
+
const shouldScanTest = shouldScanTestForAccessibility(suiteTitle, test.title, accessibilityOptions) && this.accessibility;
|
|
153
|
+
// Create test metadata similar to accessibility-handler
|
|
154
|
+
const testIdentifier = testInstance.getContext().getId();
|
|
155
|
+
const testMetadata = {
|
|
156
|
+
scanTestForAccessibility: shouldScanTest,
|
|
157
|
+
accessibilityScanStarted: shouldScanTest
|
|
158
|
+
};
|
|
159
|
+
// Store test metadata in test instance
|
|
160
|
+
TestFramework.setState(testInstance, `accessibility_metadata_${testIdentifier}`, testMetadata);
|
|
161
|
+
this.accessibilityMap.set(sessionId, shouldScanTest);
|
|
162
|
+
// Log if accessibility scan is enabled for this test
|
|
163
|
+
if (shouldScanTest) {
|
|
164
|
+
this.logger.info('Accessibility test case execution has started.');
|
|
165
|
+
}
|
|
166
|
+
else if (!this.LOG_DISABLED_SHOWN.get(sessionId)) {
|
|
167
|
+
this.logger.info('Accessibility scanning disabled for this test case.');
|
|
168
|
+
this.LOG_DISABLED_SHOWN.set(sessionId, true);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
this.logger.error(`Exception in starting accessibility automation scan for this test case: ${error}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async onAfterTest() {
|
|
176
|
+
this.logger.debug('Accessibility after test hook. Before sending test stop event');
|
|
177
|
+
try {
|
|
178
|
+
const autoInstance = AutomationFramework.getTrackedInstance();
|
|
179
|
+
const testInstance = TestFramework.getTrackedInstance();
|
|
180
|
+
const sessionId = AutomationFramework.getState(autoInstance, AutomationFrameworkConstants.KEY_FRAMEWORK_SESSION_ID);
|
|
181
|
+
if (!autoInstance || !testInstance) {
|
|
182
|
+
this.logger.error('No tracked instances found for accessibility after test');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// Get test metadata that was stored in onBeforeTest
|
|
186
|
+
const testIdentifier = testInstance.getContext().getId();
|
|
187
|
+
const testMetadata = testInstance.getData(`accessibility_metadata_${testIdentifier}`);
|
|
188
|
+
if (!testMetadata) {
|
|
189
|
+
this.logger.debug('No accessibility metadata found for this test');
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const { accessibilityScanStarted, scanTestForAccessibility } = testMetadata;
|
|
193
|
+
if (!accessibilityScanStarted) {
|
|
194
|
+
this.logger.debug('Accessibility scan was not started for this test');
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (scanTestForAccessibility) {
|
|
198
|
+
this.logger.info('Automate test case execution has ended. Processing for accessibility testing is underway.');
|
|
199
|
+
// Get the driver for sending test stop event
|
|
200
|
+
const browser = AutomationFramework.getDriver(autoInstance);
|
|
201
|
+
if (browser) {
|
|
202
|
+
let dataForExtension = {
|
|
203
|
+
'thTestRunUuid': process.env.TEST_ANALYTICS_ID,
|
|
204
|
+
'thBuildUuid': process.env.BROWSERSTACK_TESTHUB_UUID,
|
|
205
|
+
'thJwtToken': process.env.BROWSERSTACK_TESTHUB_JWT
|
|
206
|
+
};
|
|
207
|
+
const driverExecuteParams = await this.getDriverExecuteParams();
|
|
208
|
+
dataForExtension = { ...dataForExtension, ...driverExecuteParams };
|
|
209
|
+
// final scan and saving the results
|
|
210
|
+
await this.sendTestStopEvent(browser, dataForExtension);
|
|
211
|
+
this.logger.info('Accessibility testing for this test case has ended.');
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
this.logger.warn('No driver found to send accessibility test stop event');
|
|
215
|
+
}
|
|
216
|
+
this.accessibilityMap.delete(sessionId);
|
|
217
|
+
// Clean up test metadata
|
|
218
|
+
TestFramework.setState(testInstance, `accessibility_metadata_${testIdentifier}`, null);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
this.logger.error(`Accessibility results could not be processed for the test case. Error: ${error}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
shouldPatchExecuteScript(script) {
|
|
226
|
+
if (!script || typeof script !== 'string') {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
return (script.toLowerCase().indexOf('browserstack_executor') !== -1 ||
|
|
230
|
+
script.toLowerCase().indexOf('browserstack_accessibility_automation_script') !== -1);
|
|
231
|
+
}
|
|
232
|
+
getCapability(capabilities, key, legacyKey = '') {
|
|
233
|
+
if (key === 'deviceName') {
|
|
234
|
+
if (capabilities['bstack:options'] && capabilities['bstack:options']?.deviceName) {
|
|
235
|
+
return capabilities['bstack:options']?.deviceName;
|
|
236
|
+
}
|
|
237
|
+
else if (capabilities['bstack:options'] && capabilities['bstack:options']?.device) {
|
|
238
|
+
return capabilities['bstack:options']?.device;
|
|
239
|
+
}
|
|
240
|
+
else if (capabilities['appium:deviceName']) {
|
|
241
|
+
return capabilities['appium:deviceName'];
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else if (key === 'goog:chromeOptions' && capabilities['goog:chromeOptions']) {
|
|
245
|
+
return capabilities['goog:chromeOptions'];
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
const bstackOptions = capabilities['bstack:options'];
|
|
249
|
+
if (bstackOptions && bstackOptions?.[key]) {
|
|
250
|
+
return bstackOptions?.[key];
|
|
251
|
+
}
|
|
252
|
+
else if (capabilities[legacyKey]) {
|
|
253
|
+
return capabilities[legacyKey];
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async performScanCli(browser, commandName) {
|
|
258
|
+
return await PerformanceTester.measureWrapper(PERFORMANCE_SDK_EVENTS.A11Y_EVENTS.PERFORM_SCAN, async () => {
|
|
259
|
+
try {
|
|
260
|
+
if (!this.accessibility) {
|
|
261
|
+
this.logger.debug('Not an Accessibility Automation session.');
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (this.isAppAccessibility) {
|
|
265
|
+
const results = await browser.execute(formatString(this.scriptInstance.performScan, JSON.stringify(_getParamsForAppAccessibility(commandName))), {});
|
|
266
|
+
BStackLogger.debug(util.format(results));
|
|
267
|
+
return results;
|
|
268
|
+
}
|
|
269
|
+
const results = await browser.executeAsync(this.scriptInstance.performScan, { 'method': commandName || '' });
|
|
270
|
+
return results;
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
this.logger.error('Accessibility Scan could not be performed : ' + err);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
}, { command: commandName })();
|
|
277
|
+
}
|
|
278
|
+
async sendTestStopEvent(browser, dataForExtension) {
|
|
279
|
+
try {
|
|
280
|
+
if (!this.accessibility) {
|
|
281
|
+
this.logger.debug('Not an Accessibility Automation session.');
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
this.logger.debug('Performing scan before saving results');
|
|
285
|
+
await this.performScanCli(browser);
|
|
286
|
+
if (this.isAppAccessibility) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
await PerformanceTester.measureWrapper(PERFORMANCE_SDK_EVENTS.A11Y_EVENTS.SAVE_RESULTS, async () => {
|
|
290
|
+
const results = await browser.executeAsync(accessibilityScripts.saveTestResults, dataForExtension);
|
|
291
|
+
this.logger.debug(`save results : ${util.format(results)}`);
|
|
292
|
+
})();
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
this.logger.error(`Error while sending test stop event: ${error}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
async getA11yResults(browser) {
|
|
299
|
+
return await PerformanceTester.measureWrapper(PERFORMANCE_SDK_EVENTS.A11Y_EVENTS.GET_RESULTS, async () => {
|
|
300
|
+
try {
|
|
301
|
+
if (!this.accessibility) {
|
|
302
|
+
this.logger.debug('Not an Accessibility Automation session.');
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
this.logger.debug('Performing scan before getting results');
|
|
306
|
+
await this.performScanCli(browser);
|
|
307
|
+
const results = await browser.executeAsync(this.scriptInstance.getResults);
|
|
308
|
+
return results;
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
this.logger.error('No accessibility results were found.');
|
|
312
|
+
this.logger.debug(`getA11yResults Failed. Error: ${error}`);
|
|
313
|
+
return [];
|
|
314
|
+
}
|
|
315
|
+
})();
|
|
316
|
+
}
|
|
317
|
+
async getA11yResultsSummary(browser) {
|
|
318
|
+
return await PerformanceTester.measureWrapper(PERFORMANCE_SDK_EVENTS.A11Y_EVENTS.GET_RESULTS_SUMMARY, async () => {
|
|
319
|
+
try {
|
|
320
|
+
if (!this.accessibility) {
|
|
321
|
+
this.logger.debug('Not an Accessibility Automation session.');
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
this.logger.debug('Performing scan before getting results summary');
|
|
325
|
+
await this.performScanCli(browser);
|
|
326
|
+
const summaryResults = await browser.executeAsync(this.scriptInstance.getResultsSummary);
|
|
327
|
+
return summaryResults;
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
this.logger.error('No accessibility summary was found.');
|
|
331
|
+
return {};
|
|
332
|
+
}
|
|
333
|
+
})();
|
|
334
|
+
}
|
|
335
|
+
async getDriverExecuteParams() {
|
|
336
|
+
const payload = {
|
|
337
|
+
product: 'accessibility',
|
|
338
|
+
scriptName: 'saveResults'
|
|
339
|
+
};
|
|
340
|
+
const response = await GrpcClient.getInstance().fetchDriverExecuteParamsEvent(payload);
|
|
341
|
+
if (response.success) {
|
|
342
|
+
return response.accessibilityExecuteParams ? JSON.parse(Buffer.from(response.accessibilityExecuteParams).toString('utf8')) : {};
|
|
343
|
+
}
|
|
344
|
+
this.logger.error(`Failed to fetch driver execute params: ${response.error || 'Unknown error'}`);
|
|
345
|
+
return {};
|
|
346
|
+
}
|
|
347
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import BaseModule from './baseModule.js';
|
|
2
|
+
import { BStackLogger } from '../cliLogger.js';
|
|
3
|
+
import type { Options } from '@wdio/types';
|
|
4
|
+
export default class AutomateModule extends BaseModule {
|
|
5
|
+
logger: typeof BStackLogger;
|
|
6
|
+
browserStackConfig: Options.Testrunner;
|
|
7
|
+
private sessionMap;
|
|
8
|
+
static readonly MODULE_NAME = "AutomateModule";
|
|
9
|
+
/**
|
|
10
|
+
* Create a new AutomateModule
|
|
11
|
+
*/
|
|
12
|
+
constructor(browserStackConfig: Options.Testrunner);
|
|
13
|
+
getModuleName(): string;
|
|
14
|
+
onBeforeTest(args: Record<string, unknown>): Promise<void>;
|
|
15
|
+
onAfterTest(args: Record<string, unknown>): Promise<void>;
|
|
16
|
+
onAfterExecute(): Promise<void>;
|
|
17
|
+
markSessionName(sessionId: string, sessionName: string, config: {
|
|
18
|
+
user: string;
|
|
19
|
+
key: string;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
markSessionStatus(sessionId: string, sessionStatus: 'passed' | 'failed', sessionErrorMessage: string | undefined, config: {
|
|
22
|
+
user: string;
|
|
23
|
+
key: string;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=automateModule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"automateModule.d.ts","sourceRoot":"","sources":["../../../src/cli/modules/automateModule.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAK9C,OAAO,KAAK,EAAc,OAAO,EAAE,MAAM,aAAa,CAAA;AAsBtD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,UAAU;IAElD,MAAM,sBAAe;IACrB,kBAAkB,EAAE,OAAO,CAAC,UAAU,CAAA;IACtC,OAAO,CAAC,UAAU,CAAsC;IAExD,MAAM,CAAC,QAAQ,CAAC,WAAW,oBAAmB;IAC9C;;OAEG;gBACS,kBAAkB,EAAE,OAAO,CAAC,UAAU;IASlD,aAAa,IAAI,MAAM;IAIjB,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IA8C1C,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IA0DzC,cAAc;IAwCd,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;KAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA0C7G,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,GAAG,QAAQ,EAAE,mBAAmB,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CA0CjL"}
|