@sap_oss/wdio-qmate-service 2.13.1 → 2.13.2
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/docs/sections/features/selectors.md +8 -8
- package/lib/reuse/helper/elementResolving.d.ts +1 -0
- package/lib/reuse/helper/elementResolving.js +12 -0
- package/lib/reuse/helper/elementResolving.js.map +1 -1
- package/lib/reuse/modules/mobile/device.d.ts +160 -4
- package/lib/reuse/modules/mobile/device.js +367 -13
- package/lib/reuse/modules/mobile/device.js.map +1 -1
- package/lib/reuse/modules/mobile/element.d.ts +44 -25
- package/lib/reuse/modules/mobile/element.js +80 -26
- package/lib/reuse/modules/mobile/element.js.map +1 -1
- package/lib/reuse/modules/mobile/userInteraction.d.ts +73 -7
- package/lib/reuse/modules/mobile/userInteraction.js +159 -23
- package/lib/reuse/modules/mobile/userInteraction.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
To perform any action on an element (e.g. clicking a button), you need to specify the element at which the action is being executed. This differs from the web technology you are using. Read the following instructions, depending on the UI technology of the application to be tested.
|
|
3
3
|
|
|
4
4
|
!!! info
|
|
5
|
-
|
|
5
|
+
Selectors are typically created using our Qmate Suite, but it is important to note that this tool is currently **only available for internal use at SAP**. For further information as **internal**, please refer to our official Qmate documentation.
|
|
6
6
|
|
|
7
7
|
## UI5
|
|
8
8
|
|
|
@@ -62,7 +62,7 @@ You have to define at least one property in ```elementProperties```. This could
|
|
|
62
62
|
}
|
|
63
63
|
```
|
|
64
64
|
!!! tip
|
|
65
|
-
|
|
65
|
+
For most of the cases it will be sufficient to provide only the elementProperties. Qmate Suite will generate the minimal unique selector for you.
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
### Overview
|
|
@@ -81,10 +81,10 @@ The following properties apply to all selector types (elementProperties, ancesto
|
|
|
81
81
|
| ``domProperties`` | the properties of the DOM | ``"domProperties": {"nodeName": "div", "class": "buttonNU* class2*", "id": "my*Id*"}`` | string: ``"property": "value"``, numeric: ``"property": 123``, boolean: ``"property": true`` | can be used if the UI5 Virtual DOM is not sufficient |
|
|
82
82
|
|
|
83
83
|
!!! info
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
Wildcards are supported for all properties, aggregation and associations
|
|
85
|
+
```js
|
|
86
|
+
"text": "my*text*"
|
|
87
|
+
```
|
|
88
88
|
|
|
89
89
|
### Nested Properties
|
|
90
90
|
In case you need to specify the element based on its surrounding, you can define nested properties.
|
|
@@ -103,7 +103,7 @@ In case you need to specify the element based on its surrounding, you can define
|
|
|
103
103
|
};
|
|
104
104
|
```
|
|
105
105
|
!!! info
|
|
106
|
-
|
|
106
|
+
Nesting is enabled infinitely for *ancestorProperties*, *siblingProperties* and *descendantProperties*. Be cautious, the more level of nesting you add the slower your script will be.
|
|
107
107
|
|
|
108
108
|
### Usage of Selectors
|
|
109
109
|
For almost every UI5 action we provide, you can pass the selector directly to the function like:
|
|
@@ -155,7 +155,7 @@ clearly.
|
|
|
155
155
|
$$("[<attr>='<attrValue>']");
|
|
156
156
|
```
|
|
157
157
|
!!! warning
|
|
158
|
-
|
|
158
|
+
If there are more than one elements found, try to find another attribute or add some more attributes until you will find a single element (you can still pass an index to the reuse function if you are not able to find a unique selector).
|
|
159
159
|
|
|
160
160
|
|
|
161
161
|
### Usage
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveCssSelectorOrElement = resolveCssSelectorOrElement;
|
|
4
|
+
exports.resolveMobileSelectorOrElement = resolveMobileSelectorOrElement;
|
|
4
5
|
async function resolveCssSelectorOrElement(elementOrSelector) {
|
|
5
6
|
if (!elementOrSelector) {
|
|
6
7
|
throw new Error("Please provide an element or a CSS selector as first argument.");
|
|
@@ -12,4 +13,15 @@ async function resolveCssSelectorOrElement(elementOrSelector) {
|
|
|
12
13
|
return elementOrSelector;
|
|
13
14
|
}
|
|
14
15
|
}
|
|
16
|
+
async function resolveMobileSelectorOrElement(elementOrSelector) {
|
|
17
|
+
if (!elementOrSelector) {
|
|
18
|
+
throw new Error("Please provide an element or a selector as first argument.");
|
|
19
|
+
}
|
|
20
|
+
if (typeof elementOrSelector === "string") {
|
|
21
|
+
return await $(elementOrSelector);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return elementOrSelector;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
15
27
|
//# sourceMappingURL=elementResolving.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elementResolving.js","sourceRoot":"","sources":["../../../src/reuse/helper/elementResolving.ts"],"names":[],"mappings":";;AAEA,kEAUC;
|
|
1
|
+
{"version":3,"file":"elementResolving.js","sourceRoot":"","sources":["../../../src/reuse/helper/elementResolving.ts"],"names":[],"mappings":";;AAEA,kEAUC;AAED,wEAUC;AAtBM,KAAK,UAAU,2BAA2B,CAAC,iBAAmC;IACnF,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACpF,CAAC;IAED,IAAI,OAAO,iBAAiB,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,OAAO,iBAAiB,CAAC;IAC3B,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,8BAA8B,CAAC,iBAAmC;IACtF,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IAED,IAAI,OAAO,iBAAiB,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,OAAO,iBAAiB,CAAC;IAC3B,CAAC;AACH,CAAC"}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
type hideKeyboardStrategy = "pressKey" | "tapOutside" | "swipeDown" | "";
|
|
2
|
+
declare const ORIENTATION: {
|
|
3
|
+
readonly LANDSCAPE: "LANDSCAPE";
|
|
4
|
+
readonly PORTRAIT: "PORTRAIT";
|
|
5
|
+
readonly UNKNOWN: "UNKNOWN";
|
|
6
|
+
};
|
|
7
|
+
type Orientation = (typeof ORIENTATION)[keyof typeof ORIENTATION];
|
|
1
8
|
/**
|
|
2
9
|
* @class device
|
|
3
10
|
* @memberof mobile
|
|
@@ -5,25 +12,174 @@
|
|
|
5
12
|
export declare class Device {
|
|
6
13
|
private vlf;
|
|
7
14
|
private ErrorHandler;
|
|
15
|
+
/**
|
|
16
|
+
* @function isValidPlatform
|
|
17
|
+
* @memberof mobile.device
|
|
18
|
+
* @description Check the mobile platform from the session's capabilities.
|
|
19
|
+
* @returns {boolean} Returns 'true' if the platform in the session's capabilities is either Android or iOS.
|
|
20
|
+
*/
|
|
21
|
+
private isValidPlatform;
|
|
22
|
+
/**
|
|
23
|
+
* @function executionPlatform
|
|
24
|
+
* @memberof mobile.device
|
|
25
|
+
* @description Check the mobile platform from the session's capabilities.
|
|
26
|
+
* @returns {string} Return current execution platform in the session's capabilities.
|
|
27
|
+
*/
|
|
28
|
+
private executionPlatform;
|
|
8
29
|
/**
|
|
9
30
|
* @function isAppInstalled
|
|
10
31
|
* @memberof mobile.device
|
|
11
32
|
* @description Check wether given package/bundle app is installed or not in the device.
|
|
12
|
-
* @param {string}
|
|
13
|
-
* @returns {boolean} Returns true if specified app package/bundled installed in the device, or false.
|
|
14
|
-
* @example
|
|
33
|
+
* @param {string} appPackageOrBundleId - Android package Id, or iOS bundle Id.
|
|
34
|
+
* @returns {boolean} Returns 'true' if specified app package/bundled installed in the device, or 'false'.
|
|
35
|
+
* @example
|
|
36
|
+
* await mobile.device.isAppInstalled("com.google.android.apps.maps");
|
|
37
|
+
* await mobile.device.isAppInstalled("com.apple.AppStore")
|
|
15
38
|
*/
|
|
16
|
-
isAppInstalled(
|
|
39
|
+
isAppInstalled(appPackageOrBundleId: string): Promise<boolean>;
|
|
17
40
|
/**
|
|
18
41
|
* @function installApp
|
|
19
42
|
* @memberof mobile.device
|
|
20
43
|
* @description Install the appropriate app based on the platform the test is being executed on.
|
|
21
44
|
* @param {string} appPath - Path of the app(.apk, .ipa)
|
|
45
|
+
* @returns {Promise<void>}
|
|
22
46
|
* @example
|
|
23
47
|
* await mobile.device.installApp("/path/to/your/app.apk");
|
|
24
48
|
* await mobile.device.installApp("/path/to/your/app.ipa");
|
|
25
49
|
*/
|
|
26
50
|
installApp(appPath: string): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* @function switchToContext
|
|
53
|
+
* @memberof mobile.device
|
|
54
|
+
* @description Switch to the specified( WEBVIEW | NATIVE_APP ) context if available.
|
|
55
|
+
* @param {string} [targetContext='WEBVIEW'] The name of the target context.
|
|
56
|
+
* @param {number} [timeout=5000] Maximum time to wait for the web context to appear, milliseconds.
|
|
57
|
+
* @returns {Promise<boolean>} Returns 'true' if the context is successfully switched, otherwise 'false'.
|
|
58
|
+
* @example
|
|
59
|
+
* await mobile.device.switchToContext();
|
|
60
|
+
* await mobile.device.switchToContext("NATIVE_APP", 1000);
|
|
61
|
+
*/
|
|
62
|
+
switchToContext(targetContext?: string, timeout?: number): Promise<boolean>;
|
|
63
|
+
/**
|
|
64
|
+
* @function getTargetContextIfAvailable
|
|
65
|
+
* @memberof mobile.device
|
|
66
|
+
* @description
|
|
67
|
+
* Returns the specified target context if available within a given timeout.
|
|
68
|
+
*
|
|
69
|
+
* This method retrieves the list of available contexts and determines if a context
|
|
70
|
+
* that matches the `targetContext` string is present. If the target context is found,
|
|
71
|
+
* it returns the context name; otherwise, it returns `null`.
|
|
72
|
+
*
|
|
73
|
+
* @param {string} [targetContext="WEBVIEW"] - The name of the target context to check for.
|
|
74
|
+
* Common examples are "WEBVIEW" or "NATIVE_APP".
|
|
75
|
+
* @param {number} [timeout=5000] - The maximum time, in milliseconds, to wait for the target
|
|
76
|
+
* context to become available.
|
|
77
|
+
* @returns {Promise<string | null>} - The name of the target context if found, or `null` if
|
|
78
|
+
* the context is not available within the timeout.
|
|
79
|
+
* @example
|
|
80
|
+
* const context = await getTargetContextIfAvailable("WEBVIEW", 10000);
|
|
81
|
+
* const context = await getTargetContextIfAvailable("NATIVE_APP", 10000);
|
|
82
|
+
*/
|
|
83
|
+
getTargetContextIfAvailable(targetContext?: string, timeout?: number): Promise<string | null>;
|
|
84
|
+
/**
|
|
85
|
+
* @function closeApplication
|
|
86
|
+
* @memberof mobile.device
|
|
87
|
+
* @description Close the currently active mobile application.
|
|
88
|
+
* @returns {Promise<void>}
|
|
89
|
+
* @example
|
|
90
|
+
* await mobile.device.closeApplication();
|
|
91
|
+
*/
|
|
92
|
+
closeApplication(): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* @function queryAppState
|
|
95
|
+
* @memberof mobile.device
|
|
96
|
+
* @description Queries the state of the application (e.g., running, background, not installed) on the mobile device(Android or iOS).
|
|
97
|
+
* @param {string} appPackageOrBundleId - Package name (Android) or bundle ID (iOS) of the application.
|
|
98
|
+
* @returns {Promise<number>} - The app state:
|
|
99
|
+
* 0 - Not running,
|
|
100
|
+
* 1 - Not installed,
|
|
101
|
+
* 2 - Running in the background (not suspended),
|
|
102
|
+
* 3 - Running in the background (suspended),
|
|
103
|
+
* 4 - Running in the foreground.
|
|
104
|
+
* @example
|
|
105
|
+
* await mobile.device.queryAppState("com.google.android.apps.maps");
|
|
106
|
+
* await mobile.device.queryAppState("com.apple.AppStore");
|
|
107
|
+
*/
|
|
108
|
+
queryAppState(appPackageOrBundleId: string): Promise<number>;
|
|
109
|
+
/**
|
|
110
|
+
* @function launchApp
|
|
111
|
+
* @memberof mobile.device
|
|
112
|
+
* @description Launches the app for both iOS and Android with a parameterized app identifier.
|
|
113
|
+
* @param {string} appPackageOrBundleId - The Android package name or iOS bundle ID of the application.
|
|
114
|
+
* @returns {Promise<void>} Resolves when the app is successfully launched.
|
|
115
|
+
* @example
|
|
116
|
+
* await mobile.device.launchApp("com.google.android.apps.maps");
|
|
117
|
+
* await mobile.device.launchApp("com.apple.AppStore");
|
|
118
|
+
*/
|
|
119
|
+
launchApp(appPackageOrBundleId: string): Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* @function switchToLandscapeOrientation
|
|
122
|
+
* @memberof mobile.device
|
|
123
|
+
* @description Switches the device orientation to landscape mode.
|
|
124
|
+
* @returns {Promise<void>} Resolves when the orientation is successfully switched.
|
|
125
|
+
* @example
|
|
126
|
+
* await mobile.device.switchToLandscapeOrientation();
|
|
127
|
+
*/
|
|
128
|
+
switchToLandscapeOrientation(): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* @function switchToPortraitOrientation
|
|
131
|
+
* @memberof mobile.device
|
|
132
|
+
* @description Switches the device orientation to portrait mode.
|
|
133
|
+
* @returns {Promise<void>} Resolves when the orientation is successfully switched.
|
|
134
|
+
* @example
|
|
135
|
+
* await mobile.device.switchToPortraitOrientation();
|
|
136
|
+
*/
|
|
137
|
+
switchToPortraitOrientation(): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* @function getCurrentOrientation
|
|
140
|
+
* @memberof mobile.device
|
|
141
|
+
* @description Returns the device current orientation (PORTRAIT or LANDSCAPE)
|
|
142
|
+
* @returns {Promise<Orientation>} The current device orientation.
|
|
143
|
+
* @example
|
|
144
|
+
* await mobile.device.getCurrentOrientation();
|
|
145
|
+
*/
|
|
146
|
+
getCurrentOrientation(): Promise<Orientation>;
|
|
147
|
+
/**
|
|
148
|
+
* @function hideKeyboard
|
|
149
|
+
* @memberof mobile.device
|
|
150
|
+
* @description Hides the keyboard on both Android and iOS using specific strategies with timeout.
|
|
151
|
+
* @param {string} strategy - Strategy to use for hiding the keyboard ('pressKey', 'tapOutside', 'swipeDown').
|
|
152
|
+
* @param {string} key - Key to press if using the 'pressKey' strategy (e.g., 'Done', 'Enter').
|
|
153
|
+
* @param {number} keyCode - Key code for Android (optional).
|
|
154
|
+
* @param {number} [timeout=5000] - Timeout in milliseconds for retrying to hide the keyboard.
|
|
155
|
+
* @returns {Promise<void>}
|
|
156
|
+
* @example
|
|
157
|
+
* await mobile.device.hideKeyboard();
|
|
158
|
+
* await mobile.device.hideKeyboard('tapOutside');
|
|
159
|
+
* await mobile.device.hideKeyboard('swipeDown');
|
|
160
|
+
* //Android only, Sends a specific key code, like 66 for "Enter."
|
|
161
|
+
* await mobile.device.hideKeyboard('pressKey', undefined, 66);
|
|
162
|
+
* await mobile.device.hideKeyboard('pressKey', 'Done');
|
|
163
|
+
*/
|
|
164
|
+
hideKeyboard(strategy?: hideKeyboardStrategy, key?: string, keyCode?: number, timeout?: number): Promise<void>;
|
|
165
|
+
/**
|
|
166
|
+
* @function isKeyboardVisible
|
|
167
|
+
* @memberof mobile.device
|
|
168
|
+
* @description Checks if the keyboard is visible or not on the mobile device.
|
|
169
|
+
* @returns {Promise<boolean>} Returns 'true' if the keyboard is visible on the mobile view.
|
|
170
|
+
* @example
|
|
171
|
+
* await mobile.device.isKeyboardVisible();
|
|
172
|
+
*/
|
|
173
|
+
isKeyboardVisible(): Promise<boolean>;
|
|
174
|
+
/**
|
|
175
|
+
* @function isPlatformSupported
|
|
176
|
+
* @memberof mobile.device
|
|
177
|
+
* @description Determine if the current platform is supported, if the current device platform is either Android or iOS.
|
|
178
|
+
* @returns {Promise<boolean>} If neither Android nor iOS is detected (e.g., Windows, Linux, or web), the condition evaluates to false
|
|
179
|
+
* @example
|
|
180
|
+
* await mobile.device.isPlatformSupported();
|
|
181
|
+
*/
|
|
182
|
+
isPlatformSupported(): Promise<boolean>;
|
|
27
183
|
}
|
|
28
184
|
declare const _default: Device;
|
|
29
185
|
export default _default;
|