ff-automationv2 2.2.21 → 2.2.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,222 @@
1
+ import { remote } from 'webdriverio';
2
+ import { DomSimplifier } from "../domAnalysis/simplifyAndFlatten.js";
3
+ import { DomSearcher } from "../domAnalysis/searchBest.js";
4
+ import { DomRelationshipBuilder } from "../domAnalysis/relativeElementsFromDom.js";
5
+ import { getAnnotatedDOM } from "../utils/DomExtraction/jsForAttributeInjection.js";
6
+ import { ElementGetter } from "../fireflinkData/fireflinkLocators/getListOfLocators.js";
7
+ import OpenAI from "openai";
8
+ import { DomProcessingEngine } from "../domAnalysis/getRelaventElements.js";
9
+ let simplifier = new DomSimplifier();
10
+ let searcher = new DomSearcher();
11
+ let relationshipBuilder = new DomRelationshipBuilder();
12
+ let data = new ElementGetter();
13
+ const client = new OpenAI({
14
+ baseURL: "https://api.groq.com/openai/v1",
15
+ apiKey: "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",
16
+ });
17
+ async function generateIndex(step, extractedDomJson) {
18
+ let prompt = `
19
+ -You are an intelligent assistant that extracts structured UI action data.
20
+ -Given a structured UI JSON representation with uniquely identified elements (ff-inspect values like Fire-Flink-0, Fire-Flink-1, Fire-Flink-2, Fire-Flink-3... in DOM order),
21
+ -locate the most appropriate element for an automation step by performing keyword-based matching using exact, partial, and fuzzy strategies, and
22
+ return the identifier of the best match.
23
+
24
+ Return **only valid JSON** in the following format:
25
+ {
26
+ "attribute_value": "Fire-Flink-x",
27
+ "action": "x",
28
+ "input_text": "x",
29
+ "elementType": "x"
30
+ }
31
+
32
+ Rules:
33
+ You are an AI assistant. For the step : ${step}, extract the element keyword from the step (the field name like 'Leaving from', 'Going To').
34
+ - Simplified JSON: ${JSON.stringify(extractedDomJson)} — if it is empty, null, or has no valid data, return strictly "attribute_value":"Fire-Flink-0" and never use any other Fire-Flink-x value.
35
+ - Select the closest semantic match to step and return only its attribute_value, else Fire-Flink-0.
36
+ - **Find the FF-inspecter attribute value of the element in the Simplified JSON whose text or attributes best match the atep.**
37
+ - If multiple matches exist, use the reference element and choose the closest match by ff-inspect distance.
38
+ important example: step: "click on login below user login"
39
+ simplified json:
40
+ login - ff-inspect-300
41
+ user login - ff-inspect-790
42
+ login - ff-inspect-803
43
+ then should return login - ff-inspect-803 witch is near to user reference element user login - ff-inspect-790
44
+ `;
45
+ const response = await client.responses.create({
46
+ model: "openai/gpt-oss-20b",
47
+ input: prompt,
48
+ });
49
+ return JSON.parse(response.output_text);
50
+ }
51
+ async function generateKeywords(elementName) {
52
+ const prompt = `
53
+ You are an AI that generates keyword variations for identifying form elements in the DOM.
54
+
55
+ Given an element name, return ONLY a JSON array of relevant human-readable variations that could be used to identify that element in UI labels, placeholders, or attributes.
56
+
57
+ Rules:
58
+ - Return strictly a JSON array (no explanation, no extra text)
59
+ - Include common variations, phrasing, and synonyms
60
+ - Keep the list concise and relevant
61
+ - Do NOT include unrelated terms
62
+ - Do NOT include misspellings
63
+
64
+ Example:
65
+ Input: email
66
+
67
+ Output:
68
+ [
69
+ "email",
70
+ "email address",
71
+ "e-mail",
72
+ "mail",
73
+ "user email",
74
+ ]
75
+
76
+ Now generate the output for:
77
+ ${elementName}
78
+ `;
79
+ const response = await client.responses.create({
80
+ model: "openai/gpt-oss-20b",
81
+ input: prompt,
82
+ });
83
+ return response.output_text;
84
+ }
85
+ const steps = [
86
+ { action: "Open Browser" },
87
+ { action: "Maximize Browser" },
88
+ { action: "Navigate", value: "file:///D:/Bitbucket/testCase_Search/login.html" },
89
+ {
90
+ action: "Enter Text",
91
+ value: "test@example.com",
92
+ elementName: "email",
93
+ locators: [
94
+ { type: "id", value: "email" },
95
+ { type: "xpath", value: "//input[@type='email']" },
96
+ { type: "css", value: "input[placeholder='Enter Email']" }
97
+ ]
98
+ },
99
+ {
100
+ action: "Enter Text",
101
+ value: "123456",
102
+ locators: [
103
+ { type: "id", value: "password" },
104
+ { type: "xpath", value: "//input[@type='password']" },
105
+ { type: "css", value: "input[placeholder='Enter Password']" }
106
+ ]
107
+ },
108
+ {
109
+ action: "Click",
110
+ elementName: "login",
111
+ locators: [
112
+ { type: "xpath", value: "//button[text()='SignIn']" },
113
+ { type: "css", value: "buttoin" },
114
+ { type: "xpath", value: "//button[contains(text(),'SignInbtn')]" }
115
+ ]
116
+ },
117
+ ];
118
+ // ---------- ENGINE ----------
119
+ class Engine {
120
+ constructor(browser) {
121
+ this.browser = browser;
122
+ }
123
+ async open_browser() {
124
+ console.log("[STEP] Open Browser");
125
+ }
126
+ async maximize_browser() {
127
+ await this.browser.maximizeWindow();
128
+ console.log("[STEP] Maximize Browser");
129
+ }
130
+ async navigate(path) {
131
+ await this.browser.url(path);
132
+ console.log(`[STEP] Navigate → ${path}`);
133
+ }
134
+ async findElement(locators) {
135
+ for (const locator of locators) {
136
+ try {
137
+ let selector = "";
138
+ if (locator.type === "id") {
139
+ selector = `#${locator.value}`;
140
+ }
141
+ else if (locator.type === "css") {
142
+ selector = locator.value;
143
+ }
144
+ else if (locator.type === "xpath") {
145
+ selector = locator.value;
146
+ }
147
+ const element = await this.browser.$(selector);
148
+ if (await element.isExisting()) {
149
+ return element;
150
+ }
151
+ }
152
+ catch (e) {
153
+ continue;
154
+ }
155
+ }
156
+ throw new Error("Element not found");
157
+ }
158
+ async enter_text(step) {
159
+ const element = await this.findElement(step.locators);
160
+ await element.setValue(step.value);
161
+ console.log(`[STEP] Enter Text → ${step.value}`);
162
+ }
163
+ async click(step) {
164
+ const element = await this.findElement(step.locators);
165
+ await element.click();
166
+ console.log("[STEP] Click");
167
+ }
168
+ async verify_text(step) {
169
+ const element = await this.findElement(step.locators);
170
+ const isDisplayed = await element.isDisplayed();
171
+ if (isDisplayed) {
172
+ console.log(`[PASS] Found → ${step.value}`);
173
+ }
174
+ else {
175
+ console.log(`[FAIL] Not Found → ${step.value}`);
176
+ }
177
+ }
178
+ async close_browser() {
179
+ await this.browser.deleteSession();
180
+ console.log("[STEP] Close Browser");
181
+ }
182
+ }
183
+ // ---------- ACTION MAPPER ----------
184
+ function actionToMethod(action) {
185
+ return action.toLowerCase().replace(/ /g, "_");
186
+ }
187
+ let browser;
188
+ // ---------- MAIN EXECUTION ----------
189
+ (async () => {
190
+ browser = await remote({
191
+ logLevel: 'error',
192
+ capabilities: {
193
+ browserName: 'chrome'
194
+ }
195
+ });
196
+ const engine = new Engine(browser);
197
+ for (const step of steps) {
198
+ try {
199
+ const methodName = actionToMethod(step.action);
200
+ const method = engine[methodName];
201
+ if (step.value && !step.locators) {
202
+ await method.call(engine, step.value);
203
+ }
204
+ else {
205
+ await method.call(engine, step);
206
+ }
207
+ }
208
+ catch (error) {
209
+ let domInfo = await getAnnotatedDOM(browser);
210
+ const domProcessor = new DomProcessingEngine();
211
+ let extractedRelevantDom = domProcessor.webProcess({
212
+ keywords: await generateKeywords(JSON.stringify(step)),
213
+ rawDom: domInfo.dom,
214
+ stepCount: 1
215
+ });
216
+ console.log(await generateIndex(JSON.stringify(step), extractedRelevantDom));
217
+ let newData = await data.getFireFlinkElement(domInfo.dom, "[ff-inspect='Fire-Flink-8']");
218
+ console.log(newData);
219
+ break;
220
+ }
221
+ }
222
+ })();
@@ -8,28 +8,13 @@ const ssl = {
8
8
  rejectUnauthorized: false,
9
9
  };
