@mablhq/mabl-cli 2.8.25 → 2.12.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.
- package/api/mablApiClient.js +24 -0
- package/browserLauncher/playwrightBrowserLauncher/playwrightBrowser.js +2 -2
- package/browserLauncher/playwrightBrowserLauncher/playwrightPage.js +0 -3
- package/commands/environments/environments_cmds/create.js +3 -2
- package/commands/environments/environments_cmds/update.js +1 -1
- package/commands/tests/testsUtil.js +2 -0
- package/core/execution/newman-types.js +2 -1
- package/execution/index.js +9 -9
- package/execution/index.js.LICENSE.txt +60 -0
- package/execution/runAppiumServer.js +16 -4
- package/index.d.ts +2 -0
- package/mablApi/index.js +1 -1
- package/mablscript/importer.js +6 -0
- package/mablscript/mobile/steps/EnterTextStep.js +3 -0
- package/mablscript/mobile/steps/InstallAppStep.js +22 -0
- package/mablscript/mobile/steps/PrepareSessionStep.js +19 -0
- package/mablscript/mobile/steps/ScrollStep.js +52 -8
- package/mablscript/mobile/steps/UninstallAppStep.js +22 -0
- package/mablscript/mobile/steps/stepUtil.js +51 -12
- package/mablscript/mobile/tests/TestMobileFindDescriptors.js +72 -1
- package/mablscript/mobile/tests/steps/GeneralHumanization.mobiletest.js +144 -7
- package/mablscript/mobile/tests/steps/InstallAppStep.mobiletest.js +20 -0
- package/mablscript/mobile/tests/steps/ScrollStep.mobiletest.js +289 -78
- package/mablscript/mobile/tests/steps/UninstallAppStep.mobiletest.js +20 -0
- package/mablscript/steps/AwaitTabStep.js +36 -8
- package/mablscript/types/mobile/InstallAppStepDescriptor.js +2 -0
- package/mablscript/types/mobile/PrepareSessionStepDescriptor.js +2 -0
- package/mablscript/types/mobile/ScrollStepDescriptor.js +14 -0
- package/mablscript/types/mobile/UninstallAppStepDescriptor.js +2 -0
- package/mablscriptFind/index.js +1 -1
- package/package.json +2 -6
- package/resources/mablFind.js +1 -1
- package/resources/pdf-viewer/embeddedPdfDetection.js +22 -6
- package/socketTunnel/index.js +2 -0
- package/socketTunnel/index.js.LICENSE.txt +66 -0
- package/upload/index.js +1 -1
- package/util/downloadUtil.js +1 -1
package/mablscript/importer.js
CHANGED
|
@@ -64,6 +64,9 @@ const CreateVariableStepDescriptor_1 = require("./types/CreateVariableStepDescri
|
|
|
64
64
|
const JavaScriptDescriptor_1 = require("./types/JavaScriptDescriptor");
|
|
65
65
|
const MablStepV2_1 = require("./MablStepV2");
|
|
66
66
|
const PushFileStep_1 = require("./mobile/steps/PushFileStep");
|
|
67
|
+
const InstallAppStep_1 = require("./mobile/steps/InstallAppStep");
|
|
68
|
+
const UninstallAppStep_1 = require("./mobile/steps/UninstallAppStep");
|
|
69
|
+
const PrepareSessionStep_1 = require("./mobile/steps/PrepareSessionStep");
|
|
67
70
|
const ActionTypes = [
|
|
68
71
|
AwaitDownloadAction_1.AwaitDownloadAction,
|
|
69
72
|
AwaitPDFDownloadAction_1.AwaitPDFDownloadAction,
|
|
@@ -117,13 +120,16 @@ const StepTypes = [
|
|
|
117
120
|
const MobileStepTypes = [
|
|
118
121
|
AssertStep_1.AssertStep,
|
|
119
122
|
CreateVariableMobileStep_1.CreateVariableMobileStep,
|
|
123
|
+
InstallAppStep_1.InstallAppStep,
|
|
120
124
|
NavigateBackStep_1.NavigateBackStep,
|
|
121
125
|
NavigateHomeStep_1.NavigateHomeStep,
|
|
122
126
|
TapStep_1.TapStep,
|
|
123
127
|
EnterTextStep_2.EnterTextStep,
|
|
124
128
|
SetOrientationStep_1.SetOrientationStep,
|
|
125
129
|
ScrollStep_1.ScrollStep,
|
|
130
|
+
PrepareSessionStep_1.PrepareSessionStep,
|
|
126
131
|
PushFileStep_1.PushFileStep,
|
|
132
|
+
UninstallAppStep_1.UninstallAppStep,
|
|
127
133
|
];
|
|
128
134
|
const SyntheticActionCodes = [
|
|
129
135
|
'autologin',
|
|
@@ -17,6 +17,9 @@ class EnterTextStep extends MablStepV2_1.MablStepV2 {
|
|
|
17
17
|
return vars;
|
|
18
18
|
}
|
|
19
19
|
stepDescription() {
|
|
20
|
+
if ((0, stepUtil_1.isPasswordField)(this.descriptor.find)) {
|
|
21
|
+
return (0, stepUtil_1.getDescriptionForMobileStepDescriptor)(`Enter password in`, this.descriptor);
|
|
22
|
+
}
|
|
20
23
|
return (0, stepUtil_1.getDescriptionForMobileStepDescriptor)(`Enter text "${this.descriptor.text}" in`, this.descriptor);
|
|
21
24
|
}
|
|
22
25
|
static fromYaml(_stepName, stepDescriptor) {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InstallAppStep = void 0;
|
|
4
|
+
const MablStepV2_1 = require("../../MablStepV2");
|
|
5
|
+
class InstallAppStep extends MablStepV2_1.MablStepV2 {
|
|
6
|
+
constructor(descriptor) {
|
|
7
|
+
super(InstallAppStep.stepName, descriptor, 'installApp');
|
|
8
|
+
}
|
|
9
|
+
stepDescription() {
|
|
10
|
+
if (this.descriptor.packageName) {
|
|
11
|
+
return `Install app - ${this.descriptor.packageName}`;
|
|
12
|
+
}
|
|
13
|
+
return `Install primary app under test`;
|
|
14
|
+
}
|
|
15
|
+
static fromYaml(_stepName, stepDescriptor) {
|
|
16
|
+
return new InstallAppStep(stepDescriptor);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.InstallAppStep = InstallAppStep;
|
|
20
|
+
InstallAppStep.stepName = 'InstallApp';
|
|
21
|
+
InstallAppStep.yamlMablScriptNames = [InstallAppStep.stepName];
|
|
22
|
+
InstallAppStep.stepVersion = 2;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PrepareSessionStep = void 0;
|
|
4
|
+
const MablStepV2_1 = require("../../MablStepV2");
|
|
5
|
+
class PrepareSessionStep extends MablStepV2_1.MablStepV2 {
|
|
6
|
+
constructor(descriptor) {
|
|
7
|
+
super(PrepareSessionStep.stepName, descriptor, 'prepareSession');
|
|
8
|
+
}
|
|
9
|
+
stepDescription() {
|
|
10
|
+
return `Launch and initialize app session`;
|
|
11
|
+
}
|
|
12
|
+
static fromYaml(_stepName, stepDescriptor) {
|
|
13
|
+
return new PrepareSessionStep(stepDescriptor);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.PrepareSessionStep = PrepareSessionStep;
|
|
17
|
+
PrepareSessionStep.stepName = 'PrepareSession';
|
|
18
|
+
PrepareSessionStep.yamlMablScriptNames = [PrepareSessionStep.stepName];
|
|
19
|
+
PrepareSessionStep.stepVersion = 2;
|
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getScrollDirectionAndPercentageFromCoordinates = exports.formatPercentageVal = exports.humanizeScrollInformation = exports.ScrollStep = void 0;
|
|
4
4
|
const MablStepV2_1 = require("../../MablStepV2");
|
|
5
|
+
const ScrollStepDescriptor_1 = require("../../types/mobile/ScrollStepDescriptor");
|
|
6
|
+
const stepUtil_1 = require("./stepUtil");
|
|
5
7
|
const STEP_NAME = 'Scroll';
|
|
6
8
|
class ScrollStep extends MablStepV2_1.MablStepV2 {
|
|
7
9
|
constructor(descriptor) {
|
|
8
10
|
super(ScrollStep.stepName, descriptor, 'scroll');
|
|
9
11
|
}
|
|
10
12
|
stepDescription() {
|
|
11
|
-
return humanizeScrollInformation(this.descriptor
|
|
13
|
+
return humanizeScrollInformation(this.descriptor);
|
|
12
14
|
}
|
|
13
15
|
static fromYaml(_stepName, stepDescriptor) {
|
|
16
|
+
if (!stepDescriptor.scrollDirection) {
|
|
17
|
+
const { scrollDirection } = getScrollDirectionAndPercentageFromCoordinates(stepDescriptor.coordinates);
|
|
18
|
+
stepDescriptor.scrollDirection = scrollDirection;
|
|
19
|
+
}
|
|
20
|
+
if (!stepDescriptor.scrollType) {
|
|
21
|
+
stepDescriptor.scrollType = ScrollStepDescriptor_1.ScrollType.ScrollDeviceScreen;
|
|
22
|
+
}
|
|
14
23
|
return new ScrollStep(stepDescriptor);
|
|
15
24
|
}
|
|
16
25
|
}
|
|
@@ -18,20 +27,55 @@ exports.ScrollStep = ScrollStep;
|
|
|
18
27
|
ScrollStep.stepName = STEP_NAME;
|
|
19
28
|
ScrollStep.yamlMablScriptNames = [ScrollStep.stepName];
|
|
20
29
|
ScrollStep.stepVersion = 2;
|
|
30
|
+
function humanizeScrollInformation(stepDescriptor) {
|
|
31
|
+
switch (stepDescriptor.scrollType) {
|
|
32
|
+
case ScrollStepDescriptor_1.ScrollType.ScrollDeviceScreen: {
|
|
33
|
+
const { coordinates } = stepDescriptor;
|
|
34
|
+
return humanizeCoordinateScroll(coordinates, 'of the screen');
|
|
35
|
+
}
|
|
36
|
+
case ScrollStepDescriptor_1.ScrollType.ScrollToElement: {
|
|
37
|
+
const { find, maxScrollAttempts, scrollDirection, targetElementDescriptor, } = stepDescriptor;
|
|
38
|
+
const containerElementDescription = (0, stepUtil_1.getElementDescriptionFromMobileFindDescriptor)(find);
|
|
39
|
+
const targetElementDescription = (0, stepUtil_1.getElementDescriptionFromMobileFindDescriptor)(targetElementDescriptor);
|
|
40
|
+
return `Scroll ${scrollDirection} a maximum of ${maxScrollAttempts} times within the ${containerElementDescription} until the ${targetElementDescription} is visible`;
|
|
41
|
+
}
|
|
42
|
+
case ScrollStepDescriptor_1.ScrollType.ScrollWithinElement: {
|
|
43
|
+
const { coordinates, find } = stepDescriptor;
|
|
44
|
+
const containerElementDescription = (0, stepUtil_1.getElementDescriptionFromMobileFindDescriptor)(find);
|
|
45
|
+
return humanizeCoordinateScroll(coordinates, `within the ${containerElementDescription}`);
|
|
46
|
+
}
|
|
47
|
+
default:
|
|
48
|
+
return 'Unknown scroll step type';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.humanizeScrollInformation = humanizeScrollInformation;
|
|
52
|
+
function humanizeCoordinateScroll(coordinates, scrollTargetActionString) {
|
|
53
|
+
const { scrollDirection, scrollPercent } = getScrollDirectionAndPercentageFromCoordinates(coordinates);
|
|
54
|
+
return `Scroll ${scrollDirection} ${scrollPercent} ${scrollTargetActionString}`;
|
|
55
|
+
}
|
|
21
56
|
function formatPercentageVal(percent) {
|
|
22
57
|
return `${Math.round(percent * 10000) / 100}%`;
|
|
23
58
|
}
|
|
24
59
|
exports.formatPercentageVal = formatPercentageVal;
|
|
25
|
-
function
|
|
60
|
+
function getScrollDirectionAndPercentageFromCoordinates(coordinates) {
|
|
61
|
+
if (!coordinates) {
|
|
62
|
+
return { scrollDirection: ScrollStepDescriptor_1.ScrollDirection.Down, scrollPercent: '80%' };
|
|
63
|
+
}
|
|
26
64
|
const yScrollDistance = Math.abs(coordinates.to.yPercent - coordinates.from.yPercent);
|
|
27
65
|
const xScrollDistance = Math.abs(coordinates.to.xPercent - coordinates.from.xPercent);
|
|
28
66
|
if (yScrollDistance > xScrollDistance) {
|
|
29
67
|
const scrollDistanceFormatted = formatPercentageVal(yScrollDistance);
|
|
30
|
-
const
|
|
31
|
-
|
|
68
|
+
const isScrollUp = coordinates.from.yPercent < coordinates.to.yPercent;
|
|
69
|
+
const scrollDirection = isScrollUp
|
|
70
|
+
? ScrollStepDescriptor_1.ScrollDirection.Up
|
|
71
|
+
: ScrollStepDescriptor_1.ScrollDirection.Down;
|
|
72
|
+
return { scrollDirection, scrollPercent: scrollDistanceFormatted };
|
|
32
73
|
}
|
|
33
74
|
const scrollDistanceFormatted = formatPercentageVal(xScrollDistance);
|
|
34
|
-
const
|
|
35
|
-
|
|
75
|
+
const isScrollLeft = coordinates.from.xPercent < coordinates.to.xPercent;
|
|
76
|
+
const scrollDirection = isScrollLeft
|
|
77
|
+
? ScrollStepDescriptor_1.ScrollDirection.Left
|
|
78
|
+
: ScrollStepDescriptor_1.ScrollDirection.Right;
|
|
79
|
+
return { scrollDirection, scrollPercent: scrollDistanceFormatted };
|
|
36
80
|
}
|
|
37
|
-
exports.
|
|
81
|
+
exports.getScrollDirectionAndPercentageFromCoordinates = getScrollDirectionAndPercentageFromCoordinates;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UninstallAppStep = void 0;
|
|
4
|
+
const MablStepV2_1 = require("../../MablStepV2");
|
|
5
|
+
class UninstallAppStep extends MablStepV2_1.MablStepV2 {
|
|
6
|
+
constructor(descriptor) {
|
|
7
|
+
super(UninstallAppStep.stepName, descriptor, 'uninstallApp');
|
|
8
|
+
}
|
|
9
|
+
stepDescription() {
|
|
10
|
+
if (this.descriptor.appId) {
|
|
11
|
+
return `Uninstall app - ${this.descriptor.appId}`;
|
|
12
|
+
}
|
|
13
|
+
return `Uninstall primary app under test`;
|
|
14
|
+
}
|
|
15
|
+
static fromYaml(_stepName, stepDescriptor) {
|
|
16
|
+
return new UninstallAppStep(stepDescriptor);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.UninstallAppStep = UninstallAppStep;
|
|
20
|
+
UninstallAppStep.stepName = 'UninstallApp';
|
|
21
|
+
UninstallAppStep.yamlMablScriptNames = [UninstallAppStep.stepName];
|
|
22
|
+
UninstallAppStep.stepVersion = 2;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isStepWithFind = exports.humanizeCustomFind = exports.getElementDescriptionFromMobileFindDescriptor = exports.getDescriptionForMobileStepDescriptor = exports.getSimpleIOSElementName = exports.getSimpleAndroidElementName = void 0;
|
|
3
|
+
exports.isPasswordField = exports.isStepWithFind = exports.humanizeCustomFind = exports.getElementDescriptionFromMobileFindDescriptor = exports.getDescriptionForMobileStepDescriptor = exports.getSimpleIOSElementName = exports.getSimpleAndroidElementName = void 0;
|
|
4
4
|
const domUtil_1 = require("../../../domUtil");
|
|
5
5
|
const mablscriptFind_1 = require("../../../mablscriptFind");
|
|
6
6
|
function getSimpleAndroidElementName(className) {
|
|
@@ -35,24 +35,49 @@ function getElementDescriptionFromMobileFindDescriptor(descriptor) {
|
|
|
35
35
|
}
|
|
36
36
|
const selector = findTarget.selector;
|
|
37
37
|
if (selector.android && Object.keys(selector.android).length) {
|
|
38
|
-
|
|
39
|
-
return `element with text "${(0, domUtil_1.normalizeText)(selector.android.text)}"`;
|
|
40
|
-
}
|
|
41
|
-
return `"${getSimpleAndroidElementName(selector.android.class)}" element`;
|
|
38
|
+
return buildElementDescriptionForAndroid(findTarget);
|
|
42
39
|
}
|
|
43
40
|
else if (selector.iOS) {
|
|
44
|
-
|
|
45
|
-
return `"${selector.iOS.name}" element`;
|
|
46
|
-
}
|
|
47
|
-
if (selector.iOS.label) {
|
|
48
|
-
return `element with text "${(0, domUtil_1.normalizeText)(selector.iOS.label)}"`;
|
|
49
|
-
}
|
|
50
|
-
return `the "${getSimpleIOSElementName(selector.iOS.type)}" element`;
|
|
41
|
+
return buildElementDescriptionForiOS(findTarget);
|
|
51
42
|
}
|
|
52
43
|
}
|
|
53
44
|
return 'unknown element';
|
|
54
45
|
}
|
|
55
46
|
exports.getElementDescriptionFromMobileFindDescriptor = getElementDescriptionFromMobileFindDescriptor;
|
|
47
|
+
function buildElementDescriptionForAndroid(findTarget) {
|
|
48
|
+
var _a, _b, _c;
|
|
49
|
+
const selector = findTarget.selector;
|
|
50
|
+
if (!selector.android) {
|
|
51
|
+
return `unknown android element`;
|
|
52
|
+
}
|
|
53
|
+
const description = `"${getSimpleAndroidElementName(selector.android.class)}" element`;
|
|
54
|
+
if ((_a = selector.android) === null || _a === void 0 ? void 0 : _a.hint) {
|
|
55
|
+
return `${description} with hint "${(0, domUtil_1.normalizeText)(selector.android.hint)}"`;
|
|
56
|
+
}
|
|
57
|
+
if ((_b = selector.android) === null || _b === void 0 ? void 0 : _b.text) {
|
|
58
|
+
return `${description} with text "${(0, domUtil_1.normalizeText)(selector.android.text)}"`;
|
|
59
|
+
}
|
|
60
|
+
if ((_c = selector.android) === null || _c === void 0 ? void 0 : _c.contentDesc) {
|
|
61
|
+
return `${description} with content-desc "${(0, domUtil_1.normalizeText)(selector.android.contentDesc)}"`;
|
|
62
|
+
}
|
|
63
|
+
return description;
|
|
64
|
+
}
|
|
65
|
+
function buildElementDescriptionForiOS(findTarget) {
|
|
66
|
+
const selector = findTarget.selector;
|
|
67
|
+
if (!selector.iOS) {
|
|
68
|
+
return `unknown iOS element`;
|
|
69
|
+
}
|
|
70
|
+
if (selector.iOS.name) {
|
|
71
|
+
return `"${selector.iOS.name}" element`;
|
|
72
|
+
}
|
|
73
|
+
const simpleDescription = selector.iOS.type
|
|
74
|
+
? `"${getSimpleIOSElementName(selector.iOS.type)}" element`
|
|
75
|
+
: `element`;
|
|
76
|
+
if (selector.iOS.label) {
|
|
77
|
+
return `${simpleDescription} with label "${(0, domUtil_1.normalizeText)(selector.iOS.label)}"`;
|
|
78
|
+
}
|
|
79
|
+
return simpleDescription;
|
|
80
|
+
}
|
|
56
81
|
function getDescriptionForWebViewFindDescriptor(webViewElementDescriptor) {
|
|
57
82
|
if ((0, domUtil_1.isFindElementDescriptor)(webViewElementDescriptor.webView.descriptor)) {
|
|
58
83
|
return (0, mablscriptFind_1.humanizeFindOneDescriptor)(webViewElementDescriptor.webView.descriptor.findTarget);
|
|
@@ -72,3 +97,17 @@ function isStepWithFind(value) {
|
|
|
72
97
|
return !!(value === null || value === void 0 ? void 0 : value.find);
|
|
73
98
|
}
|
|
74
99
|
exports.isStepWithFind = isStepWithFind;
|
|
100
|
+
function isPasswordField(descriptor) {
|
|
101
|
+
var _a, _b;
|
|
102
|
+
if ((0, domUtil_1.isMobileFindSpecification)(descriptor === null || descriptor === void 0 ? void 0 : descriptor.findTarget)) {
|
|
103
|
+
if (((_a = descriptor.findTarget.selector.android) === null || _a === void 0 ? void 0 : _a.password) === true) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
if (((_b = descriptor.findTarget.selector.iOS) === null || _b === void 0 ? void 0 : _b.type) ===
|
|
107
|
+
'XCUIElementTypeSecureTextField') {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
exports.isPasswordField = isPasswordField;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AndroidTestLabWebViewClickCounterMobileFindDescriptor = exports.iOSTestLabWebViewClickCounterMobileFindDescriptor = exports.AndroidWebViewTextFieldMobileFindDescriptor = exports.iOSWebViewTextFieldMobileFindDescriptor = void 0;
|
|
3
|
+
exports.iOSTwoHorizontalScrollGrid2MobileFindDescriptor = exports.iOSVerticalGridCar75MobileFindDescriptor = exports.iOSVerticalGridContainerMobileFindDescriptor = exports.AndroidTestLabWebViewClickCounterMobileFindDescriptor = exports.iOSTestLabWebViewClickCounterMobileFindDescriptor = exports.AndroidWebViewTextFieldMobileFindDescriptor = exports.iOSWebViewTextFieldMobileFindDescriptor = void 0;
|
|
4
4
|
const domUtil_1 = require("../../../domUtil");
|
|
5
5
|
exports.iOSWebViewTextFieldMobileFindDescriptor = {
|
|
6
6
|
findType: domUtil_1.FindType.FIND_ONE,
|
|
@@ -213,3 +213,74 @@ exports.AndroidTestLabWebViewClickCounterMobileFindDescriptor = {
|
|
|
213
213
|
url: 'https://storage.googleapis.com/public-dev-test-lab/click/click-counter.html',
|
|
214
214
|
},
|
|
215
215
|
};
|
|
216
|
+
exports.iOSVerticalGridContainerMobileFindDescriptor = {
|
|
217
|
+
findTarget: {
|
|
218
|
+
selector: {
|
|
219
|
+
iOS: {
|
|
220
|
+
type: 'XCUIElementTypeOther',
|
|
221
|
+
enabled: true,
|
|
222
|
+
accessible: false,
|
|
223
|
+
rect: {
|
|
224
|
+
x: 0,
|
|
225
|
+
y: 143,
|
|
226
|
+
width: 390,
|
|
227
|
+
height: 5142,
|
|
228
|
+
},
|
|
229
|
+
index: 0,
|
|
230
|
+
xpath: '//XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView/XCUIElementTypeOther',
|
|
231
|
+
alternateXPaths: [],
|
|
232
|
+
},
|
|
233
|
+
uuid: '',
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
findType: domUtil_1.FindType.FIND_ONE,
|
|
237
|
+
};
|
|
238
|
+
exports.iOSVerticalGridCar75MobileFindDescriptor = {
|
|
239
|
+
findTarget: {
|
|
240
|
+
selector: {
|
|
241
|
+
iOS: {
|
|
242
|
+
rect: {
|
|
243
|
+
width: 51,
|
|
244
|
+
x: 219,
|
|
245
|
+
y: 657,
|
|
246
|
+
height: 21,
|
|
247
|
+
},
|
|
248
|
+
xpath: '//XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[55]/XCUIElementTypeStaticText',
|
|
249
|
+
name: 'Car 75',
|
|
250
|
+
index: 1,
|
|
251
|
+
alternateXPaths: [
|
|
252
|
+
'//XCUIElementTypeStaticText[@name="Car 75"]',
|
|
253
|
+
'//XCUIElementTypeButton[@name="Car 75"]/XCUIElementTypeStaticText',
|
|
254
|
+
],
|
|
255
|
+
label: 'Car 75',
|
|
256
|
+
type: 'XCUIElementTypeStaticText',
|
|
257
|
+
enabled: true,
|
|
258
|
+
},
|
|
259
|
+
uuid: '',
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
findType: domUtil_1.FindType.FIND_ONE,
|
|
263
|
+
};
|
|
264
|
+
exports.iOSTwoHorizontalScrollGrid2MobileFindDescriptor = {
|
|
265
|
+
findTarget: {
|
|
266
|
+
selector: {
|
|
267
|
+
uuid: 'd0efcf61-de79-49d2-91e3-dd318185576b',
|
|
268
|
+
iOS: {
|
|
269
|
+
type: 'XCUIElementTypeOther',
|
|
270
|
+
name: 'grid-2',
|
|
271
|
+
enabled: true,
|
|
272
|
+
accessible: false,
|
|
273
|
+
rect: {
|
|
274
|
+
x: 0,
|
|
275
|
+
y: 517,
|
|
276
|
+
width: 1125,
|
|
277
|
+
height: 301,
|
|
278
|
+
},
|
|
279
|
+
index: 0,
|
|
280
|
+
xpath: '//XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView[2]/XCUIElementTypeOther/XCUIElementTypeOther',
|
|
281
|
+
alternateXPaths: ['//XCUIElementTypeOther[@name="grid-2"]'],
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
findType: domUtil_1.FindType.FIND_ONE,
|
|
286
|
+
};
|
|
@@ -41,7 +41,7 @@ describe('Humanization of steps work', () => {
|
|
|
41
41
|
},
|
|
42
42
|
};
|
|
43
43
|
const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
|
|
44
|
-
expect(step.stepDescription()).toEqual(`Tap on element with
|
|
44
|
+
expect(step.stepDescription()).toEqual(`Tap on "Button" element with label "Click here for more"`);
|
|
45
45
|
});
|
|
46
46
|
it('Humanizes an iOS Tap step properly when only type is available', () => {
|
|
47
47
|
const stepYaml = {
|
|
@@ -61,7 +61,7 @@ describe('Humanization of steps work', () => {
|
|
|
61
61
|
},
|
|
62
62
|
};
|
|
63
63
|
const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
|
|
64
|
-
expect(step.stepDescription()).toEqual(`Tap on
|
|
64
|
+
expect(step.stepDescription()).toEqual(`Tap on "Button" element`);
|
|
65
65
|
});
|
|
66
66
|
it('Humanizes an android Tap step properly when text is available', () => {
|
|
67
67
|
const stepYaml = {
|
|
@@ -82,7 +82,7 @@ describe('Humanization of steps work', () => {
|
|
|
82
82
|
},
|
|
83
83
|
};
|
|
84
84
|
const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
|
|
85
|
-
expect(step.stepDescription()).toEqual(`Tap on element with text "submit form"`);
|
|
85
|
+
expect(step.stepDescription()).toEqual(`Tap on "Button" element with text "submit form"`);
|
|
86
86
|
});
|
|
87
87
|
it('Humanizes an android Tap step properly when only class is available', () => {
|
|
88
88
|
const stepYaml = {
|
|
@@ -133,7 +133,7 @@ describe('Humanization of steps work', () => {
|
|
|
133
133
|
findTarget: {
|
|
134
134
|
selector: {
|
|
135
135
|
iOS: {
|
|
136
|
-
type: '
|
|
136
|
+
type: 'XCUIElementTypeTextField',
|
|
137
137
|
label: 'add name here',
|
|
138
138
|
},
|
|
139
139
|
},
|
|
@@ -142,7 +142,7 @@ describe('Humanization of steps work', () => {
|
|
|
142
142
|
},
|
|
143
143
|
};
|
|
144
144
|
const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
|
|
145
|
-
expect(step.stepDescription()).toEqual(`Enter text "Bailey" in element with
|
|
145
|
+
expect(step.stepDescription()).toEqual(`Enter text "Bailey" in "TextField" element with label "add name here"`);
|
|
146
146
|
});
|
|
147
147
|
it('Humanizes an android Enter Text step properly using android text', () => {
|
|
148
148
|
const stepYaml = {
|
|
@@ -153,7 +153,7 @@ describe('Humanization of steps work', () => {
|
|
|
153
153
|
findTarget: {
|
|
154
154
|
selector: {
|
|
155
155
|
android: {
|
|
156
|
-
class: 'android.widget.
|
|
156
|
+
class: 'android.widget.EditText',
|
|
157
157
|
text: 'submit form',
|
|
158
158
|
},
|
|
159
159
|
},
|
|
@@ -162,6 +162,143 @@ describe('Humanization of steps work', () => {
|
|
|
162
162
|
},
|
|
163
163
|
};
|
|
164
164
|
const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
|
|
165
|
-
expect(step.stepDescription()).toEqual(`Enter text "Bailey" in element with text "submit form"`);
|
|
165
|
+
expect(step.stepDescription()).toEqual(`Enter text "Bailey" in "EditText" element with text "submit form"`);
|
|
166
|
+
});
|
|
167
|
+
it('humanizes an android button with contentDesc attribute', () => {
|
|
168
|
+
const stepYaml = {
|
|
169
|
+
Tap: {
|
|
170
|
+
find: {
|
|
171
|
+
findType: domUtil_1.FindType.FIND_ONE,
|
|
172
|
+
findTarget: {
|
|
173
|
+
selector: {
|
|
174
|
+
android: {
|
|
175
|
+
displayed: true,
|
|
176
|
+
resourceId: '',
|
|
177
|
+
package: 'com.polar.android.debug',
|
|
178
|
+
checkable: false,
|
|
179
|
+
clickable: true,
|
|
180
|
+
index: 0,
|
|
181
|
+
focusable: true,
|
|
182
|
+
alternateXPaths: [
|
|
183
|
+
'//android.widget.Button[@content-desc="MySeltzer"',
|
|
184
|
+
],
|
|
185
|
+
contentDesc: 'MySeltzer',
|
|
186
|
+
enabled: true,
|
|
187
|
+
longClickable: false,
|
|
188
|
+
password: false,
|
|
189
|
+
xpath: '//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.Button',
|
|
190
|
+
bounds: '[42,616][465,784]',
|
|
191
|
+
focused: false,
|
|
192
|
+
checked: false,
|
|
193
|
+
text: '',
|
|
194
|
+
class: 'android.widget.Button',
|
|
195
|
+
scrollable: false,
|
|
196
|
+
selected: false,
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
|
|
204
|
+
expect(step.stepDescription()).toEqual(`Tap on "Button" element with content-desc "MySeltzer"`);
|
|
205
|
+
});
|
|
206
|
+
it('humanizes an android text field that contains a password', () => {
|
|
207
|
+
const stepYaml = {
|
|
208
|
+
EnterText: {
|
|
209
|
+
text: 'superSecretClassified',
|
|
210
|
+
find: {
|
|
211
|
+
findType: domUtil_1.FindType.FIND_ONE,
|
|
212
|
+
findTarget: {
|
|
213
|
+
selector: {
|
|
214
|
+
android: {
|
|
215
|
+
displayed: true,
|
|
216
|
+
resourceId: '',
|
|
217
|
+
package: 'com.polar.android.debug',
|
|
218
|
+
checkable: false,
|
|
219
|
+
clickable: true,
|
|
220
|
+
index: 0,
|
|
221
|
+
focusable: true,
|
|
222
|
+
alternateXPaths: [],
|
|
223
|
+
enabled: true,
|
|
224
|
+
longClickable: false,
|
|
225
|
+
password: true,
|
|
226
|
+
xpath: '//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.Button',
|
|
227
|
+
bounds: '[42,616][465,784]',
|
|
228
|
+
focused: false,
|
|
229
|
+
checked: false,
|
|
230
|
+
text: '',
|
|
231
|
+
class: 'android.widget.EditText',
|
|
232
|
+
scrollable: false,
|
|
233
|
+
selected: false,
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
|
|
241
|
+
expect(step.stepDescription()).toEqual(`Enter password in "EditText" element`);
|
|
242
|
+
});
|
|
243
|
+
it('humanizes an iOS text field that contains a password', () => {
|
|
244
|
+
const stepYaml = {
|
|
245
|
+
EnterText: {
|
|
246
|
+
text: 'iWillNeverTell',
|
|
247
|
+
find: {
|
|
248
|
+
findType: domUtil_1.FindType.FIND_ONE,
|
|
249
|
+
findTarget: {
|
|
250
|
+
selector: {
|
|
251
|
+
android: {},
|
|
252
|
+
iOS: {
|
|
253
|
+
type: 'XCUIElementTypeSecureTextField',
|
|
254
|
+
name: 'Password field',
|
|
255
|
+
label: 'Password field',
|
|
256
|
+
enabled: true,
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
type: 'tap',
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
|
|
265
|
+
expect(step.stepDescription()).toEqual(`Enter password in "Password field" element`);
|
|
266
|
+
});
|
|
267
|
+
it('humanizes an android text field that has a hint attribute', () => {
|
|
268
|
+
const stepYaml = {
|
|
269
|
+
Tap: {
|
|
270
|
+
find: {
|
|
271
|
+
findType: domUtil_1.FindType.FIND_ONE,
|
|
272
|
+
findTarget: {
|
|
273
|
+
selector: {
|
|
274
|
+
android: {
|
|
275
|
+
displayed: true,
|
|
276
|
+
resourceId: '',
|
|
277
|
+
package: 'com.polar.android.debug',
|
|
278
|
+
checkable: false,
|
|
279
|
+
clickable: true,
|
|
280
|
+
index: 0,
|
|
281
|
+
focusable: true,
|
|
282
|
+
alternateXPaths: [],
|
|
283
|
+
enabled: true,
|
|
284
|
+
longClickable: false,
|
|
285
|
+
password: false,
|
|
286
|
+
hint: 'Search for the things',
|
|
287
|
+
xpath: '//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.EditText',
|
|
288
|
+
bounds: '[42,616][465,784]',
|
|
289
|
+
focused: false,
|
|
290
|
+
checked: false,
|
|
291
|
+
text: '',
|
|
292
|
+
class: 'android.widget.EditText',
|
|
293
|
+
scrollable: false,
|
|
294
|
+
selected: false,
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
|
|
302
|
+
expect(step.stepDescription()).toEqual(`Tap on "EditText" element with hint "Search for the things"`);
|
|
166
303
|
});
|
|
167
304
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const InstallAppStep_1 = require("../../steps/InstallAppStep");
|
|
4
|
+
const StepTestsUtil_1 = require("../StepTestsUtil");
|
|
5
|
+
describe('Install App steps parse correctly', () => {
|
|
6
|
+
it('Parses an InstallApp step', () => {
|
|
7
|
+
const stepDescriptor = {
|
|
8
|
+
id: 'hereYouGo',
|
|
9
|
+
actionCode: 'installApp',
|
|
10
|
+
};
|
|
11
|
+
const steps = [
|
|
12
|
+
{
|
|
13
|
+
InstallApp: stepDescriptor,
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
(0, StepTestsUtil_1.parseAndValidateYamlConversion)(steps, InstallAppStep_1.InstallAppStep.stepName, stepDescriptor);
|
|
17
|
+
const tapStep = new InstallAppStep_1.InstallAppStep(stepDescriptor);
|
|
18
|
+
expect(tapStep.stepId()).toEqual(stepDescriptor.id);
|
|
19
|
+
});
|
|
20
|
+
});
|