ff-automationv2 2.2.14 → 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.
- package/dist/ai/llmprompts/systemPrompts/combinedActionExtractorPromptMob.js +4 -3
- package/dist/ai/llmprompts/systemPrompts/errorDescriptionPrompt.js +9 -11
- package/dist/ai/llmprompts/systemPrompts/fireflinkElementIndexExtactors.js +7 -7
- package/dist/ai/llmprompts/systemPrompts/fireflinkElementIndexExtractor_Mob.js +39 -0
- package/dist/ai/llmprompts/systemPrompts/mobileKeywordExtractor.js +2 -1
- package/dist/ai/llmprompts/systemPrompts/verifyActionExtractorPromptMob.js +2 -1
- package/dist/ai/llmprompts/systemPrompts/visionPrompt.js +3 -2
- package/dist/ai/llmprompts/systemPrompts/waitActionExtractorPrompt.js +1 -0
- package/dist/ai/llmprompts/systemPrompts/waitActionExtractorPromptMob.js +1 -0
- package/dist/automation/actions/executor.d.ts +19 -1
- package/dist/automation/actions/executor.js +303 -1
- package/dist/automation/actions/interaction/click/MOB_DoubleTapAtSpecifiedLocation.d.ts +2 -0
- package/dist/automation/actions/interaction/click/MOB_DoubleTapAtSpecifiedLocation.js +26 -0
- package/dist/automation/actions/interaction/elementLessAction/MobCheckIfAppIsClosed.d.ts +2 -0
- package/dist/automation/actions/interaction/elementLessAction/MobCheckIfAppIsClosed.js +20 -0
- package/dist/automation/actions/interaction/elementLessAction/MobRunAppInBackgroundInterface.d.ts +2 -0
- package/dist/automation/actions/interaction/elementLessAction/MobRunAppInBackgroundInterface.js +18 -0
- package/dist/automation/actions/interaction/enterActions/EnterInputIntoElementFromClipBoardInterface_mob.d.ts +2 -0
- package/dist/automation/actions/interaction/enterActions/EnterInputIntoElementFromClipBoardInterface_mob.js +26 -0
- package/dist/automation/actions/interaction/enterActions/enterInput.js +2 -2
- package/dist/automation/actions/interaction/enterActions/enterInputAndPress.js +1 -1
- package/dist/automation/actions/interaction/enterActions/enterusingJs.js +1 -1
- package/dist/automation/actions/interaction/enterActions/waitAndEnter.js +3 -3
- package/dist/automation/actions/interaction/find/MOB_FindElement.d.ts +2 -0
- package/dist/automation/actions/interaction/find/MOB_FindElement.js +34 -0
- package/dist/automation/actions/interaction/find/findElements.js +16 -2
- package/dist/automation/actions/interaction/get/getScreenshot.js +14 -16
- package/dist/automation/actions/interaction/get/getScreenshotAs.js +26 -16
- package/dist/automation/actions/interaction/pinch/PinchInByPercentMob.d.ts +2 -0
- package/dist/automation/actions/interaction/pinch/PinchInByPercentMob.js +27 -0
- package/dist/automation/actions/interaction/pinch/PinchOutByPercentMob.d.ts +2 -0
- package/dist/automation/actions/interaction/pinch/PinchOutByPercentMob.js +27 -0
- package/dist/automation/actions/interaction/press/mobPressBackSpaceKey.d.ts +2 -0
- package/dist/automation/actions/interaction/press/mobPressBackSpaceKey.js +16 -0
- package/dist/automation/actions/interaction/press/mobPressSpaceKey.d.ts +2 -0
- package/dist/automation/actions/interaction/press/mobPressSpaceKey.js +16 -0
- package/dist/automation/actions/interaction/swipe/swipeDirectionNTimes.d.ts +2 -0
- package/dist/automation/actions/interaction/swipe/swipeDirectionNTimes.js +27 -0
- package/dist/automation/actions/interaction/swipe/swipeDownToElement.d.ts +2 -0
- package/dist/automation/actions/interaction/swipe/swipeDownToElement.js +46 -0
- package/dist/automation/actions/interaction/swipe/swipeLeftToElement.d.ts +2 -0
- package/dist/automation/actions/interaction/swipe/swipeLeftToElement.js +46 -0
- package/dist/automation/actions/interaction/swipe/swipeRightToElement.d.ts +2 -0
- package/dist/automation/actions/interaction/swipe/swipeRightToElement.js +46 -0
- package/dist/automation/actions/interaction/swipe/swipeUpToElement.d.ts +2 -0
- package/dist/automation/actions/interaction/swipe/swipeUpToElement.js +49 -0
- package/dist/automation/actions/interaction/swipe/swipeUpToElementForMWeb.d.ts +2 -0
- package/dist/automation/actions/interaction/swipe/swipeUpToElementForMWeb.js +48 -0
- package/dist/automation/actions/interaction/swipe/swipeUsingReferenceElement.d.ts +2 -0
- package/dist/automation/actions/interaction/swipe/swipeUsingReferenceElement.js +140 -0
- package/dist/automation/actions/interaction/verify/VerifyElementNotContainsText.js +2 -2
- package/dist/automation/actions/interaction/wait/waitTillElementIsClickable.js +5 -1
- package/dist/automation/actions/interaction/wait/waitTillPresenceOfElement.js +1 -1
- package/dist/automation/actions/interface/clickActionInterface.d.ts +8 -0
- package/dist/automation/actions/interface/elelementLessActionInterface.d.ts +12 -0
- package/dist/automation/actions/interface/findActionInterface.d.ts +10 -2
- package/dist/automation/actions/interface/interactionActionInterface.d.ts +8 -0
- package/dist/automation/actions/interface/pinchActionInterface.d.ts +19 -0
- package/dist/automation/actions/interface/pressActionInterface.d.ts +10 -0
- package/dist/automation/actions/interface/swipeActionInterface.d.ts +89 -0
- package/dist/automation/actions/interface/swipeActionInterface.js +1 -0
- package/dist/automation/actions/interface/waitActionInterface.d.ts +1 -0
- package/dist/core/constants/allAction.js +1 -0
- package/dist/core/constants/supportedActions.js +9 -1
- package/dist/core/interfaces/actionInterface.d.ts +19 -1
- package/dist/core/interfaces/executionDetails.d.ts +1 -4
- package/dist/core/interfaces/fireflinkScriptPayloadInterface.d.ts +2 -3
- package/dist/core/main/actionHandlerFactory.js +62 -2
- package/dist/core/main/runAutomationScript.d.ts +0 -1
- package/dist/core/main/runAutomationScript.js +17 -13
- package/dist/service/fireflink.service.d.ts +2 -4
- package/dist/service/fireflink.service.js +4 -5
- package/dist/service/kafka/fireflinkKafka.service.d.ts +2 -2
- package/dist/service/kafka/fireflinkKafka.service.js +17 -3
- package/dist/utils/logger/logData.d.ts +1 -0
- package/dist/utils/logger/logData.js +49 -22
- package/dist/utils/swipe/domSearchHelper.d.ts +5 -0
- package/dist/utils/swipe/domSearchHelper.js +42 -0
- package/dist/utils/swipe/swipeMovement.d.ts +1 -0
- package/dist/utils/swipe/swipeMovement.js +81 -0
- package/package.json +3 -4
- package/dist/tests/Framework.d.ts +0 -0
- package/dist/tests/Framework.js +0 -62
- package/dist/tests/test1.d.ts +0 -7
- package/dist/tests/test1.js +0 -13
- package/dist/tests/test12.js +0 -123
- package/dist/tests/test3.js +0 -24
- /package/dist/{tests/test12.d.ts → automation/actions/interface/elelementLessActionInterface.js} +0 -0
- /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
|
-
|
|
911
|
-
await executor.
|
|
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) {
|
|
@@ -50,7 +49,9 @@ export class AutomationRunner {
|
|
|
50
49
|
},
|
|
51
50
|
web: async () => {
|
|
52
51
|
if (request.isCloud) {
|
|
53
|
-
|
|
52
|
+
if (driver?.sessionId) {
|
|
53
|
+
await driver.deleteSession();
|
|
54
|
+
}
|
|
54
55
|
logger.info("Cloud session closed");
|
|
55
56
|
}
|
|
56
57
|
if (driver?.sessionId) {
|
|
@@ -79,13 +80,14 @@ export class AutomationRunner {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
async run(request) {
|
|
82
|
-
|
|
83
|
+
const usedElementNames = [];
|
|
84
|
+
initLogger(request.sessionPath);
|
|
83
85
|
if (request.isTerminate)
|
|
84
86
|
return AutomationRunner.updateSessionTerminationInfo(request.testCaseId);
|
|
85
87
|
AutomationRunner.sessionTerminationDetails[request.testCaseId] = request.isTerminate;
|
|
86
88
|
const apiService = new FireFlinkApiService();
|
|
87
|
-
const fireflinkServiceInstance = new fireflinkService(apiService
|
|
88
|
-
const instanceDetails = await fireflinkServiceInstance.runGetInstancesDetails(request.projectId, request.token, request.
|
|
89
|
+
const fireflinkServiceInstance = new fireflinkService(apiService);
|
|
90
|
+
const instanceDetails = await fireflinkServiceInstance.runGetInstancesDetails(request.projectId, request.token, request.serverData);
|
|
89
91
|
const aiInfo = getAiInstanceInfo(instanceDetails.responseObject);
|
|
90
92
|
const context = new ExecutionContext(request);
|
|
91
93
|
const configProvider = new ServiceProviderBaseUrlProvider();
|
|
@@ -139,13 +141,13 @@ export class AutomationRunner {
|
|
|
139
141
|
const baseName = elementName;
|
|
140
142
|
let newName = baseName;
|
|
141
143
|
let count = 0;
|
|
142
|
-
while (
|
|
144
|
+
while (usedElementNames.includes(newName)) {
|
|
143
145
|
count++;
|
|
144
146
|
newName = `${baseName}_${count}`;
|
|
145
147
|
}
|
|
146
148
|
elementName = newName;
|
|
147
149
|
result.response.elementName = elementName;
|
|
148
|
-
|
|
150
|
+
usedElementNames.push(elementName);
|
|
149
151
|
}
|
|
150
152
|
if (!allKeywordAction.includes(action)) {
|
|
151
153
|
throw new Error(`Unsupported action at action or keyword exracter: ${action}`);
|
|
@@ -551,26 +553,28 @@ export class AutomationRunner {
|
|
|
551
553
|
licenseType: request.licenseType,
|
|
552
554
|
licenseId: request.licenseId,
|
|
553
555
|
userId: request.userId,
|
|
554
|
-
topic: request.topic,
|
|
555
556
|
projectType: request.projectType,
|
|
556
557
|
tokensConsumed: (await stepProcessor.getResultTokenUsage()).totalTokens,
|
|
557
|
-
errorInfo
|
|
558
|
+
...(errorInfo && Object.keys(errorInfo).length > 0 && { errorInfo })
|
|
558
559
|
};
|
|
559
560
|
try {
|
|
560
561
|
await context.scriptAppender.waitForAllSteps();
|
|
561
|
-
|
|
562
|
+
// logger.info(context.scriptAppender.getData(), payload)
|
|
563
|
+
this.KafkaPayload.topic = `Topic-FIREFLINK-api-requests-${request.serverHost}`;
|
|
562
564
|
this.KafkaPayload.message = {
|
|
563
565
|
...payload,
|
|
564
566
|
scriptGenerationData: context.scriptAppender.getData(),
|
|
565
567
|
serverHost: request.serverHost
|
|
566
568
|
};
|
|
569
|
+
logger.info(this.KafkaPayload);
|
|
567
570
|
await fireflinkServiceInstance.produceMessageToKafka(this.KafkaPayload);
|
|
568
571
|
}
|
|
569
572
|
catch (error) {
|
|
570
|
-
throw new Error("Failed to
|
|
573
|
+
throw new Error("Failed to produce message :", { cause: error });
|
|
571
574
|
}
|
|
572
575
|
finally {
|
|
573
|
-
await this.cleanup(context, domInfo, extractedRelevantDom, stepProcessor, fireflinkServiceInstance, request, platform, await context.session.getCurrentDriver()
|
|
576
|
+
await this.cleanup(context, domInfo, extractedRelevantDom, stepProcessor, fireflinkServiceInstance, request, platform, (await context.session.getCurrentDriver().catch(() => null)) ??
|
|
577
|
+
(await context.androidSession.getCurrentDriver().catch(() => null)));
|
|
574
578
|
}
|
|
575
579
|
}
|
|
576
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
|
|
8
|
-
runGetInstancesDetails(projectId: string, token: string,
|
|
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
|
|
4
|
+
constructor(apiService) {
|
|
5
5
|
this.apiService = apiService;
|
|
6
|
-
this.
|
|
7
|
-
this.kafkaProducer = new KafkaProducerService(this.kafkaProducerInstance);
|
|
6
|
+
this.kafkaProducer = new KafkaProducerService();
|
|
8
7
|
}
|
|
9
|
-
async runGetInstancesDetails(projectId, token,
|
|
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 = `${
|
|
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(
|
|
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(
|
|
4
|
-
this.
|
|
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
|
|
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,37 +1,53 @@
|
|
|
1
1
|
import fs from "fs/promises";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import beautify from "js-beautify";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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] ${
|
|
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
|
|
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;
|
|
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,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.
|
|
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
|
-
"
|
|
54
|
-
"
|
|
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
|
package/dist/tests/Framework.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// import { AutomationRunner } from "../core/main/runAutomationScript.js";
|
|
3
|
-
// import { RuntimePromptRegistry } from "../framework/promptRegistry.runtime.js";
|
|
4
|
-
// import { RuntimeActionRegistry } from "../framework/actionRegistry.runtime.js";
|
|
5
|
-
// import { createDefaultPromptRegistry, registerDefaultPrompts } from "../framework/registerDefaultPrompts.js";
|
|
6
|
-
// import { createDefaultActionRegistry, registerDefaultActions } from "../framework/registerDefaultActions.js";
|
|
7
|
-
// // export { AutomationRunner };
|
|
8
|
-
// // export { RuntimePromptRegistry };
|
|
9
|
-
// // export { RuntimeActionRegistry };
|
|
10
|
-
// // export { createDefaultPromptRegistry, registerDefaultPrompts };
|
|
11
|
-
// // export { createDefaultActionRegistry, registerDefaultActions };
|
|
12
|
-
// // import { AutomationRunner, RuntimeActionRegistry } from "ff-automationv2";
|
|
13
|
-
// const actionRegistry = new RuntimeActionRegistry();
|
|
14
|
-
// // actionRegistry.register("minimize", {
|
|
15
|
-
// // handler: async (context) => {
|
|
16
|
-
// // const browser = await context.session.getCurrentBrowser();
|
|
17
|
-
// // await browser.minimizeWindow();
|
|
18
|
-
// // context.scriptAppender.add({
|
|
19
|
-
// // nlpName: "Minimize",
|
|
20
|
-
// // elementsData: [],
|
|
21
|
-
// // stepInputs: []
|
|
22
|
-
// // });
|
|
23
|
-
// // },
|
|
24
|
-
// // requiresExecutor: true,
|
|
25
|
-
// // requiresElement: false,
|
|
26
|
-
// // requiresInput: false
|
|
27
|
-
// // });
|
|
28
|
-
// const runner = new AutomationRunner(20000, 15000, { actionRegistry });
|
|
29
|
-
// runner.run({
|
|
30
|
-
// userStory: "(open the browser ),( navigate to https://www.google.com/) ,(wait for 2 sec),(minimize the browser) ",
|
|
31
|
-
// platform: "android",
|
|
32
|
-
// pageDetails: {
|
|
33
|
-
// Web: {
|
|
34
|
-
// pageId: "PAG73a7a0ad-c092-4351-8a93-68647f60e343",
|
|
35
|
-
// pageName: "ai-Page"
|
|
36
|
-
// }
|
|
37
|
-
// },
|
|
38
|
-
// service_accounts: "",
|
|
39
|
-
// serverHost: "https://test3.fireflink.com",
|
|
40
|
-
// webSocketId: "",
|
|
41
|
-
// generatedBy: "",
|
|
42
|
-
// licenseType: "C-Professional",
|
|
43
|
-
// licenseId: "LIC3985",
|
|
44
|
-
// userId: "USR26935",
|
|
45
|
-
// topic: "Topic-FIREFLINK-aiAutomation-Updates-test3",
|
|
46
|
-
// projectType: "Web",
|
|
47
|
-
// browser: {
|
|
48
|
-
// browserName: "chrome",
|
|
49
|
-
// },
|
|
50
|
-
// serverData: {},
|
|
51
|
-
// scriptName: "url",
|
|
52
|
-
// scriptType: "android",
|
|
53
|
-
// projectId: "PJT1116",
|
|
54
|
-
// testCaseId: "SCR1208",
|
|
55
|
-
// promptId: "3f6e123c-8ec6-47c1-90e1-1a2f53b49251",
|
|
56
|
-
// userName: "default-user",
|
|
57
|
-
// visionApikey: "Z3NrX2VubE44UVI5bmNzMlg0TXVsNDJHV0dkeWIzRllEYmJRV0lremZYaTRkME5VTzBjODZ4eHY=",
|
|
58
|
-
// apiKey: "Z3NrX2VubE44UVI5bmNzMlg0TXVsNDJHV0dkeWIzRllEYmJRV0lremZYaTRkME5VTzBjODZ4eHY=",
|
|
59
|
-
// model: "llama-3.3-70b-versatile",
|
|
60
|
-
// serviceProvider: "Groq",
|
|
61
|
-
// token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJEeE5VelJXSGhLTUVkSTVKQnV6eERFM3NsczVHRkV5cmJNeHVHNWtmNnRZIn0.eyJleHAiOjE3NzUyMjI3OTAsImlhdCI6MTc3MjYzMDc5MCwianRpIjoib25ydHJvOmY2ZDcwNzg1LTk4ODQtNDgzNS04ZjE2LWNiNzk5NjhiNWQzYSIsImlzcyI6Imh0dHA6Ly8xMDMuMTgyLjIxMC4yMjY6MzAxMDcvcmVhbG1zL0ZpcmVGbGluay10ZXN0MyIsImF1ZCI6InRhcmdldC1jbGllbnQiLCJzdWIiOiJmOmNhMzBmNDk3LTY1Y2YtNGU4Zi1iZGE3LTE0ZjM1NTNiYzZmNTpqYWlha2FzaEB5b3BtYWlsLmNvbSIsInR5cCI6IkJlYXJlciIsImF6cCI6ImZsaW5rLXNlcnZpY2UiLCJzaWQiOiJhMzg0MTVkMS1hYWZkLTQ4MTYtOWNhYS01MGVmMGMxZWI0ODciLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIioiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsImN1cnJlbnRMaWNlbnNlSWQiOiJMSUMzOTg1IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJjdXJyZW50UHJpdmlsZWdlIjoiU3VwZXIgQWRtaW4iLCJmdWxsTmFtZSI6ImphaSIsImFjdGl2YXRpb25TdGF0dXMiOiJBQ1RJVkUiLCJwcml2aWxlZ2UiOiJTdXBlciBBZG1pbiIsImxpY2Vuc2VOYW1lIjoiRmlyZUZsaW5rIC0gTElDMzk4NSIsInByZWZlcnJlZF91c2VybmFtZSI6ImphaSIsInVzZXJOYW1lIjoiamFpYWthc2hAeW9wbWFpbC5jb20iLCJiaWxsaW5nQ3ljbGUiOiJRdWFydGVybHkiLCJpZCI6IlVTUjI2OTM1IiwibGljZW5zZUlkIjoiTElDMzk4NSIsImVtYWlsIjoiamFpYWthc2hAeW9wbWFpbC5jb20ifQ.NCu_Oo86ld4tHCjWqTC2YxeBOifhWqwqmh1K7Cz6v4XEhDQuUrdULzKCOBWbYXA86BqT8oqWLOg2lA88G-LRnayCiBEutlbTbPIYsbghyuJCeagA_E9VJnM0fcccJqRi16dKG1em3cuZ2nJTQ8s_Bq1211ovPGI-Jyy2IBTc-fTDI0C4o9x8O0jpT_mz8COzCDwbCAon2e1EKxYjnyU360ZMwmwcnJjWqB5vsr384fKdrq3zx_zLESvW81x2bRGxzGYoO2hS38PWSrZbiOANNXzjVU9nDSU4kx280oBZo251rVRE58jJ4kKDSxLqmshT0TP-PERMqhNps9U2envExg",
|
|
62
|
-
// })
|
package/dist/tests/test1.d.ts
DELETED
package/dist/tests/test1.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
let sessionList = [
|
|
3
|
-
{ testCase: "A", env: "local", isTerminate: false },
|
|
4
|
-
{ testCase: "B", env: "cloud", isTerminate: false },
|
|
5
|
-
{ testCase: "B", env: "cloud", isTerminate: true },
|
|
6
|
-
{ testCase: "C", env: "local", isTerminate: false }
|
|
7
|
-
];
|
|
8
|
-
sessionList = sessionList.filter(item => !(item.testCase === "B" && item.env === "cloud" && item.isTerminate === true));
|
|
9
|
-
const founds1 = sessionList.some(item => item.testCase === "A" &&
|
|
10
|
-
item.env === "local" &&
|
|
11
|
-
item.isTerminate === false);
|
|
12
|
-
// console.log(founds); // undefined
|
|
13
|
-
console.log(sessionList);
|