ff-automationv2 2.1.3-beta.4 → 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 +2 -2
- package/src/automation/actions/executor.ts +113 -69
- package/src/automation/actions/interaction/click.ts +1 -1
- package/src/automation/actions/interaction/enterInput.ts +2 -3
- package/src/core/interfaces/automationRunnerInterface.ts +2 -1
- package/src/core/main/actionHandlerFactory.ts +124 -111
- package/src/core/main/runAutomationScript.ts +31 -33
- package/src/utils/logger/logData.ts +46 -10
package/RELEASE_GUIDE.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ff-automationv2",
|
|
3
|
-
"version": "2.1.3-beta.
|
|
3
|
+
"version": "2.1.3-beta.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "This lib is used to automate the manual testcase",
|
|
@@ -48,6 +48,6 @@
|
|
|
48
48
|
"jsdom": "27.4.0",
|
|
49
49
|
"openai": "6.18.0",
|
|
50
50
|
"uuid": "13.0.0",
|
|
51
|
-
"webdriverio": "
|
|
51
|
+
"webdriverio": "8.46.0"
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -19,97 +19,141 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
async navigate(url: string): Promise<void> {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
try {
|
|
23
|
+
await navigate({
|
|
24
|
+
driver: this.browser,
|
|
25
|
+
url,
|
|
26
|
+
scriptDataAppender: this.scriptDataAppender
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
async goBack(): Promise<void> {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
try {
|
|
36
|
+
await goBack({
|
|
37
|
+
driver: this.browser,
|
|
38
|
+
scriptDataAppender: this.scriptDataAppender
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
34
44
|
}
|
|
35
45
|
|
|
36
46
|
async refresh(): Promise<void> {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
try {
|
|
48
|
+
await pageRefresh({
|
|
49
|
+
driver: this.browser,
|
|
50
|
+
scriptDataAppender: this.scriptDataAppender
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
41
56
|
}
|
|
42
57
|
|
|
43
58
|
|
|
44
59
|
async wait(time: string): Promise<void> {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
60
|
+
try {
|
|
61
|
+
await wait({
|
|
62
|
+
driver: this.browser,
|
|
63
|
+
time,
|
|
64
|
+
scriptDataAppender: this.scriptDataAppender
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
50
70
|
}
|
|
51
71
|
async click(pageDOM: string, selector: string, fireflinkIndex: string, elementName: string, elementType: string): Promise<void> {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
try {
|
|
73
|
+
await click({
|
|
74
|
+
driver: this.browser,
|
|
75
|
+
selector,
|
|
76
|
+
scriptDataAppender: this.scriptDataAppender,
|
|
77
|
+
elementGetter: this.elementGetter,
|
|
78
|
+
fireflinkIndex,
|
|
79
|
+
pageDOM,
|
|
80
|
+
elementName,
|
|
81
|
+
elementType,
|
|
82
|
+
platform: this.platform
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
63
88
|
}
|
|
64
89
|
async enterInput(selector: string, value: string, fireflinkIndex: string, pageDOM: string, elementName: string, elementType: string): Promise<void> {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
90
|
+
try {
|
|
91
|
+
await enterInput({
|
|
92
|
+
driver: this.browser,
|
|
93
|
+
selector: selector,
|
|
94
|
+
value,
|
|
95
|
+
scriptDataAppender: this.scriptDataAppender,
|
|
96
|
+
elementGetter: this.elementGetter,
|
|
97
|
+
fireflinkIndex,
|
|
98
|
+
pageDOM,
|
|
99
|
+
elementName,
|
|
100
|
+
elementType,
|
|
101
|
+
platform: this.platform
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
77
107
|
}
|
|
78
108
|
async maximize(): Promise<void> {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
109
|
+
try {
|
|
110
|
+
await maximize({
|
|
111
|
+
driver: this.browser,
|
|
112
|
+
scriptDataAppender: this.scriptDataAppender
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
83
118
|
}
|
|
84
119
|
|
|
85
120
|
async clear(pageDOM: string, selector: string, fireflinkIndex: string, elementName: string, elementType: string): Promise<void> {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
121
|
+
try {
|
|
122
|
+
await clear({
|
|
123
|
+
driver: this.browser,
|
|
124
|
+
selector: selector,
|
|
125
|
+
scriptDataAppender: this.scriptDataAppender,
|
|
126
|
+
elementGetter: this.elementGetter,
|
|
127
|
+
fireflinkIndex,
|
|
128
|
+
pageDOM,
|
|
129
|
+
elementName,
|
|
130
|
+
elementType,
|
|
131
|
+
platform: this.platform
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
97
137
|
}
|
|
98
138
|
|
|
99
139
|
async clearAndEnter(pageDOM: string, selector: string, value: string, fireflinkIndex: string, elementName: string, elementType: string): Promise<void> {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
140
|
+
try {
|
|
141
|
+
await clearAndEnter({
|
|
142
|
+
driver: this.browser,
|
|
143
|
+
selector: selector,
|
|
144
|
+
value,
|
|
145
|
+
scriptDataAppender: this.scriptDataAppender,
|
|
146
|
+
elementGetter: this.elementGetter,
|
|
147
|
+
fireflinkIndex,
|
|
148
|
+
pageDOM,
|
|
149
|
+
elementName,
|
|
150
|
+
elementType,
|
|
151
|
+
platform: this.platform
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
112
157
|
}
|
|
113
158
|
|
|
114
|
-
|
|
115
159
|
}
|
|
@@ -29,8 +29,7 @@ export async function enterInput(args: EnterInputInterface): Promise<void> {
|
|
|
29
29
|
|
|
30
30
|
}
|
|
31
31
|
catch (error: any) {
|
|
32
|
-
|
|
33
|
-
throw new Error("enter action failed", { cause: error });
|
|
32
|
+
throw new Error(`enter action failed:`, { cause: error });
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
}
|
|
35
|
+
}
|
|
@@ -1,122 +1,135 @@
|
|
|
1
1
|
import { ExecutionContext } from "../main/executionContext.js";
|
|
2
2
|
import { ActionExecutor } from "../../automation/actions/executor.js";
|
|
3
3
|
|
|
4
|
+
type ActionHandler = (result?: any) => Promise<void>;
|
|
5
|
+
|
|
4
6
|
export function createActionHandlers(
|
|
5
7
|
context: ExecutionContext,
|
|
6
8
|
pageLoad: number,
|
|
7
9
|
implicit: number
|
|
8
|
-
): Record<string,
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
|
|
12
|
-
open: async () => {
|
|
13
|
-
await context.session.open({
|
|
14
|
-
browserName: "chrome",
|
|
15
|
-
pageLoad,
|
|
16
|
-
implicit
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
context.executor = new ActionExecutor(
|
|
20
|
-
await context.session.getCurrentBrowser(),
|
|
21
|
-
context.scriptAppender,
|
|
22
|
-
context.locator,
|
|
23
|
-
context.request.platform
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
context.scriptAppender.add({
|
|
27
|
-
nlpName: "OpenBrowser",
|
|
28
|
-
elementsData: [],
|
|
29
|
-
stepInputs: []
|
|
30
|
-
});
|
|
31
|
-
},
|
|
32
|
-
close: async (result: any) => {
|
|
33
|
-
await context.session.close();
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
navigate: async (result: any) => {
|
|
37
|
-
if (!context.executor) {
|
|
38
|
-
throw new Error("Browser not initialized.");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
await context.executor.navigate(result.response.keywords[0]);
|
|
42
|
-
},
|
|
43
|
-
maximize: async () => {
|
|
44
|
-
if (!context.executor) {
|
|
45
|
-
throw new Error("Browser not initialized.");
|
|
46
|
-
}
|
|
47
|
-
await context.executor.maximize();
|
|
48
|
-
},
|
|
49
|
-
goBack: async () => {
|
|
50
|
-
if (!context.executor) {
|
|
51
|
-
throw new Error("Browser not initialized.");
|
|
52
|
-
}
|
|
53
|
-
await context.executor.goBack();
|
|
54
|
-
},
|
|
55
|
-
refresh: async () => {
|
|
56
|
-
if (!context.executor) {
|
|
57
|
-
throw new Error("Browser not initialized.");
|
|
58
|
-
}
|
|
59
|
-
await context.executor.refresh();
|
|
60
|
-
},
|
|
61
|
-
wait: async (result: any) => {
|
|
62
|
-
if (!context.executor) {
|
|
63
|
-
throw new Error("Browser not initialized.");
|
|
64
|
-
}
|
|
65
|
-
await context.executor.wait(result.value);
|
|
66
|
-
},
|
|
67
|
-
click: async (result: any) => {
|
|
68
|
-
if (!context.executor) {
|
|
69
|
-
throw new Error("Browser not initialized.");
|
|
70
|
-
}
|
|
71
|
-
await context.executor.click(
|
|
72
|
-
result.pageDOM,
|
|
73
|
-
result.selector,
|
|
74
|
-
result.fireflinkIndex,
|
|
75
|
-
result.elementName,
|
|
76
|
-
result.elementType
|
|
77
|
-
);
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
enter: async (result: any) => {
|
|
81
|
-
if (!context.executor) {
|
|
82
|
-
throw new Error("Browser not initialized.");
|
|
83
|
-
}
|
|
84
|
-
await context.executor.enterInput(
|
|
85
|
-
result.selector,
|
|
86
|
-
result.value,
|
|
87
|
-
result.fireflinkIndex,
|
|
88
|
-
result.pageDOM,
|
|
89
|
-
result.elementName,
|
|
90
|
-
result.elementType
|
|
91
|
-
);
|
|
92
|
-
},
|
|
93
|
-
clear: async (result: any) => {
|
|
94
|
-
if (!context.executor) {
|
|
95
|
-
throw new Error("Browser not initialized.");
|
|
96
|
-
}
|
|
97
|
-
await context.executor.clear(
|
|
98
|
-
result.pageDOM,
|
|
99
|
-
result.selector,
|
|
100
|
-
result.fireflinkIndex,
|
|
101
|
-
result.elementName,
|
|
102
|
-
result.elementType
|
|
103
|
-
);
|
|
104
|
-
},
|
|
105
|
-
clearThenEnterInput: async (result: any) => {
|
|
106
|
-
if (!context.executor) {
|
|
107
|
-
throw new Error("Browser not initialized.");
|
|
108
|
-
}
|
|
109
|
-
await context.executor.clearAndEnter(
|
|
110
|
-
result.pageDOM,
|
|
111
|
-
result.selector,
|
|
112
|
-
result.value,
|
|
113
|
-
result.fireflinkIndex,
|
|
114
|
-
result.elementName,
|
|
115
|
-
result.elementType
|
|
116
|
-
);
|
|
117
|
-
},
|
|
10
|
+
): Record<string, ActionHandler> {
|
|
118
11
|
|
|
12
|
+
const requireExecutor = (): ActionExecutor => {
|
|
13
|
+
if (!context.executor) {
|
|
14
|
+
throw new Error("Browser not initialized.");
|
|
15
|
+
}
|
|
16
|
+
return context.executor;
|
|
119
17
|
};
|
|
120
18
|
|
|
19
|
+
const withExecutor =
|
|
20
|
+
(fn: (executor: ActionExecutor, result?: any) => Promise<void>): ActionHandler =>
|
|
21
|
+
async (result?: any) => {
|
|
22
|
+
try {
|
|
23
|
+
const executor = requireExecutor();
|
|
24
|
+
await fn(executor, result);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
throw error
|
|
28
|
+
}
|
|
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
|
+
},
|
|
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
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw error
|
|
133
|
+
}
|
|
121
134
|
|
|
122
|
-
}
|
|
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
|
-
logger.error(`Error executing step "${step}":`, error.message);
|
|
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
245
|
await scriptRunner.runScriptFromPayload(
|
|
250
246
|
context.scriptAppender.getData(),
|
|
251
247
|
payload,
|
|
252
|
-
|
|
253
|
-
|
|
248
|
+
request.token,
|
|
249
|
+
request.serverHost
|
|
254
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
|
}
|
|
@@ -4,6 +4,19 @@ import beautify from "js-beautify";
|
|
|
4
4
|
|
|
5
5
|
const logsDir = path.resolve(process.cwd(), "logs");
|
|
6
6
|
const domDir = path.resolve(process.cwd(), "dom");
|
|
7
|
+
const now = new Date();
|
|
8
|
+
|
|
9
|
+
const istDate = new Intl.DateTimeFormat("sv-SE", {
|
|
10
|
+
timeZone: "Asia/Kolkata",
|
|
11
|
+
year: "numeric",
|
|
12
|
+
month: "2-digit",
|
|
13
|
+
day: "2-digit",
|
|
14
|
+
hour: "2-digit",
|
|
15
|
+
minute: "2-digit",
|
|
16
|
+
second: "2-digit",
|
|
17
|
+
fractionalSecondDigits: 3,
|
|
18
|
+
hour12: false,
|
|
19
|
+
}).format(now).replace(" ", "T");
|
|
7
20
|
|
|
8
21
|
if (!fs.existsSync(logsDir)) {
|
|
9
22
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
@@ -23,26 +36,49 @@ export const logger = {
|
|
|
23
36
|
: arg
|
|
24
37
|
);
|
|
25
38
|
|
|
26
|
-
const message = `[INFO] ${
|
|
39
|
+
const message = `[INFO] ${istDate}+05:30 - ${formattedArgs.join(" ")}\n`;
|
|
27
40
|
|
|
28
41
|
fs.appendFileSync(logFilePath, message, "utf-8");
|
|
29
42
|
},
|
|
30
|
-
|
|
31
43
|
error: (...args: any[]) => {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
+
});
|
|
37
72
|
|
|
38
|
-
const message =
|
|
73
|
+
const message =
|
|
74
|
+
`[ERROR] ${new Date().toISOString()} - ${formatted.join(" ")}\n`;
|
|
39
75
|
|
|
40
76
|
fs.appendFileSync(logFilePath, message, "utf-8");
|
|
41
77
|
},
|
|
42
78
|
|
|
43
79
|
saveDOM: (domContent: string, fileName?: string) => {
|
|
44
80
|
|
|
45
|
-
const timestamp = new Date().
|
|
81
|
+
const timestamp = new Date().toLocaleString().replace(/[:.]/g, "-");
|
|
46
82
|
const finalFileName = fileName
|
|
47
83
|
? `${fileName}.html`
|
|
48
84
|
: `dom-${timestamp}.html`;
|
|
@@ -59,7 +95,7 @@ export const logger = {
|
|
|
59
95
|
},
|
|
60
96
|
|
|
61
97
|
saveJSON: (data: unknown, fileName?: string) => {
|
|
62
|
-
const timestamp = new Date().
|
|
98
|
+
const timestamp = new Date().toLocaleString().replace(/[:.]/g, "-");
|
|
63
99
|
|
|
64
100
|
const finalFileName = fileName
|
|
65
101
|
? `${fileName}.json`
|