ff-automationv2 2.2.13 → 2.2.15

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.
Files changed (89) hide show
  1. package/dist/ai/llmprompts/systemPrompts/combinedActionExtractorPromptMob.js +4 -3
  2. package/dist/ai/llmprompts/systemPrompts/errorDescriptionPrompt.js +9 -11
  3. package/dist/ai/llmprompts/systemPrompts/fireflinkElementIndexExtactors.js +7 -7
  4. package/dist/ai/llmprompts/systemPrompts/fireflinkElementIndexExtractor_Mob.js +39 -0
  5. package/dist/ai/llmprompts/systemPrompts/mobileKeywordExtractor.js +2 -1
  6. package/dist/ai/llmprompts/systemPrompts/verifyActionExtractorPromptMob.js +2 -1
  7. package/dist/ai/llmprompts/systemPrompts/visionPrompt.js +3 -2
  8. package/dist/ai/llmprompts/systemPrompts/waitActionExtractorPrompt.js +1 -0
  9. package/dist/ai/llmprompts/systemPrompts/waitActionExtractorPromptMob.js +1 -0
  10. package/dist/automation/actions/executor.d.ts +19 -1
  11. package/dist/automation/actions/executor.js +303 -1
  12. package/dist/automation/actions/interaction/click/MOB_DoubleTapAtSpecifiedLocation.d.ts +2 -0
  13. package/dist/automation/actions/interaction/click/MOB_DoubleTapAtSpecifiedLocation.js +26 -0
  14. package/dist/automation/actions/interaction/elementLessAction/MobCheckIfAppIsClosed.d.ts +2 -0
  15. package/dist/automation/actions/interaction/elementLessAction/MobCheckIfAppIsClosed.js +20 -0
  16. package/dist/automation/actions/interaction/elementLessAction/MobRunAppInBackgroundInterface.d.ts +2 -0
  17. package/dist/automation/actions/interaction/elementLessAction/MobRunAppInBackgroundInterface.js +18 -0
  18. package/dist/automation/actions/interaction/enterActions/EnterInputIntoElementFromClipBoardInterface_mob.d.ts +2 -0
  19. package/dist/automation/actions/interaction/enterActions/EnterInputIntoElementFromClipBoardInterface_mob.js +26 -0
  20. package/dist/automation/actions/interaction/enterActions/enterInput.js +2 -2
  21. package/dist/automation/actions/interaction/enterActions/enterInputAndPress.js +1 -1
  22. package/dist/automation/actions/interaction/enterActions/enterusingJs.js +1 -1
  23. package/dist/automation/actions/interaction/enterActions/waitAndEnter.js +3 -3
  24. package/dist/automation/actions/interaction/find/MOB_FindElement.d.ts +2 -0
  25. package/dist/automation/actions/interaction/find/MOB_FindElement.js +34 -0
  26. package/dist/automation/actions/interaction/find/findElements.js +16 -2
  27. package/dist/automation/actions/interaction/get/getScreenshot.js +14 -16
  28. package/dist/automation/actions/interaction/get/getScreenshotAs.js +26 -16
  29. package/dist/automation/actions/interaction/pinch/PinchInByPercentMob.d.ts +2 -0
  30. package/dist/automation/actions/interaction/pinch/PinchInByPercentMob.js +27 -0
  31. package/dist/automation/actions/interaction/pinch/PinchOutByPercentMob.d.ts +2 -0
  32. package/dist/automation/actions/interaction/pinch/PinchOutByPercentMob.js +27 -0
  33. package/dist/automation/actions/interaction/press/mobPressBackSpaceKey.d.ts +2 -0
  34. package/dist/automation/actions/interaction/press/mobPressBackSpaceKey.js +16 -0
  35. package/dist/automation/actions/interaction/press/mobPressSpaceKey.d.ts +2 -0
  36. package/dist/automation/actions/interaction/press/mobPressSpaceKey.js +16 -0
  37. package/dist/automation/actions/interaction/swipe/swipeDirectionNTimes.d.ts +2 -0
  38. package/dist/automation/actions/interaction/swipe/swipeDirectionNTimes.js +27 -0
  39. package/dist/automation/actions/interaction/swipe/swipeDownToElement.d.ts +2 -0
  40. package/dist/automation/actions/interaction/swipe/swipeDownToElement.js +46 -0
  41. package/dist/automation/actions/interaction/swipe/swipeLeftToElement.d.ts +2 -0
  42. package/dist/automation/actions/interaction/swipe/swipeLeftToElement.js +46 -0
  43. package/dist/automation/actions/interaction/swipe/swipeRightToElement.d.ts +2 -0
  44. package/dist/automation/actions/interaction/swipe/swipeRightToElement.js +46 -0
  45. package/dist/automation/actions/interaction/swipe/swipeUpToElement.d.ts +2 -0
  46. package/dist/automation/actions/interaction/swipe/swipeUpToElement.js +49 -0
  47. package/dist/automation/actions/interaction/swipe/swipeUpToElementForMWeb.d.ts +2 -0
  48. package/dist/automation/actions/interaction/swipe/swipeUpToElementForMWeb.js +48 -0
  49. package/dist/automation/actions/interaction/swipe/swipeUsingReferenceElement.d.ts +2 -0
  50. package/dist/automation/actions/interaction/swipe/swipeUsingReferenceElement.js +140 -0
  51. package/dist/automation/actions/interaction/verify/VerifyElementNotContainsText.js +2 -2
  52. package/dist/automation/actions/interaction/wait/waitTillElementIsClickable.js +5 -1
  53. package/dist/automation/actions/interaction/wait/waitTillPresenceOfElement.js +1 -1
  54. package/dist/automation/actions/interface/clickActionInterface.d.ts +8 -0
  55. package/dist/automation/actions/interface/elelementLessActionInterface.d.ts +12 -0
  56. package/dist/automation/actions/interface/findActionInterface.d.ts +10 -2
  57. package/dist/automation/actions/interface/interactionActionInterface.d.ts +8 -0
  58. package/dist/automation/actions/interface/pinchActionInterface.d.ts +19 -0
  59. package/dist/automation/actions/interface/pressActionInterface.d.ts +10 -0
  60. package/dist/automation/actions/interface/swipeActionInterface.d.ts +89 -0
  61. package/dist/automation/actions/interface/swipeActionInterface.js +1 -0
  62. package/dist/automation/actions/interface/waitActionInterface.d.ts +1 -0
  63. package/dist/core/constants/allAction.js +1 -0
  64. package/dist/core/constants/supportedActions.js +9 -1
  65. package/dist/core/interfaces/actionInterface.d.ts +19 -1
  66. package/dist/core/interfaces/executionDetails.d.ts +1 -4
  67. package/dist/core/interfaces/fireflinkScriptPayloadInterface.d.ts +2 -3
  68. package/dist/core/main/actionHandlerFactory.js +62 -2
  69. package/dist/core/main/runAutomationScript.d.ts +0 -1
  70. package/dist/core/main/runAutomationScript.js +33 -23
  71. package/dist/service/fireflink.service.d.ts +2 -4
  72. package/dist/service/fireflink.service.js +4 -5
  73. package/dist/service/kafka/fireflinkKafka.service.d.ts +2 -2
  74. package/dist/service/kafka/fireflinkKafka.service.js +17 -3
  75. package/dist/utils/logger/logData.d.ts +1 -0
  76. package/dist/utils/logger/logData.js +49 -22
  77. package/dist/utils/swipe/domSearchHelper.d.ts +5 -0
  78. package/dist/utils/swipe/domSearchHelper.js +42 -0
  79. package/dist/utils/swipe/swipeMovement.d.ts +1 -0
  80. package/dist/utils/swipe/swipeMovement.js +81 -0
  81. package/package.json +3 -4
  82. package/dist/tests/Framework.d.ts +0 -0
  83. package/dist/tests/Framework.js +0 -62
  84. package/dist/tests/test1.d.ts +0 -7
  85. package/dist/tests/test1.js +0 -13
  86. package/dist/tests/test12.js +0 -123
  87. package/dist/tests/test3.js +0 -24
  88. /package/dist/{tests/test12.d.ts → automation/actions/interface/elelementLessActionInterface.js} +0 -0
  89. /package/dist/{tests/test3.d.ts → automation/actions/interface/pinchActionInterface.js} +0 -0