10
10
  const runner = new AutomationRunner();
11
- console.log(new Date().getTime());
12
11
  runner.run({
13
12
  userStory: [
14
13
  ["Open browser"],
15
14
  ["Navigate to https://www.google.com/"],
16
15
  ["Maximize the browser"],
17
- // ["Navigate to https://www.google.com/"],
18
- // ["Maximize the browser"],
19
- // ["Navigate to https://www.google.com/"],
20
- // ["Maximize the browser"],
21
- // ["click on Gmail link"],
16
+ ["Wait for 10 seconds"],
22
17
  ["Close browser"],
23
- // ["start iteration using 'Data1' Dataprovider"],
24
- // ["enter 'startIteration1' in search field"],
25
- // ["enter level-A in search field"],
26
- // ["start iteration using 'Data1' Dataprovider"],
27
- // ["enter 'startIteration1' in search field"],
28
- // ["enter level-B in search field"],
29
- // ["End iteration"],
30
- // ["End iteration"],
31
- // ["click on Gmail link"],
32
- // ["Close browser"],
33
18
  ],
34
19
  platform: "web",
35
20
  pageDetails: {
@@ -40,8 +25,6 @@ runner.run({
40
25
  },
41
26
  sessionPath: path.join("D:", "Bitbucket", "automationV2"),
42
27
  serverHost: "https://test3.fireflink.com",
43
- // topic: "",
44
- // serviceAccounts: "",
45
28
  webSocketId: "",
46
29
  generatedBy: "",
47
30
  licenseType: "C-Professional",
@@ -81,5 +64,5 @@ runner.run({
81
64
  browserVersion: "146"
82
65
  },
83
66
  isTerminate: false,
84
- token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJRUFRfTnFuMkxxdDVmN09tOElWaW53dUJlR3ZVUUVBUkdxZkFuRHJxZU9NIn0.eyJleHAiOjE3NzUyODczODQsImlhdCI6MTc3NTIwMDk4NCwianRpIjoib25ydHJvOjYzOTYzMjJkLTNlZWYtNDg1NC04NmUzLTdlNzBhNjY1ZjM0MSIsImlzcyI6Imh0dHA6Ly8xMDMuMTgyLjIxMC4yMjY6MzAxMDcvcmVhbG1zL0ZpcmVGbGluay10ZXN0MyIsImF1ZCI6InRhcmdldC1jbGllbnQiLCJzdWIiOiJmOmNhMzBmNDk3LTY1Y2YtNGU4Zi1iZGE3LTE0ZjM1NTNiYzZmNTpqYWlha2FzaEB5b3BtYWlsLmNvbSIsInR5cCI6IkJlYXJlciIsImF6cCI6ImZsaW5rLXNlcnZpY2UiLCJzaWQiOiIxMDkzNTU4Yi0xMDY4LTQxM2MtYjhlNi0wMjE3NzQwODBjMjgiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIioiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsImN1cnJlbnRMaWNlbnNlSWQiOiJMSUMzOTg1IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJjdXJyZW50UHJpdmlsZWdlIjoiU3VwZXIgQWRtaW4iLCJmdWxsTmFtZSI6ImphaSIsImFjdGl2YXRpb25TdGF0dXMiOiJBQ1RJVkUiLCJwcml2aWxlZ2UiOiJTdXBlciBBZG1pbiIsImxpY2Vuc2VOYW1lIjoiRmlyZUZsaW5rIC0gTElDMzk4NSIsInByZWZlcnJlZF91c2VybmFtZSI6ImphaSIsInVzZXJOYW1lIjoiamFpYWthc2hAeW9wbWFpbC5jb20iLCJiaWxsaW5nQ3ljbGUiOiJRdWFydGVybHkiLCJpZCI6IlVTUjI2OTM1IiwibGljZW5zZUlkIjoiTElDMzk4NSIsImVtYWlsIjoiamFpYWthc2hAeW9wbWFpbC5jb20ifQ.NOa6gz1thU8Qh04dvJMwUvGo3FZVc_ZAMbHL0j0pg_wOkmshcd8LSua0RoFYbBw5LR2RjJhVBkiZ2zD6s28EqdUdMJwjFfx4QF9ol8ut1T6-ohI_-xtCy1wdzx-dJ7svVSc7zptEcYEMEnkGEPXhTIjB0iql-Ry5MM2CkjOQP5yPdO3W8Lua2kSQmXWwWfZJSSnem8foN4oG7uJ_4T8Yh8V69iI2Trsbdp5k8CXUxs42vI73KyX0qwzcL-B-X6o1DnOaNS6T6RI7t9kGq6WXW0Iu29EVdqQ3jVnkPbOFfvSdRYRCb9Uw4qZL2qUQK3V31Jqw6Rd-r1IjDmBcXogoTg"
67
+ token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJRUFRfTnFuMkxxdDVmN09tOElWaW53dUJlR3ZVUUVBUkdxZkFuRHJxZU9NIn0.eyJleHAiOjE3NzU4MjY4NjEsImlhdCI6MTc3NTc0MDQ2MSwianRpIjoib25ydHJvOjBhMTc3YWVmLTU0ZWEtNDVlOS1iNzUyLTMzNjJjZTcwZjA3NiIsImlzcyI6Imh0dHA6Ly8xMDMuMTgyLjIxMC4yMjY6MzAxMDcvcmVhbG1zL0ZpcmVGbGluay10ZXN0MyIsImF1ZCI6InRhcmdldC1jbGllbnQiLCJzdWIiOiJmOmNhMzBmNDk3LTY1Y2YtNGU4Zi1iZGE3LTE0ZjM1NTNiYzZmNTpqYWlha2FzaEB5b3BtYWlsLmNvbSIsInR5cCI6IkJlYXJlciIsImF6cCI6ImZsaW5rLXNlcnZpY2UiLCJzaWQiOiJmY2EwZjMyNi1kMTA2LTQxYzktOGQwMy1kYzYzMTdjMDE0MTUiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIioiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsImN1cnJlbnRMaWNlbnNlSWQiOiJMSUMzOTg1IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJjdXJyZW50UHJpdmlsZWdlIjoiU3VwZXIgQWRtaW4iLCJmdWxsTmFtZSI6ImphaSIsImFjdGl2YXRpb25TdGF0dXMiOiJBQ1RJVkUiLCJwcml2aWxlZ2UiOiJTdXBlciBBZG1pbiIsImxpY2Vuc2VOYW1lIjoiRmlyZUZsaW5rIC0gTElDMzk4NSIsInByZWZlcnJlZF91c2VybmFtZSI6ImphaSIsInVzZXJOYW1lIjoiamFpYWthc2hAeW9wbWFpbC5jb20iLCJiaWxsaW5nQ3ljbGUiOiJRdWFydGVybHkiLCJpZCI6IlVTUjI2OTM1IiwibGljZW5zZUlkIjoiTElDMzk4NSIsImVtYWlsIjoiamFpYWthc2hAeW9wbWFpbC5jb20ifQ.iWJJEzB83jy-YGIywIM1GYTqj3I23FZP0UMOy1VfB1vU1OBxcGWpJeHsJw-TA3s6ihHjQs-xCMj41DGDfEOVBUGLHwb0OLnj2wtoyjdsyc_qLegiWe4CDVmfF2zjhubF3gRhP1ZyuVHEcUQJmx_BuCL3FdeO4Vr6T-KM2TCniyXue9RLgVanuxqt8-bcGBtWfL8bYapecky8mjuCmbZNIA5plrK9b5BMf9N-lOp8fEcad0f9IWCA0Z8ixRVwaALnERDiZ0FwqvSxAnWxlb9oLeoZKRtVSYvKHB3BZQaimFyZqXN8RaMHHUpSEcDuTzbXkWbg-6xOi6Bm2qkoEQuvqA"
85
68
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ff-automationv2",
3
- "version": "2.2.21",
3
+ "version": "2.2.23",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "This lib is used to automate the manual testcase",
@@ -49,24 +49,23 @@
49
49
  "nodemon": "3.1.11",
50
50
  "ts-node": "10.9.2",
51
51
  "typescript": "^5.9.3",
52
- "webdriverio": "9.26.1",
53
- "typescript-eslint": "8.56.0"
52
+ "typescript-eslint": "8.56.0",
53
+ "webdriverio": "9.26.1"
54
+ },
55
+ "peerDependencies": {
56
+ "canvas": "^3.2.3"
54
57
  },
55
58
  "dependencies": {
56
59
  "@xmldom/xmldom": "^0.8.11",
57
60
  "axios": "^1.13.5",
58
- "canvas": "3.2.1",
59
61
  "cheerio": "1.2.0",
60
- "devtools": "^8.42.0",
61
- "dotenv": "^17.3.1",
62
62
  "fast-fuzzy": "^1.12.0",
63
- "fs-extra": "11.3.3",
64
63
  "js-beautify": "1.15.1",
65
- "jsdom": "27.4.0",
66
- "kafkajs": "^2.2.4",
67
64
  "openai": "6.18.0",
68
65
  "uuid": "13.0.0",
66
+ "xpath": "^0.0.34",
69
67
  "webdriverio": "9.26.1",
70
- "xpath": "^0.0.34"
68
+ "kafkajs": "^2.2.4",
69
+ "jsdom": "27.4.0"
71
70
  }
72
71
  }