ff-automationv2 2.1.1 → 2.1.3-beta.0
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/package.json +1 -1
- package/src/automation/actions/executor.ts +6 -6
- package/src/automation/actions/interaction/click.ts +1 -1
- package/src/automation/actions/interaction/enterInput.ts +1 -1
- package/src/automation/actions/interface/interactionActionInterface.ts +2 -2
- package/src/automation/actions/interface/navigationActionInterface.ts +4 -4
- package/src/automation/actions/interface/waitActionInterface.ts +1 -1
- package/src/automation/actions/navigation/getTitle.ts +1 -1
- package/src/automation/actions/navigation/goBack.ts +1 -1
- package/src/automation/actions/navigation/navigate.ts +1 -1
- package/src/automation/actions/navigation/refresh.ts +1 -1
- package/src/automation/actions/wait/wait.ts +1 -1
- package/src/automation/browserSession/initiateBrowserSession.ts +5 -5
- package/src/core/main/runAutomationScript.ts +66 -3
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
17
17
|
|
|
18
18
|
async navigate(url: string): Promise<void> {
|
|
19
19
|
await navigate({
|
|
20
|
-
|
|
20
|
+
driver: this.browser,
|
|
21
21
|
url,
|
|
22
22
|
scriptDataAppender: this.scriptDataAppender
|
|
23
23
|
});
|
|
@@ -25,14 +25,14 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
25
25
|
|
|
26
26
|
async goBack(): Promise<void> {
|
|
27
27
|
await goBack({
|
|
28
|
-
|
|
28
|
+
driver: this.browser,
|
|
29
29
|
scriptDataAppender: this.scriptDataAppender
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
async refresh(): Promise<void> {
|
|
34
34
|
await pageRefresh({
|
|
35
|
-
|
|
35
|
+
driver: this.browser,
|
|
36
36
|
scriptDataAppender: this.scriptDataAppender
|
|
37
37
|
});
|
|
38
38
|
}
|
|
@@ -40,14 +40,14 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
40
40
|
|
|
41
41
|
async wait(time: string): Promise<void> {
|
|
42
42
|
await wait({
|
|
43
|
-
|
|
43
|
+
driver: this.browser,
|
|
44
44
|
time,
|
|
45
45
|
scriptDataAppender: this.scriptDataAppender
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
async click(pageDOM: string, selector: string, fireflinkIndex: string, elementName: string, elementType: string): Promise<void> {
|
|
49
49
|
await click({
|
|
50
|
-
|
|
50
|
+
driver: this.browser,
|
|
51
51
|
selector,
|
|
52
52
|
scriptDataAppender: this.scriptDataAppender,
|
|
53
53
|
elementGetter: this.elementGetter,
|
|
@@ -60,7 +60,7 @@ export class ActionExecutor implements IActionExecutor {
|
|
|
60
60
|
}
|
|
61
61
|
async enterInput(selector: string, value: string, fireflinkIndex: string, pageDOM: string, elementName: string, elementType: string): Promise<void> {
|
|
62
62
|
await enterInput({
|
|
63
|
-
|
|
63
|
+
driver: this.browser,
|
|
64
64
|
selector: selector,
|
|
65
65
|
value,
|
|
66
66
|
scriptDataAppender: this.scriptDataAppender,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ClickInterface } from "../interface/interactionActionInterface.js";
|
|
2
2
|
export async function click(args: ClickInterface): Promise<void> {
|
|
3
3
|
try {
|
|
4
|
-
const element = await args.
|
|
4
|
+
const element = await args.driver.$(args.selector);
|
|
5
5
|
await element.scrollIntoView({ block: 'center', inline: 'center' });
|
|
6
6
|
await element.click();
|
|
7
7
|
const ffElement: any = await args.elementGetter.getFireFlinkElement(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EnterInputInterface } from "../interface/interactionActionInterface.js";
|
|
2
2
|
export async function enterInput(args: EnterInputInterface): Promise<void> {
|
|
3
3
|
try {
|
|
4
|
-
const element = args.
|
|
4
|
+
const element = args.driver.$(args.selector);
|
|
5
5
|
await element.scrollIntoView({ block: 'center', inline: 'center' });
|
|
6
6
|
await element.setValue(args.value);
|
|
7
7
|
const ffElement: any = await args.elementGetter.getFireFlinkElement(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ScriptDataAppender } from "../../../fireflinkData/fireflinkScript/scriptGenrationData.js";
|
|
2
2
|
import { ElementGetter } from "../../../fireflinkData/fireflinkLocators/getListOfLocators.js";
|
|
3
3
|
export interface ClickInterface {
|
|
4
|
-
|
|
4
|
+
driver: WebdriverIO.Browser;
|
|
5
5
|
selector: string;
|
|
6
6
|
scriptDataAppender: ScriptDataAppender;
|
|
7
7
|
elementGetter: ElementGetter;
|
|
@@ -14,7 +14,7 @@ export interface ClickInterface {
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
export interface EnterInputInterface {
|
|
17
|
-
|
|
17
|
+
driver: WebdriverIO.Browser;
|
|
18
18
|
selector: string;
|
|
19
19
|
value: string;
|
|
20
20
|
scriptDataAppender: ScriptDataAppender;
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { ScriptDataAppender } from "../../../fireflinkData/fireflinkScript/scriptGenrationData.js";
|
|
2
2
|
|
|
3
3
|
export interface getTitleInterface {
|
|
4
|
-
|
|
4
|
+
driver: WebdriverIO.Browser;
|
|
5
5
|
scriptDataAppender: ScriptDataAppender;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export interface goBackInterface {
|
|
9
|
-
|
|
9
|
+
driver: WebdriverIO.Browser;
|
|
10
10
|
scriptDataAppender: ScriptDataAppender;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface navigateToUrlInterface {
|
|
14
|
-
|
|
14
|
+
driver: WebdriverIO.Browser;
|
|
15
15
|
scriptDataAppender: ScriptDataAppender;
|
|
16
16
|
url: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface refreshInterface {
|
|
20
|
-
|
|
20
|
+
driver: WebdriverIO.Browser;
|
|
21
21
|
scriptDataAppender: ScriptDataAppender;
|
|
22
22
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getTitleInterface } from "../interface/navigationActionInterface.js";
|
|
2
2
|
export async function getTitle(args: getTitleInterface): Promise<void> {
|
|
3
3
|
try {
|
|
4
|
-
const title = await args.
|
|
4
|
+
const title = await args.driver.getTitle();
|
|
5
5
|
args.scriptDataAppender.add({ nlpName: 'getTitle', elementsData: [], stepInputs: [title] });
|
|
6
6
|
} catch (error: any) {
|
|
7
7
|
throw new Error("Get title action failed", { cause: error });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { goBackInterface } from "../interface/navigationActionInterface.js";
|
|
2
2
|
export async function goBack(args: goBackInterface): Promise<void> {
|
|
3
3
|
try {
|
|
4
|
-
await args.
|
|
4
|
+
await args.driver.back();
|
|
5
5
|
args.scriptDataAppender.add({ nlpName: 'goBack', elementsData: [], stepInputs: [] });
|
|
6
6
|
} catch (error: any) {
|
|
7
7
|
throw new Error("Navigate action failed", { cause: error });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { navigateToUrlInterface } from "../interface/navigationActionInterface.js";
|
|
2
2
|
export async function navigate(args: navigateToUrlInterface): Promise<void> {
|
|
3
3
|
try {
|
|
4
|
-
await args.
|
|
4
|
+
await args.driver.url(args.url);
|
|
5
5
|
args.scriptDataAppender.add({ nlpName: 'NavigateToURL', elementsData: [], stepInputs: [args.url] });
|
|
6
6
|
|
|
7
7
|
} catch (error: any) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { refreshInterface } from "../interface/navigationActionInterface.js";
|
|
2
2
|
export async function pageRefresh(args: refreshInterface): Promise<void> {
|
|
3
3
|
try {
|
|
4
|
-
await args.
|
|
4
|
+
await args.driver.refresh();
|
|
5
5
|
args.scriptDataAppender.add({ nlpName: 'refresh', elementsData: [], stepInputs: [] });
|
|
6
6
|
} catch (error: any) {
|
|
7
7
|
throw new Error("Refresh action failed", { cause: error });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { waitInterface } from "../interface/waitActionInterface.js";
|
|
2
2
|
export async function wait(args: waitInterface): Promise<void> {
|
|
3
3
|
try {
|
|
4
|
-
await args.
|
|
4
|
+
await args.driver.pause(Number(args.time) * 1000);
|
|
5
5
|
args.scriptDataAppender.add({ nlpName: 'Sleep', elementsData: [], stepInputs: [args.time] });
|
|
6
6
|
|
|
7
7
|
} catch (error: any) {
|
|
@@ -6,7 +6,7 @@ export class BrowserSession {
|
|
|
6
6
|
|
|
7
7
|
private async openBrowser(capabilities: browserCapabilities): Promise<WebdriverIO.Browser> {
|
|
8
8
|
try {
|
|
9
|
-
const
|
|
9
|
+
const driver = await remote(
|
|
10
10
|
{
|
|
11
11
|
capabilities: {
|
|
12
12
|
browserName: capabilities.browserName,
|
|
@@ -14,13 +14,13 @@ export class BrowserSession {
|
|
|
14
14
|
logLevel: "silent"
|
|
15
15
|
}
|
|
16
16
|
);
|
|
17
|
-
|
|
18
|
-
await
|
|
19
|
-
const state = await
|
|
17
|
+
driver.setTimeout({ 'pageLoad': capabilities.pageLoad, 'implicit': capabilities.implicit });
|
|
18
|
+
await driver.waitUntil(async () => {
|
|
19
|
+
const state = await driver.execute(() => document.readyState);
|
|
20
20
|
return state === "complete";
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
return
|
|
23
|
+
return driver;
|
|
24
24
|
} catch (error: any) {
|
|
25
25
|
throw new Error("Browser failed to open", { cause: error });
|
|
26
26
|
}
|
|
@@ -14,12 +14,64 @@ import { DomProcessingEngine } from "../../domAnalysis/getRelaventElements.js"
|
|
|
14
14
|
import { getAnnotatedDOM } from "../../utils/DomExtraction/jsForAttributeInjection.js"
|
|
15
15
|
import { logger } from "../../utils/logger/logData.js"
|
|
16
16
|
export class AutomationRunner implements IAutomationRunner {
|
|
17
|
+
static sessionTerminationDetails: Record<string, boolean> = {};
|
|
17
18
|
constructor(
|
|
18
19
|
private readonly request: AutomationRequest,
|
|
19
20
|
private pageLoad: number = 20000,
|
|
20
21
|
private implicit: number = 15000,
|
|
21
22
|
private tokensConsumed: number = 0
|
|
22
|
-
|
|
23
|
+
|
|
24
|
+
) { AutomationRunner.sessionTerminationDetails[request.testCaseId] = false }
|
|
25
|
+
|
|
26
|
+
static getSessionTerminationInfo(testCaseId: string): boolean {
|
|
27
|
+
return AutomationRunner.sessionTerminationDetails[testCaseId]
|
|
28
|
+
}
|
|
29
|
+
static updateSessionTerminationInfo(testCaseId: string): void {
|
|
30
|
+
AutomationRunner.sessionTerminationDetails[testCaseId] = true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private async cleanup(
|
|
34
|
+
context: ExecutionContext,
|
|
35
|
+
domInfo: any,
|
|
36
|
+
extractedRelevantDom: any,
|
|
37
|
+
stepProcessor: StepProcessor,
|
|
38
|
+
scriptRunner: ScriptRunner
|
|
39
|
+
) {
|
|
40
|
+
try {
|
|
41
|
+
logger.info("Starting cleanup process...");
|
|
42
|
+
if (context?.session) {
|
|
43
|
+
try {
|
|
44
|
+
const browser = await context.session.getCurrentBrowser();
|
|
45
|
+
if (browser) {
|
|
46
|
+
await browser.deleteSession?.();
|
|
47
|
+
}
|
|
48
|
+
} catch (e) {
|
|
49
|
+
logger.error("Browser cleanup failed:", e);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
domInfo = null;
|
|
54
|
+
extractedRelevantDom = null;
|
|
55
|
+
|
|
56
|
+
if (stepProcessor) {
|
|
57
|
+
(stepProcessor as any).llm = null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
scriptRunner = null as any;
|
|
61
|
+
|
|
62
|
+
delete AutomationRunner.sessionTerminationDetails[this.request.testCaseId];
|
|
63
|
+
|
|
64
|
+
if (global.gc) {
|
|
65
|
+
global.gc();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
logger.info("Cleanup completed successfully.");
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
logger.error("Cleanup error:", error);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
23
75
|
|
|
24
76
|
async run(): Promise<void> {
|
|
25
77
|
const apiService = new FireFlinkApiService();
|
|
@@ -47,6 +99,8 @@ export class AutomationRunner implements IAutomationRunner {
|
|
|
47
99
|
}
|
|
48
100
|
for (const step of listOfSteps) {
|
|
49
101
|
try {
|
|
102
|
+
if (AutomationRunner.getSessionTerminationInfo(this.request.testCaseId)) { break; }
|
|
103
|
+
|
|
50
104
|
const start = Math.max(0, stepCount - 3);
|
|
51
105
|
const end = Math.min(listOfSteps.length, stepCount + 3);
|
|
52
106
|
const priorAndNextSteps = listOfSteps.slice(start, end);
|
|
@@ -96,8 +150,8 @@ export class AutomationRunner implements IAutomationRunner {
|
|
|
96
150
|
}
|
|
97
151
|
|
|
98
152
|
|
|
99
|
-
const
|
|
100
|
-
domInfo = await getAnnotatedDOM(
|
|
153
|
+
const driver = await context.session.getCurrentBrowser();
|
|
154
|
+
domInfo = await getAnnotatedDOM(driver);
|
|
101
155
|
await logger.saveDOM(domInfo.dom, `annotated-dom-${stepCount}`);
|
|
102
156
|
|
|
103
157
|
extractedRelevantDom = domProcessor.process({
|
|
@@ -184,5 +238,14 @@ export class AutomationRunner implements IAutomationRunner {
|
|
|
184
238
|
"Failed to send payload to FireFlink API:", { cause: error }
|
|
185
239
|
);
|
|
186
240
|
}
|
|
241
|
+
finally {
|
|
242
|
+
await this.cleanup(
|
|
243
|
+
context,
|
|
244
|
+
domInfo,
|
|
245
|
+
extractedRelevantDom,
|
|
246
|
+
stepProcessor,
|
|
247
|
+
scriptRunner
|
|
248
|
+
);
|
|
249
|
+
}
|
|
187
250
|
}
|
|
188
251
|
}
|