@@ -907,8 +907,14 @@ export function createActionHandlers(context) {
907
907
  MOB_PressBackKey: withExecutor(async (executor) => {
908
908
  await executor.MOB_PressBackKey();
909
909
  }),
910
- WaitTillPresenceOfElement: withExecutor(async (executor, result) => {
911
- await executor.WaitTillPresenceOfElement(result.pageDOM, result.selector, result.fireflinkIndex, result.elementName, result.elementType);
910
+ MOB_PressBackSpaceKey: withExecutor(async (executor) => {
911
+ await executor.MOB_PressBackSpaceKey();
912
+ }),
913
+ MOB_PressSpaceKey: withExecutor(async (executor) => {
914
+ await executor.MOB_PressSpaceKey();
915
+ }),
916
+ WaitTillPresenceOfElement: withExecutor(async (executor, args) => {
917
+ await executor.WaitTillPresenceOfElement(args.pageDOM, args.selector, args.value, args.fireflinkIndex, args.elementName, args.elementType);
912
918
  }),
913
919
  WaitTillPresenceOfAllElements: withExecutor(async (executor, result) => {
914
920
  await executor.WaitTillPresenceOfAllElements(result.pageDOM, result.selector, result.value, result.fireflinkIndex, result.elementName, result.elementType);
@@ -928,6 +934,9 @@ export function createActionHandlers(context) {
928
934
  FindElements: withExecutor(async (executor, result) => {
929
935
  await executor.FindElements(result.pageDOM, result.selector, result.value, result.fireflinkIndex, result.elementName, result.elementType);
930
936
  }),
937
+ MOB_FindElement: withExecutor(async (executor, result) => {
938
+ await executor.MOB_FindElement(result.selector, result.elementName, result.elementType);
939
+ }),
931
940
  WaitTillElementIsClickable: withExecutor(async (executor, result) => {
932
941
  await executor.WaitTillElementIsClickable(result.pageDOM, result.selector, result.fireflinkIndex, result.elementName, result.elementType);
933
942
  }),
@@ -937,6 +946,9 @@ export function createActionHandlers(context) {
937
946
  PressAnyKey: withExecutor(async (executor, result) => {
938
947
  await executor.PressAnyKey(result.value);
939
948
  }),
949
+ MOB_WaitTillPresenceOfElement: withExecutor(async (executor, args) => {
950
+ await executor.WaitTillPresenceOfElement(args.pageDOM, args.selector, args.value, args.fireflinkIndex, args.elementName, args.elementType);
951
+ }),
940
952
  WaitTillElementHasText: withExecutor(async (executor, result) => {
941
953
  await executor.WaitTillElementHasText(result.pageDOM, result.selector, result.fireflinkIndex, result.elementName, result.elementType);
942
954
  }),
@@ -1108,5 +1120,53 @@ export function createActionHandlers(context) {
1108
1120
  MOB_SetEmulatorPowerPercentage: withExecutor(async (executor, result) => {
1109
1121
  await executor.MOB_SetEmulatorPowerPercentage(result.value);
1110
1122
  }),
1123
+ MOB_SwipeToElement: withExecutor(async (executor, result) => {
1124
+ await executor.swipeToElement(result.value, result.elementName, result.elementType, result.num_of_scrolls);
1125
+ }),
1126
+ MOB_SwipeUpToElement: withExecutor(async (executor, result) => {
1127
+ await executor.swipeUpToElement(result.value, result.elementName, result.elementType, result.num_of_scrolls);
1128
+ }),
1129
+ MOB_SwipeDownToElement: withExecutor(async (executor, result) => {
1130
+ await executor.swipeDownToElement(result.value, result.elementName, result.elementType, result.num_of_scrolls);
1131
+ }),
1132
+ MOB_SwipeLeftToElement: withExecutor(async (executor, result) => {
1133
+ await executor.swipeLeftToElement(result.value, result.elementName, result.elementType, result.num_of_scrolls);
1134
+ }),
1135
+ MOB_SwipeRightToElement: withExecutor(async (executor, result) => {
1136
+ await executor.swipeRightToElement(result.value, result.elementName, result.elementType, result.num_of_scrolls);
1137
+ }),
1138
+ MOB_SwipeNTimes: withExecutor(async (executor, result) => {
1139
+ await executor.swipeNTimes(result.num_of_scrolls, result.direction);
1140
+ }),
1141
+ MOB_Builtin_Swipe: withExecutor(async (executor, result) => {
1142
+ await executor.swipeDirectionNTimes(result.num_of_scrolls, result.direction);
1143
+ }),
1144
+ MOB_SwipeDirectionNTimes: withExecutor(async (executor, result) => {
1145
+ await executor.swipeDirectionNTimes(result.num_of_scrolls, result.direction);
1146
+ }),
1147
+ MOB_SwipeToElementForMWeb: withExecutor(async (executor, result) => {
1148
+ await executor.swipeToElementForMWeb(result.value, result.elementName, result.elementType);
1149
+ }),
1150
+ MOB_SwipeUsingReferenceElement: withExecutor(async (executor, result) => {
1151
+ await executor.swipeUsingReferenceElement(result.value, result.elementName, result.elementType, result.num_of_scrolls, result.direction);
1152
+ }),
1153
+ MOB_EnterInputIntoElementFromClipBoard: withExecutor(async (executor, result) => {
1154
+ await executor.MOB_EnterInputIntoElementFromClipBoard(result.selector, result.elementName, result.elementType);
1155
+ }),
1156
+ MOB_CheckIfAppIsClosed: withExecutor(async (executor) => {
1157
+ await executor.MOB_CheckIfAppIsClosed();
1158
+ }),
1159
+ MOB_RunAppInBackground: withExecutor(async (executor, result) => {
1160
+ await executor.MOB_RunAppInBackground(result.value);
1161
+ }),
1162
+ MOB_PinchInByPercent: withExecutor(async (executor, result) => {
1163
+ await executor.MOB_PinchInByPercent(result.selector, result.value, result.elementName, result.elementType);
1164
+ }),
1165
+ MOB_PinchOutByPercent: withExecutor(async (executor, result) => {
1166
+ await executor.MOB_PinchOutByPercent(result.selector, result.value, result.elementName, result.elementType);
1167
+ }),
1168
+ MOB_DoubleTapAtSpecifiedLocation: withExecutor(async (executor, result) => {
1169
+ await executor.MOB_DoubleTapAtSpecifiedLocation(result.value, result.elementName, result.elementType);
1170
+ }),
1111
1171
  };
1112
1172
  }
@@ -2,7 +2,6 @@ import { IAutomationRunner } from "../interfaces/automationRunnerInterface.js";
2
2
  import { AutomationRequest } from "../../core/interfaces/executionDetails.js";
3
3
  export declare class AutomationRunner implements IAutomationRunner {
4
4
  static sessionTerminationDetails: Record<string, boolean>;
5
- private usedElementNames;
6
5
  private KafkaPayload;
7
6
  static getSessionTerminationInfo(testCaseId: string): boolean;
8
7
  static updateSessionTerminationInfo(testCaseId: string): void;
@@ -19,13 +19,12 @@ import { isAlertPresent } from "../../utils/alertPopup/isAlertPresent.js";
19
19
  import { TOAST_WATCHER_JS } from "../../utils/javascript/jsForToaster.js";
20
20
  import { Find_element_by_ff_js_script } from "../../utils/javascript/jsFindElement.js";
21
21
  import { getFFIndexAndXPath } from "../../utils/helpers/xpathcreation.js";
22
- import { logger } from "../../utils/logger/logData.js";
22
+ import { initLogger, logger } from "../../utils/logger/logData.js";
23
23
  import { sameActionHelper } from "../../utils/helpers/sameActionsHelper.js";
24
24
  import { error } from "node:console";
25
25
  import { annotateScreenshot } from "../../imageAnalysisMobile/annotatedScreenshotMobile.js";
26
26
  export class AutomationRunner {
27
27
  constructor() {
28
- this.usedElementNames = [];
29
28
  this.KafkaPayload = {};
30
29
  }
31
30
  static getSessionTerminationInfo(testCaseId) {
@@ -49,7 +48,15 @@ export class AutomationRunner {
49
48
  logger.info("Android session deleted successfully");
50
49
  },
51
50
  web: async () => {
52
- logger.info("Still browser session is active, session id :", driver.sessionId);
51
+ if (request.isCloud) {
52
+ if (driver?.sessionId) {
53
+ await driver.deleteSession();
54
+ }
55
+ logger.info("Cloud session closed");
56
+ }
57
+ if (driver?.sessionId) {
58
+ logger.info("Still browser session is active, session id :", driver.sessionId);
59
+ }
53
60
  }
54
61
  };
55
62
  await (platformHandlers[platform] ?? platformHandlers.web)();
@@ -73,13 +80,14 @@ export class AutomationRunner {
73
80
  }
74
81
  }
75
82
  async run(request) {
76
- this.usedElementNames = [];
83
+ const usedElementNames = [];
84
+ initLogger(request.sessionPath);
77
85
  if (request.isTerminate)
78
86
  return AutomationRunner.updateSessionTerminationInfo(request.testCaseId);
79
87
  AutomationRunner.sessionTerminationDetails[request.testCaseId] = request.isTerminate;
80
88
  const apiService = new FireFlinkApiService();
81
- const fireflinkServiceInstance = new fireflinkService(apiService, request.kafkaProducerInstance);
82
- const instanceDetails = await fireflinkServiceInstance.runGetInstancesDetails(request.projectId, request.token, request.serverHost);
89
+ const fireflinkServiceInstance = new fireflinkService(apiService);
90
+ const instanceDetails = await fireflinkServiceInstance.runGetInstancesDetails(request.projectId, request.token, request.serverData);
83
91
  const aiInfo = getAiInstanceInfo(instanceDetails.responseObject);
84
92
  const context = new ExecutionContext(request);
85
93
  const configProvider = new ServiceProviderBaseUrlProvider();
@@ -102,6 +110,16 @@ export class AutomationRunner {
102
110
  }
103
111
  const start_time = new Date().getTime();
104
112
  for (const step of listOfSteps) {
113
+ let stepResult;
114
+ let stepResultVision;
115
+ let stepAction;
116
+ let fireflinkIndex;
117
+ let selector;
118
+ let xpath;
119
+ let frameAction;
120
+ let iframeDomHtml = null;
121
+ let doc;
122
+ let beforeHandles = null;
105
123
  try {
106
124
  if (AutomationRunner.getSessionTerminationInfo(request.testCaseId)) {
107
125
  logger.info(`Execution terminated successfully. Script: ${request.scriptName}, Test Case ID: ${request.testCaseId}`);
@@ -123,13 +141,13 @@ export class AutomationRunner {
123
141
  const baseName = elementName;
124
142
  let newName = baseName;
125
143
  let count = 0;
126
- while (this.usedElementNames.includes(newName)) {
144
+ while (usedElementNames.includes(newName)) {
127
145
  count++;
128
146
  newName = `${baseName}_${count}`;
129
147
  }
130
148
  elementName = newName;
131
149
  result.response.elementName = elementName;
132
- this.usedElementNames.push(elementName);
150
+ usedElementNames.push(elementName);
133
151
  }
134
152
  if (!allKeywordAction.includes(action)) {
135
153
  throw new Error(`Unsupported action at action or keyword exracter: ${action}`);
@@ -141,16 +159,6 @@ export class AutomationRunner {
141
159
  stepCount++;
142
160
  continue;
143
161
  }
144
- let stepResult;
145
- let stepResultVision;
146
- let stepAction;
147
- let fireflinkIndex;
148
- let selector;
149
- let xpath;
150
- let frameAction = null;
151
- let iframeDomHtml = null;
152
- let doc = null;
153
- let beforeHandles = null;
154
162
  if (platform == "web") {
155
163
  driver = await context.session.getCurrentDriver();
156
164
  }
@@ -545,26 +553,28 @@ export class AutomationRunner {
545
553
  licenseType: request.licenseType,
546
554
  licenseId: request.licenseId,
547
555
  userId: request.userId,
548
- topic: request.topic,
549
556
  projectType: request.projectType,
550
557
  tokensConsumed: (await stepProcessor.getResultTokenUsage()).totalTokens,
551
- errorInfo: errorInfo
558
+ ...(errorInfo && Object.keys(errorInfo).length > 0 && { errorInfo })
552
559
  };
553
560
  try {
554
561
  await context.scriptAppender.waitForAllSteps();
555
- this.KafkaPayload.topic = request.topic;
562
+ // logger.info(context.scriptAppender.getData(), payload)
563
+ this.KafkaPayload.topic = `Topic-FIREFLINK-api-requests-${request.serverHost}`;
556
564
  this.KafkaPayload.message = {
557
565
  ...payload,
558
566
  scriptGenerationData: context.scriptAppender.getData(),
559
567
  serverHost: request.serverHost
560
568
  };
569
+ logger.info(this.KafkaPayload);
561
570
  await fireflinkServiceInstance.produceMessageToKafka(this.KafkaPayload);
562
571
  }
563
572
  catch (error) {
564
- throw new Error("Failed to send payload to FireFlink API:", { cause: error });
573
+ throw new Error("Failed to produce message :", { cause: error });
565
574
  }
566
575
  finally {
567
- await this.cleanup(context, domInfo, extractedRelevantDom, stepProcessor, fireflinkServiceInstance, request, platform, driver);
576
+ await this.cleanup(context, domInfo, extractedRelevantDom, stepProcessor, fireflinkServiceInstance, request, platform, (await context.session.getCurrentDriver().catch(() => null)) ??
577
+ (await context.androidSession.getCurrentDriver().catch(() => null)));
568
578
  }
569
579
  }
570
580
  }
@@ -1,10 +1,8 @@
1
1
  import { IFireflinkService, IFireFlinkApiService, IKafkaPayload } from "../core/interfaces/fireflinkScriptPayloadInterface.js";
2
- import { Producer } from "kafkajs";
3
2
  export declare class fireflinkService implements IFireflinkService {
4
3
  private apiService;
5
- private kafkaProducerInstance;
6
4
  private kafkaProducer;
7
- constructor(apiService: IFireFlinkApiService, kafkaProducerInstance: Producer);
8
- runGetInstancesDetails(projectId: string, token: string, serverHost: string): Promise<any>;
5
+ constructor(apiService: IFireFlinkApiService);
6
+ runGetInstancesDetails(projectId: string, token: string, serverData: string): Promise<any>;
9
7
  produceMessageToKafka(kafkaArgs: IKafkaPayload): Promise<void>;
10
8
  }
@@ -1,12 +1,11 @@
1
1
  import { KafkaProducerService } from "./kafka/fireflinkKafka.service.js";
2
2
  import { logger } from "../utils/logger/logData.js";
3
3
  export class fireflinkService {
4
- constructor(apiService, kafkaProducerInstance) {
4
+ constructor(apiService) {
5
5
  this.apiService = apiService;
6
- this.kafkaProducerInstance = kafkaProducerInstance;
7
- this.kafkaProducer = new KafkaProducerService(this.kafkaProducerInstance);
6
+ this.kafkaProducer = new KafkaProducerService();
8
7
  }
9
- async runGetInstancesDetails(projectId, token, serverHost) {
8
+ async runGetInstancesDetails(projectId, token, serverData) {
10
9
  const headers = {
11
10
  Accept: "*/*",
12
11
  "Accept-Language": "en-US,en;q=0.9",
@@ -14,7 +13,7 @@ export class fireflinkService {
14
13
  projectId: projectId || "",
15
14
  Authorization: `Bearer ${token}`,
16
15
  };
17
- const url = `${serverHost}/project/optimize/v3/ai-service-provider/selected-instance?projectId=${projectId}`;
16
+ const url = `${serverData}/project/optimize/v3/ai-service-provider/selected-instance?projectId=${projectId}`;
18
17
  try {
19
18
  const finalResult = await this.apiService.getInstancesDetailsApi(headers, url);
20
19
  if (finalResult) {
@@ -1,7 +1,7 @@
1
- import { Producer } from "kafkajs";
2
1
  import { IKafkaPayload } from "../../core/interfaces/fireflinkScriptPayloadInterface.js";
3
2
  export declare class KafkaProducerService {
3
+ private kafka;
4
4
  private kafkaProducer;
5
- constructor(kafkaProducer: Producer | any);
5
+ constructor();
6
6
  produceMessage(kafkaArgs: IKafkaPayload): Promise<void>;
7
7
  }
@@ -1,7 +1,21 @@
1
+ import { Kafka } from "kafkajs";
1
2
  import { logger } from "../../utils/logger/logData.js";
3
+ import fs from "fs";
4
+ import dotenv from "dotenv";
5
+ dotenv.config();
2
6
  export class KafkaProducerService {
3
- constructor(kafkaProducer) {
4
- this.kafkaProducer = kafkaProducer;
7
+ constructor() {
8
+ this.kafka = new Kafka({
9
+ clientId: process.env.KAFKA_CLIENT_ID,
10
+ brokers: process.env.KAFKA_BROKERS.split(","),
11
+ ssl: {
12
+ ca: [fs.readFileSync(process.env.KAFKA_SSL_CA, "utf-8")],
13
+ key: fs.readFileSync(process.env.KAFKA_SSL_KEY, "utf-8"),
14
+ cert: fs.readFileSync(process.env.KAFKA_SSL_CERT, "utf-8"),
15
+ rejectUnauthorized: true,
16
+ },
17
+ });
18
+ this.kafkaProducer = this.kafka.producer();
5
19
  }
6
20
  async produceMessage(kafkaArgs) {
7
21
  try {
@@ -12,7 +26,7 @@ export class KafkaProducerService {
12
26
  messages: [{ value: JSON.stringify(kafkaArgs.message) }],
13
27
  });
14
28
  await this.kafkaProducer.disconnect();
15
- logger.info("Kafka produced message successfully and Kafka produced disconnected successfully");
29
+ logger.info("Kafka produced message successfully and Kafka producer disconnected successfully");
16
30
  }
17
31
  catch (error) {
18
32
  await this.kafkaProducer.disconnect();
@@ -1,3 +1,4 @@
1
+ export declare function initLogger(basePath: string): void;
1
2
  export declare const logger: {
2
3
  info: (...args: any[]) => Promise<void>;
3
4
  error: (...args: any[]) => Promise<void>;
@@ -1,37 +1,53 @@
1
1
  import fs from "fs/promises";
2
2
  import path from "path";
3
3
  import beautify from "js-beautify";
4
- const logsDir = path.resolve(process.cwd(), "logs");
5
- const domDir = path.resolve(process.cwd(), "dom");
6
- const screenshotsDir = path.resolve(process.cwd(), "screenshots");
7
- const now = new Date();
8
- const istDate = new Intl.DateTimeFormat("sv-SE", {
9
- timeZone: "Asia/Kolkata",
10
- year: "numeric",
11
- month: "2-digit",
12
- day: "2-digit",
13
- hour: "2-digit",
14
- minute: "2-digit",
15
- second: "2-digit",
16
- fractionalSecondDigits: 3,
17
- hour12: false,
18
- })
19
- .format(now)
20
- .replace(" ", "T");
21
- const logFilePath = path.join(logsDir, "ai-execution-logs.txt");
4
+ let sessionPath;
5
+ let logsDir;
6
+ let domDir;
7
+ let screenshotsDir;
8
+ let logFilePath;
9
+ export function initLogger(basePath) {
10
+ sessionPath = basePath;
11
+ logsDir = path.resolve(sessionPath, "logs");
12
+ domDir = path.resolve(sessionPath, "dom");
13
+ screenshotsDir = path.resolve(sessionPath, "screenshots");
14
+ logFilePath = path.join(logsDir, "ai-execution-logs.txt");
15
+ }
22
16
  async function ensureDirs() {
17
+ if (!logsDir)
18
+ throw new Error("Logger not initialized");
23
19
  await fs.mkdir(logsDir, { recursive: true });
24
20
  await fs.mkdir(domDir, { recursive: true });
25
21
  await fs.mkdir(screenshotsDir, { recursive: true });
26
22
  }
27
- ensureDirs();
23
+ function getISTDate() {
24
+ return new Intl.DateTimeFormat("sv-SE", {
25
+ timeZone: "Asia/Kolkata",
26
+ year: "numeric",
27
+ month: "2-digit",
28
+ day: "2-digit",
29
+ hour: "2-digit",
30
+ minute: "2-digit",
31
+ second: "2-digit",
32
+ fractionalSecondDigits: 3,
33
+ hour12: false,
34
+ })
35
+ .format(new Date())
36
+ .replace(" ", "T");
37
+ }
28
38
  export const logger = {
29
39
  info: async (...args) => {
40
+ if (!logFilePath)
41
+ throw new Error("Logger not initialized");
42
+ await ensureDirs();
30
43
  const formattedArgs = args.map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : arg);
31
- const message = `[INFO] ${istDate}+05:30 - ${formattedArgs.join(" ")}\n`;
44
+ const message = `[INFO] ${getISTDate()}+05:30 - ${formattedArgs.join(" ")}\n`;
32
45
  await fs.appendFile(logFilePath, message, "utf-8");
33
46
  },
34
47
  error: async (...args) => {
48
+ if (!logFilePath)
49
+ throw new Error("Logger not initialized");
50
+ await ensureDirs();
35
51
  const formatted = args.map((arg) => {
36
52
  if (arg instanceof Error) {
37
53
  let output = arg.stack || `${arg.name}: ${arg.message}`;
@@ -71,6 +87,9 @@ export const logger = {
71
87
  return formatted.join(" ");
72
88
  },
73
89
  saveDOM: async (domContent, fileName) => {
90
+ if (!domDir)
91
+ throw new Error("Logger not initialized");
92
+ await ensureDirs();
74
93
  const timestamp = new Date().toLocaleString().replace(/[:.]/g, "-");
75
94
  let finalFileName;
76
95
  let formattedContent;
@@ -90,17 +109,25 @@ export const logger = {
90
109
  await fs.writeFile(filePath, formattedContent, "utf-8");
91
110
  },
92
111
  saveJSON: async (data, fileName) => {
112
+ if (!domDir)
113
+ throw new Error("Logger not initialized");
114
+ await ensureDirs();
93
115
  const timestamp = new Date().toLocaleString().replace(/[:.]/g, "-");
94
- const finalFileName = fileName ? `${fileName}.json` : `data-${timestamp}.json`;
116
+ const finalFileName = fileName
117
+ ? `${fileName}.json`
118
+ : `data-${timestamp}.json`;
95
119
  const filePath = path.join(domDir, finalFileName);
96
120
  const safeData = JSON.stringify(data, (key, value) => {
97
121
  if (key === "element")
98
- return undefined; // remove DOM node
122
+ return undefined;
99
123
  return value;
100
124
  }, 2);
101
125
  await fs.writeFile(filePath, safeData, "utf-8");
102
126
  },
103
127
  saveImage: async (imageBuffer, fileName) => {
128
+ if (!screenshotsDir)
129
+ throw new Error("Logger not initialized");
130
+ await ensureDirs();
104
131
  const filePath = path.join(screenshotsDir, fileName);
105
132
  await fs.writeFile(filePath, imageBuffer);
106
133
  },
@@ -0,0 +1,5 @@
1
+ export declare function findElementInDom(driver: WebdriverIO.Browser, text: string): Promise<{
2
+ element: import("webdriverio").ChainablePromiseElement;
3
+ xpath: string;
4
+ annotatedDom: string;
5
+ } | null>;
@@ -0,0 +1,42 @@
1
+ import { getAnnotatedDOMForMobile } from "../DomExtraction/jsForAttributeInjection.js";
2
+ import { DomSimplifier } from "../../domAnalysis/simplifyAndFlatten.js";
3
+ import { getFFIndexAndXPath } from "../helpers/xpathcreation.js";
4
+ export async function findElementInDom(driver, text) {
5
+ const simplifier = new DomSimplifier();
6
+ const keywords = text
7
+ .toLowerCase()
8
+ .split(/\s+/)
9
+ .filter(Boolean);
10
+ const { dom: annotatedDom } = await getAnnotatedDOMForMobile(driver);
11
+ const { flatNodes } = simplifier.simplifyMobile(annotatedDom);
12
+ const sequenceMatch = (value, words) => {
13
+ const v = value.toLowerCase();
14
+ const pattern = new RegExp("\\b" + words.join("\\s*") + "\\b", "i");
15
+ return pattern.test(v);
16
+ };
17
+ for (const nodeObj of flatNodes) {
18
+ const node = nodeObj.node;
19
+ const textVal = (node["text"] || "").toLowerCase();
20
+ const descVal = (node["content-desc"] || "").toLowerCase();
21
+ const ridVal = (node["resource-id"] || "").toLowerCase();
22
+ if (sequenceMatch(textVal, keywords) ||
23
+ sequenceMatch(descVal, keywords) ||
24
+ sequenceMatch(ridVal, keywords)) {
25
+ const ffIndex = node["FF-inspecter"];
26
+ if (!ffIndex)
27
+ continue;
28
+ const xpath = getFFIndexAndXPath(annotatedDom, ffIndex);
29
+ if (!xpath)
30
+ continue;
31
+ const element = await driver.$(xpath.xpathPath);
32
+ if (await element.isExisting()) {
33
+ return {
34
+ element,
35
+ xpath: xpath.xpathPath,
36
+ annotatedDom
37
+ };
38
+ }
39
+ }
40
+ }
41
+ return null;
42
+ }
@@ -0,0 +1 @@
1
+ export declare function executeSwipeMovement(driver: WebdriverIO.Browser, direction: string): Promise<void>;
@@ -0,0 +1,81 @@
1
+ export async function executeSwipeMovement(driver, direction) {
2
+ if (direction === 'left' || direction === 'right') {
3
+ const horizontalContainers = [
4
+ '//android.widget.HorizontalScrollView',
5
+ '//androidx.recyclerview.widget.RecyclerView'
6
+ ];
7
+ let hsv = null;
8
+ for (const selector of horizontalContainers) {
9
+ const el = await driver.$(selector);
10
+ if (await el.isExisting()) {
11
+ hsv = el;
12
+ break;
13
+ }
14
+ }
15
+ if (hsv && typeof hsv.getRect === "function") {
16
+ const rect = await hsv.getRect();
17
+ const y = rect.y + Math.floor(rect.height / 2);
18
+ let startX, endX;
19
+ if (direction === 'left') {
20
+ startX = rect.x + Math.floor(rect.width * 0.8);
21
+ endX = rect.x + Math.floor(rect.width * 0.2);
22
+ }
23
+ else {
24
+ startX = rect.x + Math.floor(rect.width * 0.2);
25
+ endX = rect.x + Math.floor(rect.width * 0.8);
26
+ }
27
+ await performW3CSwipe(driver, startX, y, endX, y);
28
+ return;
29
+ }
30
+ }
31
+ const size = await driver.getWindowSize();
32
+ const midX = size.width / 2;
33
+ let startX, startY, endX, endY;
34
+ if (direction === 'up') {
35
+ startX = midX;
36
+ startY = size.height * 0.6;
37
+ endX = midX;
38
+ endY = size.height * 0.1;
39
+ }
40
+ else if (direction === 'down') {
41
+ startX = midX;
42
+ startY = size.height * 0.4;
43
+ endX = midX;
44
+ endY = size.height * 0.8;
45
+ }
46
+ else if (direction === 'left') {
47
+ startX = size.width * 0.8;
48
+ startY = size.height * 0.5;
49
+ endX = size.width * 0.2;
50
+ endY = size.height * 0.5;
51
+ }
52
+ else if (direction === 'right') {
53
+ startX = size.width * 0.2;
54
+ startY = size.height * 0.5;
55
+ endX = size.width * 0.8;
56
+ endY = size.height * 0.5;
57
+ }
58
+ else {
59
+ startX = midX;
60
+ startY = size.height * 0.8;
61
+ endX = midX;
62
+ endY = size.height * 0.2;
63
+ }
64
+ await performW3CSwipe(driver, startX, startY, endX, endY);
65
+ }
66
+ async function performW3CSwipe(driver, startX, startY, endX, endY) {
67
+ await driver.performActions([
68
+ {
69
+ type: 'pointer',
70
+ id: 'finger1',
71
+ parameters: { pointerType: 'touch' },
72
+ actions: [
73
+ { type: 'pointerMove', duration: 0, x: Math.floor(startX), y: Math.floor(startY) },
74
+ { type: 'pointerDown', button: 0 },
75
+ { type: 'pointerMove', duration: 800, x: Math.floor(endX), y: Math.floor(endY) },
76
+ { type: 'pointerUp', button: 0 }
77
+ ]
78
+ }
79
+ ]);
80
+ await driver.pause(1000);
81
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ff-automationv2",
3
- "version": "2.2.13",
3
+ "version": "2.2.15",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "This lib is used to automate the manual testcase",
@@ -23,7 +23,6 @@
23
23
  "prepare": "husky",
24
24
  "lint": "eslint src --max-warnings=0",
25
25
  "test": "npm run build && node dist/tests/test12.js",
26
- "test1": "npm run build && node dist/tests/test.js",
27
26
  "llm": "npm run build && node dist/tests/testllm.js",
28
27
  "dev": "npm run build && node dist/index.js",
29
28
  "start": "node dist/index.js",
@@ -50,8 +49,8 @@
50
49
  "nodemon": "3.1.11",
51
50
  "ts-node": "10.9.2",
52
51
  "typescript": "^5.9.3",
53
- "typescript-eslint": "8.56.0",
54
- "webdriverio": "9.26.1"
52
+ "webdriverio": "9.26.1",
53
+ "typescript-eslint": "8.56.0"
55
54
  },
56
55
  "dependencies": {
57
56
  "@xmldom/xmldom": "^0.8.11",
File without changes