ff-automationv2 2.1.3-beta.5 → 2.1.3-beta.6
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/RELEASE_GUIDE.md +1 -1
- package/package.json +1 -1
- package/src/automation/actions/executor.ts +9 -9
- package/src/automation/actions/interaction/click.ts +1 -1
- package/src/automation/actions/interaction/enterInput.ts +1 -1
- package/src/core/interfaces/automationRunnerInterface.ts +2 -1
- package/src/core/main/actionHandlerFactory.ts +103 -98
- package/src/core/main/runAutomationScript.ts +34 -36
- package/src/utils/logger/logData.ts +30 -7
package/RELEASE_GUIDE.md
CHANGED
package/package.json
CHANGED
|
@@ -27,7 +27,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
catch (error) {
|
|
30
|
-
throw
|
|
30
|
+
throw error;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -39,7 +39,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
catch (error) {
|
|
42
|
-
throw
|
|
42
|
+
throw error;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -51,7 +51,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
catch (error) {
|
|
54
|
-
throw
|
|
54
|
+
throw error;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -65,7 +65,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
catch (error) {
|
|
68
|
-
throw
|
|
68
|
+
throw error;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
async click(pageDOM: string, selector: string, fireflinkIndex: string, elementName: string, elementType: string): Promise<void> {
|
|
@@ -83,7 +83,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
85
|
catch (error) {
|
|
86
|
-
throw
|
|
86
|
+
throw error;
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
async enterInput(selector: string, value: string, fireflinkIndex: string, pageDOM: string, elementName: string, elementType: string): Promise<void> {
|
|
@@ -102,7 +102,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
catch (error) {
|
|
105
|
-
throw
|
|
105
|
+
throw error;
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
async maximize(): Promise<void> {
|
|
@@ -113,7 +113,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
catch (error) {
|
|
116
|
-
throw
|
|
116
|
+
throw error;
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -132,7 +132,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
132
132
|
});
|
|
133
133
|
}
|
|
134
134
|
catch (error) {
|
|
135
|
-
throw
|
|
135
|
+
throw error;
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
@@ -152,7 +152,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
152
152
|
});
|
|
153
153
|
}
|
|
154
154
|
catch (error) {
|
|
155
|
-
throw
|
|
155
|
+
throw error;
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
@@ -24,107 +24,112 @@ export function createActionHandlers(
|
|
|
24
24
|
await fn(executor, result);
|
|
25
25
|
}
|
|
26
26
|
catch (error) {
|
|
27
|
-
throw
|
|
27
|
+
throw error
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
|
+
try {
|
|
31
|
+
return {
|
|
32
|
+
|
|
33
|
+
open: async () => {
|
|
34
|
+
try {
|
|
35
|
+
await context.session.open({
|
|
36
|
+
browserName: "chrome",
|
|
37
|
+
pageLoad,
|
|
38
|
+
implicit
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
context.executor = new ActionExecutor(
|
|
42
|
+
await context.session.getCurrentBrowser(),
|
|
43
|
+
context.scriptAppender,
|
|
44
|
+
context.locator,
|
|
45
|
+
context.request.platform
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
context.scriptAppender.add({
|
|
49
|
+
nlpName: "OpenBrowser",
|
|
50
|
+
elementsData: [],
|
|
51
|
+
stepInputs: []
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
throw new Error(`Error occuried in createActionHandlers , error : ${error}`)
|
|
56
|
+
}
|
|
57
|
+
},
|
|
30
58
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
59
|
+
close: async () => {
|
|
60
|
+
try {
|
|
61
|
+
await context.session.close();
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
throw new Error(`Error occuried in createActionHandlers , error : ${error}`)
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
navigate: withExecutor(async (executor, result) => {
|
|
69
|
+
await executor.navigate(result.response.keywords[0]);
|
|
70
|
+
}),
|
|
71
|
+
|
|
72
|
+
maximize: withExecutor(async (executor) => {
|
|
73
|
+
await executor.maximize();
|
|
74
|
+
}),
|
|
75
|
+
|
|
76
|
+
goBack: withExecutor(async (executor) => {
|
|
77
|
+
await executor.goBack();
|
|
78
|
+
}),
|
|
79
|
+
|
|
80
|
+
refresh: withExecutor(async (executor) => {
|
|
81
|
+
await executor.refresh();
|
|
82
|
+
}),
|
|
83
|
+
|
|
84
|
+
wait: withExecutor(async (executor, result) => {
|
|
85
|
+
await executor.wait(result.value);
|
|
86
|
+
}),
|
|
87
|
+
|
|
88
|
+
click: withExecutor(async (executor, result) => {
|
|
89
|
+
await executor.click(
|
|
90
|
+
result.pageDOM,
|
|
91
|
+
result.selector,
|
|
92
|
+
result.fireflinkIndex,
|
|
93
|
+
result.elementName,
|
|
94
|
+
result.elementType
|
|
46
95
|
);
|
|
96
|
+
}),
|
|
97
|
+
|
|
98
|
+
enter: withExecutor(async (executor, result) => {
|
|
99
|
+
await executor.enterInput(
|
|
100
|
+
result.selector,
|
|
101
|
+
result.value,
|
|
102
|
+
result.fireflinkIndex,
|
|
103
|
+
result.pageDOM,
|
|
104
|
+
result.elementName,
|
|
105
|
+
result.elementType
|
|
106
|
+
);
|
|
107
|
+
}),
|
|
108
|
+
|
|
109
|
+
clear: withExecutor(async (executor, result) => {
|
|
110
|
+
await executor.clear(
|
|
111
|
+
result.pageDOM,
|
|
112
|
+
result.selector,
|
|
113
|
+
result.fireflinkIndex,
|
|
114
|
+
result.elementName,
|
|
115
|
+
result.elementType
|
|
116
|
+
);
|
|
117
|
+
}),
|
|
118
|
+
|
|
119
|
+
clearThenEnterInput: withExecutor(async (executor, result) => {
|
|
120
|
+
await executor.clearAndEnter(
|
|
121
|
+
result.pageDOM,
|
|
122
|
+
result.selector,
|
|
123
|
+
result.value,
|
|
124
|
+
result.fireflinkIndex,
|
|
125
|
+
result.elementName,
|
|
126
|
+
result.elementType
|
|
127
|
+
);
|
|
128
|
+
}),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw error
|
|
133
|
+
}
|
|
47
134
|
|
|
48
|
-
context.scriptAppender.add({
|
|
49
|
-
nlpName: "OpenBrowser",
|
|
50
|
-
elementsData: [],
|
|
51
|
-
stepInputs: []
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
throw new Error(`Error occuried in createActionHandlers , error : ${error}`)
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
close: async () => {
|
|
60
|
-
try {
|
|
61
|
-
await context.session.close();
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
throw new Error(`Error occuried in createActionHandlers , error : ${error}`)
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
navigate: withExecutor(async (executor, result) => {
|
|
69
|
-
await executor.navigate(result.response.keywords[0]);
|
|
70
|
-
}),
|
|
71
|
-
|
|
72
|
-
maximize: withExecutor(async (executor) => {
|
|
73
|
-
await executor.maximize();
|
|
74
|
-
}),
|
|
75
|
-
|
|
76
|
-
goBack: withExecutor(async (executor) => {
|
|
77
|
-
await executor.goBack();
|
|
78
|
-
}),
|
|
79
|
-
|
|
80
|
-
refresh: withExecutor(async (executor) => {
|
|
81
|
-
await executor.refresh();
|
|
82
|
-
}),
|
|
83
|
-
|
|
84
|
-
wait: withExecutor(async (executor, result) => {
|
|
85
|
-
await executor.wait(result.value);
|
|
86
|
-
}),
|
|
87
|
-
|
|
88
|
-
click: withExecutor(async (executor, result) => {
|
|
89
|
-
await executor.click(
|
|
90
|
-
result.pageDOM,
|
|
91
|
-
result.selector,
|
|
92
|
-
result.fireflinkIndex,
|
|
93
|
-
result.elementName,
|
|
94
|
-
result.elementType
|
|
95
|
-
);
|
|
96
|
-
}),
|
|
97
|
-
|
|
98
|
-
enter: withExecutor(async (executor, result) => {
|
|
99
|
-
await executor.enterInput(
|
|
100
|
-
result.selector,
|
|
101
|
-
result.value,
|
|
102
|
-
result.fireflinkIndex,
|
|
103
|
-
result.pageDOM,
|
|
104
|
-
result.elementName,
|
|
105
|
-
result.elementType
|
|
106
|
-
);
|
|
107
|
-
}),
|
|
108
|
-
|
|
109
|
-
clear: withExecutor(async (executor, result) => {
|
|
110
|
-
await executor.clear(
|
|
111
|
-
result.pageDOM,
|
|
112
|
-
result.selector,
|
|
113
|
-
result.fireflinkIndex,
|
|
114
|
-
result.elementName,
|
|
115
|
-
result.elementType
|
|
116
|
-
);
|
|
117
|
-
}),
|
|
118
|
-
|
|
119
|
-
clearThenEnterInput: withExecutor(async (executor, result) => {
|
|
120
|
-
await executor.clearAndEnter(
|
|
121
|
-
result.pageDOM,
|
|
122
|
-
result.selector,
|
|
123
|
-
result.value,
|
|
124
|
-
result.fireflinkIndex,
|
|
125
|
-
result.elementName,
|
|
126
|
-
result.elementType
|
|
127
|
-
);
|
|
128
|
-
}),
|
|
129
|
-
};
|
|
130
135
|
}
|
|
@@ -16,12 +16,10 @@ import { logger } from "../../utils/logger/logData.js"
|
|
|
16
16
|
export class AutomationRunner implements IAutomationRunner {
|
|
17
17
|
static sessionTerminationDetails: Record<string, boolean> = {};
|
|
18
18
|
constructor(
|
|
19
|
-
private readonly request: AutomationRequest,
|
|
20
19
|
private pageLoad: number = 20000,
|
|
21
20
|
private implicit: number = 15000,
|
|
22
|
-
private tokensConsumed: number = 0
|
|
23
21
|
|
|
24
|
-
) {
|
|
22
|
+
) { }
|
|
25
23
|
|
|
26
24
|
static getSessionTerminationInfo(testCaseId: string): boolean {
|
|
27
25
|
return AutomationRunner.sessionTerminationDetails[testCaseId]
|
|
@@ -35,16 +33,14 @@ export class AutomationRunner implements IAutomationRunner {
|
|
|
35
33
|
domInfo: any,
|
|
36
34
|
extractedRelevantDom: any,
|
|
37
35
|
stepProcessor: StepProcessor,
|
|
38
|
-
scriptRunner: ScriptRunner
|
|
36
|
+
scriptRunner: ScriptRunner,
|
|
37
|
+
request: AutomationRequest
|
|
39
38
|
) {
|
|
40
39
|
try {
|
|
41
40
|
logger.info("Starting cleanup process...");
|
|
42
41
|
if (context?.session) {
|
|
43
42
|
try {
|
|
44
43
|
const browser = await context.session.getCurrentBrowser();
|
|
45
|
-
// if (browser) {
|
|
46
|
-
// await browser.deleteSession?.();
|
|
47
|
-
// }
|
|
48
44
|
} catch (e) {
|
|
49
45
|
logger.error("Browser cleanup failed:", e);
|
|
50
46
|
}
|
|
@@ -59,7 +55,7 @@ export class AutomationRunner implements IAutomationRunner {
|
|
|
59
55
|
|
|
60
56
|
scriptRunner = null as any;
|
|
61
57
|
|
|
62
|
-
delete AutomationRunner.sessionTerminationDetails[
|
|
58
|
+
delete AutomationRunner.sessionTerminationDetails[request.testCaseId];
|
|
63
59
|
|
|
64
60
|
if (global.gc) {
|
|
65
61
|
global.gc();
|
|
@@ -73,18 +69,19 @@ export class AutomationRunner implements IAutomationRunner {
|
|
|
73
69
|
}
|
|
74
70
|
|
|
75
71
|
|
|
76
|
-
async run(): Promise<void> {
|
|
72
|
+
async run(request: AutomationRequest): Promise<void> {
|
|
73
|
+
AutomationRunner.sessionTerminationDetails[request.testCaseId] = false;
|
|
77
74
|
const apiService = new FireFlinkApiService();
|
|
78
75
|
const scriptRunner = new ScriptRunner(apiService);
|
|
79
|
-
const context = new ExecutionContext(
|
|
76
|
+
const context = new ExecutionContext(request);
|
|
80
77
|
const configProvider = new ServiceProviderBaseUrlProvider();
|
|
81
|
-
const baseUrl = configProvider.getBaseUrl(
|
|
78
|
+
const baseUrl = configProvider.getBaseUrl(request.serviceProvider);
|
|
82
79
|
let domInfo: any = null;
|
|
83
80
|
let extractedRelevantDom: any = null;
|
|
84
|
-
const llm = new llmAction(
|
|
81
|
+
const llm = new llmAction(request.apiKey, baseUrl, request.model, request.visionApikey);
|
|
85
82
|
const stepProcessor = new StepProcessor(llm);
|
|
86
83
|
|
|
87
|
-
const stepResult = await stepProcessor.getLLMResponse({ type: PromptType.USER_STORY_TO_LIST, args: {}, input: { userStory:
|
|
84
|
+
const stepResult = await stepProcessor.getLLMResponse({ type: PromptType.USER_STORY_TO_LIST, args: {}, input: { userStory: request.userStory } });
|
|
88
85
|
|
|
89
86
|
const actionHandlers = createActionHandlers(
|
|
90
87
|
context,
|
|
@@ -103,7 +100,7 @@ export class AutomationRunner implements IAutomationRunner {
|
|
|
103
100
|
|
|
104
101
|
for (const step of listOfSteps) {
|
|
105
102
|
try {
|
|
106
|
-
if (AutomationRunner.getSessionTerminationInfo(
|
|
103
|
+
if (AutomationRunner.getSessionTerminationInfo(request.testCaseId)) { break; }
|
|
107
104
|
|
|
108
105
|
logger.info
|
|
109
106
|
(
|
|
@@ -167,7 +164,7 @@ export class AutomationRunner implements IAutomationRunner {
|
|
|
167
164
|
await logger.saveJSON(extractedRelevantDom, `relevant-dom-${stepCount}`);
|
|
168
165
|
let stepResult: any;
|
|
169
166
|
if (action == "verify") {
|
|
170
|
-
|
|
167
|
+
stepResult = await stepProcessor.getLLMResponse({
|
|
171
168
|
type: PromptType.VERIFY_PROMPT,
|
|
172
169
|
args: {
|
|
173
170
|
extractedDomJson: JSON.stringify(extractedRelevantDom, null, 2),
|
|
@@ -224,35 +221,35 @@ export class AutomationRunner implements IAutomationRunner {
|
|
|
224
221
|
elementsData: [],
|
|
225
222
|
stepInputs: []
|
|
226
223
|
});
|
|
227
|
-
|
|
228
224
|
logger.error(`Error executing step "${step}":`, error);
|
|
229
225
|
break;
|
|
230
226
|
}
|
|
231
227
|
}
|
|
232
228
|
const payload: IPayload = {
|
|
233
|
-
scriptName:
|
|
234
|
-
scriptType:
|
|
235
|
-
projectId:
|
|
236
|
-
testCaseId:
|
|
237
|
-
promptId:
|
|
238
|
-
pageDetails:
|
|
239
|
-
generatedBy:
|
|
240
|
-
webSocketId:
|
|
241
|
-
licenseType:
|
|
242
|
-
licenseId:
|
|
243
|
-
userId:
|
|
244
|
-
topic:
|
|
245
|
-
projectType:
|
|
229
|
+
scriptName: request.scriptName,
|
|
230
|
+
scriptType: request.scriptType,
|
|
231
|
+
projectId: request.projectId,
|
|
232
|
+
testCaseId: request.testCaseId,
|
|
233
|
+
promptId: request.promptId,
|
|
234
|
+
pageDetails: request.pageDetails,
|
|
235
|
+
generatedBy: request.generatedBy,
|
|
236
|
+
webSocketId: request.webSocketId,
|
|
237
|
+
licenseType: request.licenseType,
|
|
238
|
+
licenseId: request.licenseId,
|
|
239
|
+
userId: request.userId,
|
|
240
|
+
topic: request.topic,
|
|
241
|
+
projectType: request.projectType,
|
|
246
242
|
tokensConsumed: (await stepProcessor.getResultTokenUsage()).totalTokens,
|
|
247
243
|
}
|
|
248
244
|
try {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
245
|
+
await scriptRunner.runScriptFromPayload(
|
|
246
|
+
context.scriptAppender.getData(),
|
|
247
|
+
payload,
|
|
248
|
+
request.token,
|
|
249
|
+
request.serverHost
|
|
250
|
+
);
|
|
255
251
|
} catch (error: any) {
|
|
252
|
+
|
|
256
253
|
throw new Error(
|
|
257
254
|
"Failed to send payload to FireFlink API:", { cause: error }
|
|
258
255
|
);
|
|
@@ -263,7 +260,8 @@ export class AutomationRunner implements IAutomationRunner {
|
|
|
263
260
|
domInfo,
|
|
264
261
|
extractedRelevantDom,
|
|
265
262
|
stepProcessor,
|
|
266
|
-
scriptRunner
|
|
263
|
+
scriptRunner,
|
|
264
|
+
request
|
|
267
265
|
);
|
|
268
266
|
}
|
|
269
267
|
}
|
|
@@ -40,15 +40,38 @@ export const logger = {
|
|
|
40
40
|
|
|
41
41
|
fs.appendFileSync(logFilePath, message, "utf-8");
|
|
42
42
|
},
|
|
43
|
-
|
|
44
43
|
error: (...args: any[]) => {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
const formatted = args.map(arg => {
|
|
45
|
+
if (arg instanceof Error) {
|
|
46
|
+
let output = arg.stack || `${arg.name}: ${arg.message}`;
|
|
47
|
+
output = output.replace(
|
|
48
|
+
/invalid session id:\s*invalid session id:/gi,
|
|
49
|
+
"invalid session id:"
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
if (arg.cause instanceof Error) {
|
|
53
|
+
let causeStack = arg.cause.stack || "";
|
|
54
|
+
|
|
55
|
+
causeStack = causeStack.replace(
|
|
56
|
+
/invalid session id:\s*invalid session id:/gi,
|
|
57
|
+
"invalid session id:"
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
output += `\nCaused by: ${causeStack}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return output;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (typeof arg === "object") {
|
|
67
|
+
return JSON.stringify(arg, null, 2);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return String(arg);
|
|
71
|
+
});
|
|
50
72
|
|
|
51
|
-
const message =
|
|
73
|
+
const message =
|
|
74
|
+
`[ERROR] ${new Date().toISOString()} - ${formatted.join(" ")}\n`;
|
|
52
75
|
|
|
53
76
|
fs.appendFileSync(logFilePath, message, "utf-8");
|
|
54
77
|
},
|