ff-automationv2 2.2.29 → 2.2.30
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/dist/ai/llmcalls/llmAction.js +49 -13
- package/dist/ai/llmcalls/parseLlmOputput.js +5 -5
- package/dist/ai/llmprompts/promptRegistry.js +4 -0
- package/dist/ai/llmprompts/systemPrompts/actionExtractorPrompt.js +39 -11
- package/dist/ai/llmprompts/systemPrompts/fireflinkElementIndexExtactors.js +6 -6
- package/dist/ai/llmprompts/systemPrompts/fireflinkElementIndexExtractor_Mob.js +32 -0
- package/dist/ai/llmprompts/systemPrompts/mobileKeywordExtractor.js +17 -8
- package/dist/ai/llmprompts/systemPrompts/otpExtractorPrompt.d.ts +1 -0
- package/dist/ai/llmprompts/systemPrompts/otpExtractorPrompt.js +22 -0
- package/dist/ai/llmprompts/systemPrompts/verifyActionExtractorPrompt.js +3 -1
- package/dist/ai/llmprompts/systemPrompts/visionPrompt.js +14 -6
- package/dist/ai/llmprompts/systemPrompts/visionPromptMobile.js +3 -0
- package/dist/ai/llmprompts/userPrompts/userPrompt.js +1 -0
- package/dist/automation/actions/executor.d.ts +4 -0
- package/dist/automation/actions/executor.js +20 -0
- package/dist/automation/actions/interaction/clear/clear.js +1 -1
- package/dist/automation/actions/interaction/clear/clearAndEnter.js +1 -1
- package/dist/automation/actions/interaction/click/click.js +10 -3
- package/dist/automation/actions/interaction/click/clickNtimes.js +1 -1
- package/dist/automation/actions/interaction/click/doubleClick.js +1 -1
- package/dist/automation/actions/interaction/click/rightClick.js +1 -1
- package/dist/automation/actions/interaction/elementlessActions/getOtp.d.ts +2 -0
- package/dist/automation/actions/interaction/elementlessActions/getOtp.js +101 -0
- package/dist/automation/actions/interaction/enterActions/enterInput.js +11 -6
- package/dist/automation/actions/interaction/enterActions/enterInputAndPress.js +2 -2
- package/dist/automation/actions/interaction/enterActions/enterusingJs.js +2 -2
- package/dist/automation/actions/interaction/enterActions/waitAndEnter.js +1 -1
- package/dist/automation/actions/interaction/upload/uploadfile.js +1 -1
- package/dist/automation/actions/interaction/verify/VerifyNavigateURL.js +38 -11
- package/dist/automation/actions/interface/FireFlinkResponseSchema.d.ts +12 -0
- package/dist/automation/actions/interface/FireFlinkResponseSchema.js +19 -3
- package/dist/automation/actions/interface/getOtpInterface.d.ts +15 -0
- package/dist/automation/actions/interface/getOtpInterface.js +2 -0
- package/dist/automation/browserSession/initiateBrowserSession.d.ts +1 -1
- package/dist/automation/browserSession/initiateBrowserSession.js +15 -7
- package/dist/automation/driverState.d.ts +2 -0
- package/dist/automation/driverState.js +4 -0
- package/dist/automation/mobileSession/initiateMobileSession.d.ts +4 -5
- package/dist/automation/mobileSession/initiateMobileSession.js +83 -19
- package/dist/core/constants/allAction.js +5 -1
- package/dist/core/constants/supportedActions.js +5 -2
- package/dist/core/interfaces/actionInterface.d.ts +4 -0
- package/dist/core/interfaces/browserConfigurationInterface.d.ts +0 -4
- package/dist/core/interfaces/browserConfigurationInterface.js +0 -1
- package/dist/core/interfaces/executionDetails.d.ts +6 -3
- package/dist/core/interfaces/fireflinkScriptPayloadInterface.d.ts +22 -16
- package/dist/core/interfaces/llmResponseInterface.d.ts +1 -0
- package/dist/core/interfaces/promptInterface.d.ts +1 -0
- package/dist/core/main/SessionManager.d.ts +9 -0
- package/dist/core/main/SessionManager.js +23 -0
- package/dist/core/main/actionHandlerFactory.js +261 -64
- package/dist/core/main/executionContext.d.ts +7 -1
- package/dist/core/main/executionContext.js +93 -3
- package/dist/core/main/runAutomationScript.d.ts +1 -0
- package/dist/core/main/runAutomationScript.js +912 -304
- package/dist/core/main/stepProcessor.js +7 -2
- package/dist/core/types/browserType.d.ts +3 -3
- package/dist/core/types/browserType.js +2 -2
- package/dist/core/types/messageType.d.ts +13 -0
- package/dist/core/types/messageType.js +15 -0
- package/dist/core/types/promptType.d.ts +2 -1
- package/dist/core/types/promptType.js +1 -0
- package/dist/domAnalysis/searchBest.js +15 -16
- package/dist/domAnalysis/simplifyAndFlatten.js +6 -4
- package/dist/fireflinkData/fireflinkLocators/getListOfLocators.d.ts +3 -0
- package/dist/fireflinkData/fireflinkLocators/getListOfLocators.js +23 -15
- package/dist/fireflinkData/fireflinkLocators/parser/getElementsFromHTML.d.ts +3 -3
- package/dist/fireflinkData/fireflinkLocators/parser/getElementsFromHTML.js +134 -118
- package/dist/fireflinkData/fireflinkLocators/types/locator.d.ts +11 -1
- package/dist/fireflinkData/fireflinkLocators/utils/androidSelector.d.ts +1 -1
- package/dist/fireflinkData/fireflinkLocators/utils/androidSelector.js +35 -9
- package/dist/fireflinkData/fireflinkLocators/utils/cssSelector.d.ts +10 -10
- package/dist/fireflinkData/fireflinkLocators/utils/cssSelector.js +56 -59
- package/dist/fireflinkData/fireflinkLocators/utils/iosSelector.d.ts +1 -1
- package/dist/fireflinkData/fireflinkLocators/utils/iosSelector.js +53 -29
- package/dist/fireflinkData/fireflinkLocators/utils/referenceXpath.d.ts +8 -8
- package/dist/fireflinkData/fireflinkLocators/utils/referenceXpath.js +113 -190
- package/dist/fireflinkData/fireflinkLocators/utils/xpath.d.ts +17 -26
- package/dist/fireflinkData/fireflinkLocators/utils/xpath.js +314 -786
- package/dist/fireflinkData/fireflinkLocators/utils/xpathHelpers.d.ts +68 -70
- package/dist/fireflinkData/fireflinkLocators/utils/xpathHelpers.js +498 -517
- package/dist/fireflinkData/fireflinkScript/appendScriptData.d.ts +1 -1
- package/dist/fireflinkData/fireflinkScript/appendScriptData.js +5 -8
- package/dist/fireflinkData/fireflinkScript/scriptGenrationData.d.ts +2 -2
- package/dist/fireflinkData/fireflinkScript/scriptGenrationData.js +17 -27
- package/dist/llmConfig/llmConfiguration.js +13 -6
- package/dist/service/api/fireflinkApi.service.d.ts +1 -1
- package/dist/service/api/fireflinkApi.service.js +1 -2
- package/dist/service/fireflink.service.d.ts +3 -3
- package/dist/service/fireflink.service.js +23 -21
- package/dist/service/kafka/fireflinkKafka.service.d.ts +1 -2
- package/dist/service/kafka/fireflinkKafka.service.js +6 -4
- package/dist/tests/test12.d.ts +0 -1
- package/dist/tests/test12.js +65 -78
- package/dist/tests/testkaf.d.ts +0 -1
- package/dist/tests/testkaf.js +51 -55
- package/dist/utils/InstancesDetails/getInstancesInfo.js +1 -1
- package/dist/utils/browserCap/capability.d.ts +5 -1
- package/dist/utils/browserCap/capability.js +91 -15
- package/dist/utils/helpers/domSanitizer.d.ts +1 -0
- package/dist/utils/helpers/domSanitizer.js +9 -0
- package/dist/utils/helpers/enterActionHelper.js +23 -4
- package/dist/utils/helpers/xpathcreation.js +2 -2
- package/dist/utils/javascript/jsFindElement.d.ts +1 -1
- package/dist/utils/javascript/jsFindElement.js +2 -2
- package/dist/utils/newTab/newTabTracker.js +18 -6
- package/dist/utils/workers/LocatorWorkerInterface.d.ts +22 -0
- package/dist/utils/workers/LocatorWorkerInterface.js +2 -0
- package/dist/utils/workers/LocatorWorkerPool.d.ts +13 -0
- package/dist/utils/workers/LocatorWorkerPool.js +89 -0
- package/dist/utils/workers/locatorWorker.d.ts +1 -0
- package/dist/utils/workers/locatorWorker.js +44 -0
- package/package.json +3 -1
|
@@ -1,31 +1,57 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.generateAiAndroidLocators = void 0;
|
|
4
4
|
const xpathHelpers_js_1 = require("./xpathHelpers.js");
|
|
5
|
-
const
|
|
6
|
-
const xpath = (0, xpathHelpers_js_1.
|
|
5
|
+
const addAiLocator = (locators, key, attribute, value, element, docmt, isTarget) => {
|
|
6
|
+
const xpath = (0, xpathHelpers_js_1.getAiPropertyXPath)(element, docmt, attribute, value, isTarget, 'android');
|
|
7
7
|
if (xpath &&
|
|
8
|
-
(0, xpathHelpers_js_1.
|
|
8
|
+
(0, xpathHelpers_js_1.getAiCountOfXPath)(xpath, element, docmt) === 1) {
|
|
9
9
|
locators.push({
|
|
10
10
|
key,
|
|
11
11
|
value: xpath
|
|
12
12
|
});
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
|
-
const
|
|
15
|
+
const generateAiAndroidLocators = (element, docmt, isTarget) => {
|
|
16
16
|
const locators = [];
|
|
17
17
|
const resourceId = element.getAttribute("resource-id");
|
|
18
18
|
const contentDesc = element.getAttribute("content-desc");
|
|
19
19
|
const text = element.getAttribute("text");
|
|
20
20
|
if (resourceId) {
|
|
21
|
-
|
|
21
|
+
addAiLocator(locators, "androidResourceID", "@resource-id", resourceId, element, docmt, isTarget);
|
|
22
22
|
}
|
|
23
23
|
if (contentDesc) {
|
|
24
|
-
|
|
24
|
+
addAiLocator(locators, "androidAccessibilityID", "@content-desc", contentDesc, element, docmt, isTarget);
|
|
25
25
|
}
|
|
26
26
|
if (text) {
|
|
27
|
-
|
|
27
|
+
addAiLocator(locators, "androidText", "@text", text, element, docmt, isTarget);
|
|
28
|
+
}
|
|
29
|
+
if (locators.length === 0) {
|
|
30
|
+
const relativeXpath = (0, xpathHelpers_js_1.getAIRelativeXPath)(element, docmt, isTarget, Array.from(element.attributes), "android");
|
|
31
|
+
if (relativeXpath && (0, xpathHelpers_js_1.getAiCountOfXPath)(relativeXpath, element, docmt) === 1) {
|
|
32
|
+
locators.push({
|
|
33
|
+
key: "Relative xpath",
|
|
34
|
+
value: relativeXpath
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (locators.length === 0) {
|
|
39
|
+
const absoluteXpath = (0, xpathHelpers_js_1.getAiAbsoluteXPath)(element, docmt);
|
|
40
|
+
if (absoluteXpath) {
|
|
41
|
+
if (absoluteXpath.startsWith('/hierarchy')) {
|
|
42
|
+
locators.push({
|
|
43
|
+
key: "absoluteXPath",
|
|
44
|
+
value: absoluteXpath
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
locators.push({
|
|
49
|
+
key: "absoluteXPath",
|
|
50
|
+
value: `/hierarchy${absoluteXpath}`
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
28
54
|
}
|
|
29
55
|
return locators;
|
|
30
56
|
};
|
|
31
|
-
exports.
|
|
57
|
+
exports.generateAiAndroidLocators = generateAiAndroidLocators;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { SelectorMode } from "../types/locator.js";
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const parseAiCssSelectors: (el: Element, mode?: SelectorMode) => {
|
|
3
3
|
key: string;
|
|
4
4
|
value: string;
|
|
5
5
|
}[];
|
|
6
|
-
export declare const
|
|
7
|
-
export declare const
|
|
8
|
-
export declare const
|
|
9
|
-
export declare const
|
|
6
|
+
export declare const getIdAiCssPath: (el: HTMLElement | Element) => string | undefined;
|
|
7
|
+
export declare const getAiAttributeCssPath: (el: Element) => string | undefined;
|
|
8
|
+
export declare const getAiClassCssPath: (el: HTMLElement | Element) => string | undefined;
|
|
9
|
+
export declare const getAiAbsoluteCssPath: (el: Element) => string | undefined;
|
|
10
10
|
export declare const cssSelectors: {
|
|
11
|
-
|
|
11
|
+
parseAiCssSelectors: (el: Element, mode?: SelectorMode) => {
|
|
12
12
|
key: string;
|
|
13
13
|
value: string;
|
|
14
14
|
}[];
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
getIdAiCssPath: (el: HTMLElement | Element) => string | undefined;
|
|
16
|
+
getAiAttributeCssPath: (el: Element) => string | undefined;
|
|
17
|
+
getAiClassCssPath: (el: HTMLElement | Element) => string | undefined;
|
|
18
|
+
getAiAbsoluteCssPath: (el: Element) => string | undefined;
|
|
19
19
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cssSelectors = exports.
|
|
3
|
+
exports.cssSelectors = exports.getAiAbsoluteCssPath = exports.getAiClassCssPath = exports.getAiAttributeCssPath = exports.getIdAiCssPath = exports.parseAiCssSelectors = void 0;
|
|
4
4
|
const logData_js_1 = require("../../../utils/logger/logData.js");
|
|
5
5
|
const xpathHelpers_js_1 = require("./xpathHelpers.js");
|
|
6
|
-
const
|
|
6
|
+
const escapeAiCssAttributeValue = (value) => {
|
|
7
7
|
return String(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
8
8
|
};
|
|
9
|
-
const
|
|
9
|
+
const isAiCssSelectorUnique = (selector, el, root) => {
|
|
10
10
|
try {
|
|
11
11
|
const matches = root.querySelectorAll(selector);
|
|
12
12
|
return matches.length === 1 && matches[0] === el;
|
|
@@ -15,21 +15,21 @@ const isCssSelectorUnique = (selector, el, root) => {
|
|
|
15
15
|
return false;
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
|
-
const
|
|
18
|
+
const parseAiCssSelectors = (el, mode = "single") => {
|
|
19
19
|
const selectors = [];
|
|
20
20
|
const root = el.getRootNode();
|
|
21
21
|
try {
|
|
22
|
-
const idPath = (0, exports.
|
|
23
|
-
if (idPath &&
|
|
22
|
+
const idPath = (0, exports.getIdAiCssPath)(el);
|
|
23
|
+
if (idPath && isAiCssSelectorUnique(idPath, el, root)) {
|
|
24
24
|
selectors.push({ key: "cssSelector by id", value: idPath });
|
|
25
25
|
if (mode === "single")
|
|
26
26
|
return selectors;
|
|
27
27
|
}
|
|
28
|
-
const classPath = (0, exports.
|
|
29
|
-
if (classPath &&
|
|
28
|
+
const classPath = (0, exports.getAiClassCssPath)(el);
|
|
29
|
+
if (classPath && isAiCssSelectorUnique(classPath, el, root)) {
|
|
30
30
|
selectors.push({ key: "cssSelector by class", value: classPath });
|
|
31
31
|
}
|
|
32
|
-
const namePath = (0, exports.
|
|
32
|
+
const namePath = (0, exports.getAiAttributeCssPath)(el);
|
|
33
33
|
if (namePath) {
|
|
34
34
|
selectors.push({ key: "cssSelector by name", value: namePath });
|
|
35
35
|
}
|
|
@@ -39,27 +39,27 @@ const parseCssSelectors = (el, mode = "single") => {
|
|
|
39
39
|
}
|
|
40
40
|
return selectors;
|
|
41
41
|
};
|
|
42
|
-
exports.
|
|
43
|
-
function
|
|
42
|
+
exports.parseAiCssSelectors = parseAiCssSelectors;
|
|
43
|
+
function cssAiEscape(value) {
|
|
44
44
|
return value.replace(/([ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g, "\\$1");
|
|
45
45
|
}
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
if (!view || !(el instanceof view.Element))
|
|
46
|
+
const getIdAiCssPath = (el) => {
|
|
47
|
+
if (!el || el.nodeType !== 1)
|
|
49
48
|
return;
|
|
50
49
|
const tagName = el.tagName.toLowerCase();
|
|
51
50
|
if (tagName.includes("style") || tagName.includes("script"))
|
|
52
51
|
return;
|
|
53
52
|
const path = [];
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
let currentEl = el;
|
|
54
|
+
while (currentEl && currentEl.nodeType === 1) {
|
|
55
|
+
let selector = currentEl.nodeName?.toLowerCase();
|
|
56
|
+
if (currentEl.id && !(0, xpathHelpers_js_1.isAiNumberExist)(currentEl.id)) {
|
|
57
|
+
selector += `#${cssAiEscape(currentEl.id)}`;
|
|
58
58
|
path.unshift(selector);
|
|
59
59
|
break;
|
|
60
60
|
}
|
|
61
61
|
else {
|
|
62
|
-
let sib =
|
|
62
|
+
let sib = currentEl;
|
|
63
63
|
let nth = 1;
|
|
64
64
|
if (sib.previousElementSibling) {
|
|
65
65
|
while ((sib = sib.previousElementSibling)) {
|
|
@@ -70,17 +70,17 @@ const getIdCssPath = (el) => {
|
|
|
70
70
|
if (nth !== 1) {
|
|
71
71
|
selector += `:nth-of-type(${nth})`;
|
|
72
72
|
}
|
|
73
|
-
const parent =
|
|
73
|
+
const parent = currentEl.parentElement;
|
|
74
74
|
if (nth === 1 && parent?.childElementCount > 1) {
|
|
75
75
|
selector += `:nth-child(${nth})`;
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
path.unshift(selector);
|
|
79
|
-
|
|
79
|
+
currentEl = currentEl.parentElement;
|
|
80
80
|
}
|
|
81
81
|
return path.join(" > ");
|
|
82
82
|
};
|
|
83
|
-
exports.
|
|
83
|
+
exports.getIdAiCssPath = getIdAiCssPath;
|
|
84
84
|
const EXCLUDED_ATTRS = new Set([
|
|
85
85
|
"id",
|
|
86
86
|
"class",
|
|
@@ -89,55 +89,54 @@ const EXCLUDED_ATTRS = new Set([
|
|
|
89
89
|
"ff-inspecter",
|
|
90
90
|
"ff-xpath"
|
|
91
91
|
]);
|
|
92
|
-
function
|
|
92
|
+
function getAiAttributeSelectors(el) {
|
|
93
93
|
return Array.from(el.attributes)
|
|
94
94
|
.filter((attr) => !EXCLUDED_ATTRS.has(attr?.name?.toLowerCase()) &&
|
|
95
95
|
attr.value &&
|
|
96
|
-
!(0, xpathHelpers_js_1.
|
|
97
|
-
.map((attr) => `[${attr.name}="${
|
|
96
|
+
!(0, xpathHelpers_js_1.isAiNumberExist)(attr.value))
|
|
97
|
+
.map((attr) => `[${attr.name}="${escapeAiCssAttributeValue(attr.value)}"]`);
|
|
98
98
|
}
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
if (!view || !(el instanceof view.Element))
|
|
99
|
+
const getAiAttributeCssPath = (el) => {
|
|
100
|
+
if (!el || el.nodeType !== 1)
|
|
102
101
|
return;
|
|
103
102
|
const root = el.getRootNode();
|
|
104
103
|
const tag = el.tagName.toLowerCase();
|
|
105
104
|
if (tag === "style" || tag === "script")
|
|
106
105
|
return;
|
|
107
|
-
const attrSelectors =
|
|
106
|
+
const attrSelectors = getAiAttributeSelectors(el);
|
|
108
107
|
for (const attrSelector of attrSelectors) {
|
|
109
108
|
const candidate = `${tag}${attrSelector}`;
|
|
110
|
-
if (
|
|
109
|
+
if (isAiCssSelectorUnique(candidate, el, root)) {
|
|
111
110
|
return candidate;
|
|
112
111
|
}
|
|
113
112
|
}
|
|
114
113
|
return;
|
|
115
114
|
};
|
|
116
|
-
exports.
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
if (!view || !(el instanceof view.Element))
|
|
115
|
+
exports.getAiAttributeCssPath = getAiAttributeCssPath;
|
|
116
|
+
const getAiClassCssPath = (el) => {
|
|
117
|
+
if (!el || el.nodeType !== 1)
|
|
120
118
|
return;
|
|
121
119
|
const tagName = el.tagName.toLowerCase();
|
|
122
120
|
if (tagName.includes("style") || tagName.includes("script"))
|
|
123
121
|
return;
|
|
124
122
|
const path = [];
|
|
125
|
-
|
|
126
|
-
while (
|
|
127
|
-
let selector =
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
123
|
+
let currentEl = el;
|
|
124
|
+
while (currentEl && currentEl.nodeType === 1) {
|
|
125
|
+
let selector = currentEl.nodeName?.toLowerCase();
|
|
126
|
+
const className = currentEl.getAttribute("class") || currentEl.className;
|
|
127
|
+
if (typeof className === "string" &&
|
|
128
|
+
className &&
|
|
129
|
+
!(0, xpathHelpers_js_1.isAiNumberExist)(className)) {
|
|
130
|
+
currentEl.classList?.remove("marked-element-temp");
|
|
131
|
+
currentEl.classList?.remove("removePointers");
|
|
132
|
+
if (className) {
|
|
133
|
+
selector += `.${className.trim().replace(/\s+/g, ".")}`;
|
|
135
134
|
path.unshift(selector);
|
|
136
135
|
break;
|
|
137
136
|
}
|
|
138
137
|
}
|
|
139
138
|
else {
|
|
140
|
-
let sib =
|
|
139
|
+
let sib = currentEl;
|
|
141
140
|
let nth = 1;
|
|
142
141
|
if (sib.previousElementSibling) {
|
|
143
142
|
while ((sib = sib.previousElementSibling)) {
|
|
@@ -148,24 +147,22 @@ const getClassCssPath = (el) => {
|
|
|
148
147
|
if (nth !== 1) {
|
|
149
148
|
selector += `:nth-of-type(${nth})`;
|
|
150
149
|
}
|
|
151
|
-
const parent =
|
|
150
|
+
const parent = currentEl.parentElement;
|
|
152
151
|
if (nth === 1 && parent?.childElementCount > 1) {
|
|
153
152
|
selector += `:nth-child(${nth})`;
|
|
154
153
|
}
|
|
155
154
|
}
|
|
156
155
|
path.unshift(selector);
|
|
157
|
-
|
|
156
|
+
currentEl = currentEl.parentElement;
|
|
158
157
|
}
|
|
159
158
|
return path.join(" > ");
|
|
160
159
|
};
|
|
161
|
-
exports.
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
if (!view || !(el instanceof view.Element))
|
|
160
|
+
exports.getAiClassCssPath = getAiClassCssPath;
|
|
161
|
+
const getAiAbsoluteCssPath = (el) => {
|
|
162
|
+
if (!el || el.nodeType !== 1)
|
|
165
163
|
return;
|
|
166
164
|
const path = [];
|
|
167
|
-
|
|
168
|
-
while (el && el.nodeType === NodeRef.ELEMENT_NODE) {
|
|
165
|
+
while (el && el.nodeType === 1) {
|
|
169
166
|
const tagName = el.tagName.toLowerCase();
|
|
170
167
|
if (tagName === "style" || tagName === "script")
|
|
171
168
|
return;
|
|
@@ -182,11 +179,11 @@ const getAbsoluteCssPath = (el) => {
|
|
|
182
179
|
}
|
|
183
180
|
return path.join(" > ");
|
|
184
181
|
};
|
|
185
|
-
exports.
|
|
182
|
+
exports.getAiAbsoluteCssPath = getAiAbsoluteCssPath;
|
|
186
183
|
exports.cssSelectors = {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
184
|
+
parseAiCssSelectors: exports.parseAiCssSelectors,
|
|
185
|
+
getIdAiCssPath: exports.getIdAiCssPath,
|
|
186
|
+
getAiAttributeCssPath: exports.getAiAttributeCssPath,
|
|
187
|
+
getAiClassCssPath: exports.getAiClassCssPath,
|
|
188
|
+
getAiAbsoluteCssPath: exports.getAiAbsoluteCssPath
|
|
192
189
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { XPathEntry } from "../types/locator.js";
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const generateAiIOSLocators: (element: HTMLElement | Element, docmt: Document, isTarget: boolean) => XPathEntry[];
|
|
@@ -1,59 +1,82 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.generateAiIOSLocators = void 0;
|
|
4
4
|
const xpathHelpers_js_1 = require("./xpathHelpers.js");
|
|
5
5
|
const logData_js_1 = require("../../../utils/logger/logData.js");
|
|
6
|
-
const
|
|
7
|
-
const xpath = (0, xpathHelpers_js_1.
|
|
6
|
+
const addAiLocator = (locators, key, attribute, value, element, docmt, isTarget) => {
|
|
7
|
+
const xpath = (0, xpathHelpers_js_1.getAiPropertyXPath)(element, docmt, attribute, value, isTarget, 'ios');
|
|
8
8
|
if (xpath &&
|
|
9
|
-
(0, xpathHelpers_js_1.
|
|
9
|
+
(0, xpathHelpers_js_1.getAiCountOfXPath)(xpath, element, docmt) === 1) {
|
|
10
10
|
locators.push({
|
|
11
11
|
key,
|
|
12
12
|
value: xpath
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
-
const
|
|
16
|
+
const generateAiIOSLocators = (element, docmt, isTarget) => {
|
|
17
17
|
const locators = [];
|
|
18
18
|
const name = element.getAttribute("name");
|
|
19
19
|
const label = element.getAttribute("label");
|
|
20
20
|
const value = element.getAttribute("value");
|
|
21
|
-
const classChain =
|
|
21
|
+
const classChain = getAiOptimalClassChain(docmt, element, [
|
|
22
22
|
"label",
|
|
23
23
|
"name",
|
|
24
24
|
"value",
|
|
25
25
|
]);
|
|
26
|
-
const predicate =
|
|
26
|
+
const predicate = getAiOptimalPredicateString(docmt, element, [
|
|
27
27
|
"label",
|
|
28
28
|
"name",
|
|
29
29
|
"value",
|
|
30
30
|
"type",
|
|
31
31
|
]);
|
|
32
32
|
if (name) {
|
|
33
|
-
|
|
33
|
+
addAiLocator(locators, "iosAccessibilityID", "@name", name, element, docmt, isTarget);
|
|
34
34
|
}
|
|
35
35
|
if (label) {
|
|
36
|
-
|
|
36
|
+
addAiLocator(locators, "iosLabel", "@label", label, element, docmt, isTarget);
|
|
37
37
|
}
|
|
38
38
|
if (value) {
|
|
39
|
-
|
|
39
|
+
addAiLocator(locators, "iosValue", "@value", value, element, docmt, isTarget);
|
|
40
40
|
}
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
if (locators.length === 0) {
|
|
42
|
+
let absoluteXpath = (0, xpathHelpers_js_1.getAiAbsoluteXPath)(element, docmt);
|
|
43
|
+
if (absoluteXpath) {
|
|
44
|
+
if (absoluteXpath.startsWith('/AppiumAUT')) {
|
|
45
|
+
absoluteXpath = absoluteXpath.substring('/AppiumAUT'.length);
|
|
46
|
+
if (!absoluteXpath.startsWith('/')) {
|
|
47
|
+
absoluteXpath = `/${absoluteXpath}`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (absoluteXpath.startsWith('AppiumAUT')) {
|
|
51
|
+
absoluteXpath = absoluteXpath.substring('AppiumAUT'.length);
|
|
52
|
+
if (!absoluteXpath.startsWith('/')) {
|
|
53
|
+
absoluteXpath = `/${absoluteXpath}`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
locators.push({
|
|
57
|
+
key: "absoluteXPath",
|
|
58
|
+
value: absoluteXpath
|
|
59
|
+
});
|
|
60
|
+
}
|
|
46
61
|
}
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
if (locators.length === 0) {
|
|
63
|
+
if (classChain) {
|
|
64
|
+
locators.push({
|
|
65
|
+
key: "iosClassChain",
|
|
66
|
+
value: `**${classChain}`,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (predicate) {
|
|
70
|
+
locators.push({
|
|
71
|
+
key: "iosPredicateString",
|
|
72
|
+
value: predicate,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
52
75
|
}
|
|
53
76
|
return locators;
|
|
54
77
|
};
|
|
55
|
-
exports.
|
|
56
|
-
function
|
|
78
|
+
exports.generateAiIOSLocators = generateAiIOSLocators;
|
|
79
|
+
function getAiOptimalClassChain(doc, domNode, uniqueAttributes) {
|
|
57
80
|
try {
|
|
58
81
|
// BASE CASE #1: If this isn't an element, we're above the root, or this is `XCUIElementTypeApplication`,
|
|
59
82
|
// which is not an official XCUITest element, return empty string
|
|
@@ -65,13 +88,13 @@ function getOptimalClassChain(doc, domNode, uniqueAttributes) {
|
|
|
65
88
|
// BASE CASE #2: If this node has a unique class chain based on attributes then return it
|
|
66
89
|
for (const attrName of uniqueAttributes) {
|
|
67
90
|
const attrValue = domNode.getAttribute(attrName);
|
|
68
|
-
if (attrValue && !(0, xpathHelpers_js_1.
|
|
91
|
+
if (attrValue && !(0, xpathHelpers_js_1.isAiNumberExist)(attrValue)) {
|
|
69
92
|
const xpathe = `//${domNode.tagName || '*'}[@${attrName}="${attrValue}"]`;
|
|
70
93
|
let classChain = `/${domNode.tagName || '*'}[\`${attrName} == "${attrValue}"\`]`;
|
|
71
94
|
let othersWithAttr;
|
|
72
95
|
// If the XPath does not parse, move to the next unique attribute
|
|
73
96
|
try {
|
|
74
|
-
othersWithAttr = (0, xpathHelpers_js_1.
|
|
97
|
+
othersWithAttr = (0, xpathHelpers_js_1.getAiCountOfXPath)(xpathe, domNode, doc);
|
|
75
98
|
}
|
|
76
99
|
catch (ign) {
|
|
77
100
|
logData_js_1.logger.error(ign);
|
|
@@ -82,7 +105,7 @@ function getOptimalClassChain(doc, domNode, uniqueAttributes) {
|
|
|
82
105
|
}
|
|
83
106
|
// If the attribute isn't actually unique, get it's index too
|
|
84
107
|
if (othersWithAttr > 1) {
|
|
85
|
-
const index = (0, xpathHelpers_js_1.
|
|
108
|
+
const index = (0, xpathHelpers_js_1.findAiXpathWithIndex)(xpathe, domNode, doc, 0);
|
|
86
109
|
if (index) {
|
|
87
110
|
classChain = `${classChain}[${index}]`;
|
|
88
111
|
return classChain;
|
|
@@ -105,7 +128,8 @@ function getOptimalClassChain(doc, domNode, uniqueAttributes) {
|
|
|
105
128
|
}
|
|
106
129
|
}
|
|
107
130
|
// Make a recursive call to this nodes parents and prepend it to this xpath
|
|
108
|
-
|
|
131
|
+
const parent = domNode.parentElement || domNode.parentNode;
|
|
132
|
+
return (getAiOptimalClassChain(doc, parent, uniqueAttributes) +
|
|
109
133
|
classChain);
|
|
110
134
|
}
|
|
111
135
|
catch (error) {
|
|
@@ -114,7 +138,7 @@ function getOptimalClassChain(doc, domNode, uniqueAttributes) {
|
|
|
114
138
|
return null;
|
|
115
139
|
}
|
|
116
140
|
}
|
|
117
|
-
function
|
|
141
|
+
function getAiOptimalPredicateString(doc, domNode, uniqueAttributes) {
|
|
118
142
|
try {
|
|
119
143
|
// BASE CASE #1: If this isn't an element, we're above the root, or this is `XCUIElementTypeApplication`,
|
|
120
144
|
// which is not an official XCUITest element, return empty string
|
|
@@ -131,14 +155,14 @@ function getOptimalPredicateString(doc, domNode, uniqueAttributes) {
|
|
|
131
155
|
if (!attrValue) {
|
|
132
156
|
continue;
|
|
133
157
|
}
|
|
134
|
-
if (attrValue && !(0, xpathHelpers_js_1.
|
|
158
|
+
if (attrValue && !(0, xpathHelpers_js_1.isAiNumberExist)(attrValue)) {
|
|
135
159
|
xpathAttributes.push(`@${attrName}="${attrValue}"`);
|
|
136
160
|
const xpathe = `//*[${xpathAttributes.join(' and ')}]`;
|
|
137
161
|
predicateString.push(`${attrName} == "${attrValue}"`);
|
|
138
162
|
let othersWithAttr;
|
|
139
163
|
// If the XPath does not parse, move to the next unique attribute
|
|
140
164
|
try {
|
|
141
|
-
othersWithAttr = (0, xpathHelpers_js_1.
|
|
165
|
+
othersWithAttr = (0, xpathHelpers_js_1.getAiCountOfXPath)(xpathe, domNode, doc);
|
|
142
166
|
}
|
|
143
167
|
catch (ign) {
|
|
144
168
|
logData_js_1.logger.error(ign);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export declare const
|
|
1
|
+
export declare const findAiRelativeXpath: (element1: Element, element2: Element, docmt: Document, xpaths1: any[], xpaths2: any[], isIndex: boolean, multiElementReferenceMode?: boolean, allowedRelations?: string[] | null) => any[];
|
|
2
|
+
export declare const getAiSmartRelations: (element1: HTMLElement | Element, element2: HTMLElement | Element) => string[];
|
|
3
3
|
declare const referenceXpath: {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
findAiRelativeXpath: (element1: Element, element2: Element, docmt: Document, xpaths1: any[], xpaths2: any[], isIndex: boolean, multiElementReferenceMode?: boolean, allowedRelations?: string[] | null) => any[];
|
|
5
|
+
getAiDescendantXpath: (refExpectElement: Array<HTMLElement | Element>, docmt: Document, xpaths1: {
|
|
6
6
|
key: string;
|
|
7
7
|
value: string;
|
|
8
8
|
}[], xpaths2: {
|
|
@@ -12,7 +12,7 @@ declare const referenceXpath: {
|
|
|
12
12
|
key: string;
|
|
13
13
|
value: string;
|
|
14
14
|
}[] | undefined;
|
|
15
|
-
|
|
15
|
+
getAiAncestorBridgeXpath: (element1: HTMLElement | Element, element2: HTMLElement | Element, relation: "ancestor" | "ancestor-or-self", xpaths1: {
|
|
16
16
|
key: string;
|
|
17
17
|
value: string;
|
|
18
18
|
}[], xpaths2: {
|
|
@@ -22,14 +22,14 @@ declare const referenceXpath: {
|
|
|
22
22
|
key: string;
|
|
23
23
|
value: string;
|
|
24
24
|
}[];
|
|
25
|
-
|
|
25
|
+
getAiXpathRelationExpression: (element1: HTMLElement | Element, element2: HTMLElement | Element, relation: string, xpath1: any[], xpath2: any[], isIndex: boolean, multiElementReferenceMode: boolean) => {
|
|
26
26
|
key: string;
|
|
27
27
|
value: any;
|
|
28
28
|
}[];
|
|
29
|
-
|
|
29
|
+
getAiTraverseXpathExpression: (xpathe1: string, absoluteXpathElements: string[], element2: HTMLElement | Element, refExpectElement: Array<HTMLElement | Element>, docmt: Node, relation: string, isIndex: boolean, multiElementReferenceMode: boolean) => {
|
|
30
30
|
key: string;
|
|
31
31
|
value: string;
|
|
32
32
|
}[] | undefined;
|
|
33
|
-
|
|
33
|
+
getAiSmartRelations: (element1: HTMLElement | Element, element2: HTMLElement | Element) => string[];
|
|
34
34
|
};
|
|
35
35
|
export default referenceXpath;
|