ff-automationv2 1.0.0 → 2.0.1-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.
Files changed (60) hide show
  1. package/bitbucket-pipelines.yml +20 -0
  2. package/eslint.config.ts +29 -29
  3. package/package.json +51 -51
  4. package/src/ai/llmcalls/decodeApiKey.ts +14 -14
  5. package/src/ai/llmcalls/llmAction.ts +89 -89
  6. package/src/ai/llmcalls/parseLlmOputput.ts +69 -69
  7. package/src/ai/llmprompts/systemPrompts/actionExtractorPrompt.ts +70 -70
  8. package/src/ai/llmprompts/systemPrompts/errorDescriptionPrompt.ts +23 -23
  9. package/src/ai/llmprompts/systemPrompts/fireflinkElementIndexExtactors.ts +198 -198
  10. package/src/ai/llmprompts/systemPrompts/userStoryToListPrompt.ts +24 -24
  11. package/src/ai/llmprompts/systemPrompts/visionPrompt.ts +28 -28
  12. package/src/automation/actions/executor.ts +74 -74
  13. package/src/automation/actions/interaction/enterInput.ts +27 -27
  14. package/src/automation/actions/interface/interactionActionInterface.ts +26 -26
  15. package/src/automation/actions/interface/navigationActionInterface.ts +21 -21
  16. package/src/automation/actions/interface/waitActionInterface.ts +5 -5
  17. package/src/automation/actions/navigation/getTitle.ts +8 -8
  18. package/src/automation/actions/navigation/goBack.ts +8 -8
  19. package/src/automation/actions/navigation/navigate.ts +9 -9
  20. package/src/automation/actions/navigation/refresh.ts +8 -8
  21. package/src/automation/actions/wait/wait.ts +9 -9
  22. package/src/automation/browserSession/initiateBrowserSession.ts +81 -81
  23. package/src/core/constants/supportedActions.ts +7 -7
  24. package/src/core/interfaces/StableDomInterface.ts +5 -5
  25. package/src/core/interfaces/actionInterface.ts +13 -13
  26. package/src/core/interfaces/automationRunnerInterface.ts +2 -2
  27. package/src/core/interfaces/browserCapabilitiesInterface.ts +4 -4
  28. package/src/core/interfaces/browserConfigurationInterface.ts +2 -2
  29. package/src/core/interfaces/domAnalysisInterface.ts +34 -34
  30. package/src/core/interfaces/executionDetails.ts +29 -29
  31. package/src/core/interfaces/fireflinkScriptPayloadInterface.ts +39 -39
  32. package/src/core/interfaces/llmConfigurationInterface.ts +2 -2
  33. package/src/core/interfaces/llmResponseInterface.ts +38 -38
  34. package/src/core/interfaces/promptInterface.ts +21 -21
  35. package/src/core/interfaces/scriptGenrationDataInterface.ts +16 -16
  36. package/src/core/interfaces/toolsInterface.ts +5 -5
  37. package/src/core/main/actionHandlerFactory.ts +86 -86
  38. package/src/core/main/executionContext.ts +18 -18
  39. package/src/core/main/runAutomationScript.ts +177 -177
  40. package/src/core/main/stepProcessor.ts +28 -28
  41. package/src/core/types/llmResponseType.ts +10 -10
  42. package/src/core/types/visionllmInputType.ts +4 -4
  43. package/src/domAnalysis/getRelaventElements.ts +24 -24
  44. package/src/domAnalysis/relativeElementsFromDom.ts +94 -94
  45. package/src/domAnalysis/searchBest.ts +159 -159
  46. package/src/domAnalysis/simplifyAndFlatten.ts +118 -118
  47. package/src/fireflinkData/fireflinkLocators/elementsFromHTML.ts +656 -656
  48. package/src/fireflinkData/fireflinkLocators/getListOfLocators.ts +31 -31
  49. package/src/fireflinkData/fireflinkLocators/typeList.ts +36 -36
  50. package/src/fireflinkData/fireflinkScript/scriptGenrationData.ts +30 -30
  51. package/src/index.ts +5 -5
  52. package/src/llmConfig/llmConfiguration.ts +26 -26
  53. package/src/service/fireflinkApi.service.ts +46 -46
  54. package/src/service/scriptRunner.service.ts +83 -83
  55. package/src/utils/DomExtraction/jsForAttributeInjection.ts +254 -254
  56. package/src/utils/javascript/jsFindElement.ts +161 -161
  57. package/src/utils/javascript/jsForShadowRoot.ts +216 -216
  58. package/src/utils/javascript/jsForToaster.ts +60 -60
  59. package/src/utils/logger/logData.ts +36 -36
  60. package/tsconfig.json +26 -26
@@ -1,28 +1,28 @@
1
-
2
- type visionPrompt = {
3
- currentStep: string,
4
- priorAndNextSteps: string[]
5
- }
6
- export async function visionPrompt(
7
- { currentStep, priorAndNextSteps }: visionPrompt
8
- ): Promise<string> {
9
-
10
- const customPromptText = `
11
- You are a precise automation assistant.
12
- Context: ${priorAndNextSteps}
13
- - Use the context to understand the step and select the closest semantic match to ${currentStep} and return only its index, else Fire-Flink-0.
14
- - **If u can't find the element, return Fire-Flink-0. dont return any other elements index.**
15
- - Using the provided annotated screenshot and ${currentStep}, identify the correct element index from the image.
16
- - Match the index to the text or action described in ${currentStep} as accurately as possible.
17
- - Return only the Fire-Flink-xx for the target element.
18
- - Do not provide any additional text or explanation. The output must be strictly Fire-Flink-xx.
19
- Now, Analyze the step:
20
- Step: "${currentStep}"
21
-
22
- Respond only with JSON using this format:
23
- {fireflinkIndex: Fire-Flink-xx.}
24
-
25
- `.trim();
26
-
27
- return customPromptText;
28
- }
1
+
2
+ type visionPrompt = {
3
+ currentStep: string,
4
+ priorAndNextSteps: string[]
5
+ }
6
+ export async function visionPrompt(
7
+ { currentStep, priorAndNextSteps }: visionPrompt
8
+ ): Promise<string> {
9
+
10
+ const customPromptText = `
11
+ You are a precise automation assistant.
12
+ Context: ${priorAndNextSteps}
13
+ - Use the context to understand the step and select the closest semantic match to ${currentStep} and return only its index, else Fire-Flink-0.
14
+ - **If u can't find the element, return Fire-Flink-0. dont return any other elements index.**
15
+ - Using the provided annotated screenshot and ${currentStep}, identify the correct element index from the image.
16
+ - Match the index to the text or action described in ${currentStep} as accurately as possible.
17
+ - Return only the Fire-Flink-xx for the target element.
18
+ - Do not provide any additional text or explanation. The output must be strictly Fire-Flink-xx.
19
+ Now, Analyze the step:
20
+ Step: "${currentStep}"
21
+
22
+ Respond only with JSON using this format:
23
+ {fireflinkIndex: Fire-Flink-xx.}
24
+
25
+ `.trim();
26
+
27
+ return customPromptText;
28
+ }
@@ -1,75 +1,75 @@
1
- import type { IActionExecutor } from "../../core/interfaces/actionInterface.js";
2
- import { navigate } from './navigation/navigate.js';
3
- import { goBack } from './navigation/goBack.js';
4
- import { pageRefresh } from './navigation/refresh.js';
5
- import { click } from './interaction/click.js';
6
- import { wait } from "./wait/wait.js"
7
- import { enterInput } from "./interaction/enterInput.js";
8
- import { ScriptDataAppender } from "../../fireflinkData/fireflinkScript/scriptGenrationData.js";
9
- import { ElementGetter } from "../../fireflinkData/fireflinkLocators/getListOfLocators.js";
10
- export class ActionExecutor implements IActionExecutor {
11
- constructor(private readonly browser: WebdriverIO.Browser,
12
- private scriptDataAppender: ScriptDataAppender,
13
- private elementGetter: ElementGetter,
14
- private platform: string) { }
15
-
16
-
17
-
18
- async navigate(url: string): Promise<void> {
19
- await navigate({
20
- browser: this.browser,
21
- url,
22
- scriptDataAppender: this.scriptDataAppender
23
- });
24
- }
25
-
26
- async goBack(): Promise<void> {
27
- await goBack({
28
- browser: this.browser,
29
- scriptDataAppender: this.scriptDataAppender
30
- });
31
- }
32
-
33
- async refresh(): Promise<void> {
34
- await pageRefresh({
35
- browser: this.browser,
36
- scriptDataAppender: this.scriptDataAppender
37
- });
38
- }
39
-
40
-
41
- async wait(time: string): Promise<void> {
42
- await wait({
43
- browser: this.browser,
44
- time,
45
- scriptDataAppender: this.scriptDataAppender
46
- });
47
- }
48
- async click(pageDOM: string, selector: string, fireflinkIndex: string, elementName: string, elementType: string): Promise<void> {
49
- await click({
50
- browser: this.browser,
51
- selector,
52
- scriptDataAppender: this.scriptDataAppender,
53
- elementGetter: this.elementGetter,
54
- fireflinkIndex,
55
- pageDOM,
56
- elementName,
57
- elementType,
58
- platform: this.platform
59
- });
60
- }
61
- async enterInput(selector: string, value: string, fireflinkIndex: string, pageDOM: string, elementName: string, elementType: string): Promise<void> {
62
- await enterInput({
63
- browser: this.browser,
64
- selector: selector,
65
- value,
66
- scriptDataAppender: this.scriptDataAppender,
67
- elementGetter: this.elementGetter,
68
- fireflinkIndex,
69
- pageDOM,
70
- elementName,
71
- elementType,
72
- platform: this.platform
73
- });
74
- }
1
+ import type { IActionExecutor } from "../../core/interfaces/actionInterface.js";
2
+ import { navigate } from './navigation/navigate.js';
3
+ import { goBack } from './navigation/goBack.js';
4
+ import { pageRefresh } from './navigation/refresh.js';
5
+ import { click } from './interaction/click.js';
6
+ import { wait } from "./wait/wait.js"
7
+ import { enterInput } from "./interaction/enterInput.js";
8
+ import { ScriptDataAppender } from "../../fireflinkData/fireflinkScript/scriptGenrationData.js";
9
+ import { ElementGetter } from "../../fireflinkData/fireflinkLocators/getListOfLocators.js";
10
+ export class ActionExecutor implements IActionExecutor {
11
+ constructor(private readonly browser: WebdriverIO.Browser,
12
+ private scriptDataAppender: ScriptDataAppender,
13
+ private elementGetter: ElementGetter,
14
+ private platform: string) { }
15
+
16
+
17
+
18
+ async navigate(url: string): Promise<void> {
19
+ await navigate({
20
+ browser: this.browser,
21
+ url,
22
+ scriptDataAppender: this.scriptDataAppender
23
+ });
24
+ }
25
+
26
+ async goBack(): Promise<void> {
27
+ await goBack({
28
+ browser: this.browser,
29
+ scriptDataAppender: this.scriptDataAppender
30
+ });
31
+ }
32
+
33
+ async refresh(): Promise<void> {
34
+ await pageRefresh({
35
+ browser: this.browser,
36
+ scriptDataAppender: this.scriptDataAppender
37
+ });
38
+ }
39
+
40
+
41
+ async wait(time: string): Promise<void> {
42
+ await wait({
43
+ browser: this.browser,
44
+ time,
45
+ scriptDataAppender: this.scriptDataAppender
46
+ });
47
+ }
48
+ async click(pageDOM: string, selector: string, fireflinkIndex: string, elementName: string, elementType: string): Promise<void> {
49
+ await click({
50
+ browser: this.browser,
51
+ selector,
52
+ scriptDataAppender: this.scriptDataAppender,
53
+ elementGetter: this.elementGetter,
54
+ fireflinkIndex,
55
+ pageDOM,
56
+ elementName,
57
+ elementType,
58
+ platform: this.platform
59
+ });
60
+ }
61
+ async enterInput(selector: string, value: string, fireflinkIndex: string, pageDOM: string, elementName: string, elementType: string): Promise<void> {
62
+ await enterInput({
63
+ browser: this.browser,
64
+ selector: selector,
65
+ value,
66
+ scriptDataAppender: this.scriptDataAppender,
67
+ elementGetter: this.elementGetter,
68
+ fireflinkIndex,
69
+ pageDOM,
70
+ elementName,
71
+ elementType,
72
+ platform: this.platform
73
+ });
74
+ }
75
75
  }
@@ -1,27 +1,27 @@
1
- import { EnterInputInterface } from "../interface/interactionActionInterface.js";
2
- export async function enterInput(args: EnterInputInterface): Promise<void> {
3
- try {
4
- const element = args.browser.$(args.selector);
5
- await element.scrollIntoView({ block: 'center', inline: 'center' });
6
- await element.setValue(args.value);
7
- const ffElement: any = await args.elementGetter.getFireFlinkElement(
8
- args.pageDOM,
9
- `[ff-inspect="${args.fireflinkIndex}"]`
10
- );
11
- args.scriptDataAppender.add({
12
- nlpName: 'SendKeys',
13
- stepInputs: [args.value],
14
- elementsData: [{
15
- elementName: args.elementName,
16
- type: args.elementType,
17
- locators: ffElement.locators,
18
- platform: args.platform
19
- }]
20
- });
21
-
22
- }
23
- catch (error: any) {
24
- throw new Error("enter action failed", { cause: error });
25
- }
26
-
27
- }
1
+ import { EnterInputInterface } from "../interface/interactionActionInterface.js";
2
+ export async function enterInput(args: EnterInputInterface): Promise<void> {
3
+ try {
4
+ const element = args.browser.$(args.selector);
5
+ await element.scrollIntoView({ block: 'center', inline: 'center' });
6
+ await element.setValue(args.value);
7
+ const ffElement: any = await args.elementGetter.getFireFlinkElement(
8
+ args.pageDOM,
9
+ `[ff-inspect="${args.fireflinkIndex}"]`
10
+ );
11
+ args.scriptDataAppender.add({
12
+ nlpName: 'SendKeys',
13
+ stepInputs: [args.value],
14
+ elementsData: [{
15
+ elementName: args.elementName,
16
+ type: args.elementType,
17
+ locators: ffElement.locators,
18
+ platform: args.platform
19
+ }]
20
+ });
21
+
22
+ }
23
+ catch (error: any) {
24
+ throw new Error("enter action failed", { cause: error });
25
+ }
26
+
27
+ }
@@ -1,27 +1,27 @@
1
- import { ScriptDataAppender } from "../../../fireflinkData/fireflinkScript/scriptGenrationData.js";
2
- import { ElementGetter } from "../../../fireflinkData/fireflinkLocators/getListOfLocators.js";
3
- export interface ClickInterface {
4
- browser: WebdriverIO.Browser;
5
- selector: string;
6
- scriptDataAppender: ScriptDataAppender;
7
- elementGetter: ElementGetter;
8
- fireflinkIndex: string;
9
- pageDOM: string;
10
- elementName: string;
11
- elementType: any;
12
- platform: string;
13
- }
14
-
15
-
16
- export interface EnterInputInterface {
17
- browser: WebdriverIO.Browser;
18
- selector: string;
19
- value: string;
20
- scriptDataAppender: ScriptDataAppender;
21
- elementGetter: ElementGetter;
22
- fireflinkIndex: string;
23
- pageDOM: string;
24
- elementName: string;
25
- elementType: any;
26
- platform: string;
1
+ import { ScriptDataAppender } from "../../../fireflinkData/fireflinkScript/scriptGenrationData.js";
2
+ import { ElementGetter } from "../../../fireflinkData/fireflinkLocators/getListOfLocators.js";
3
+ export interface ClickInterface {
4
+ browser: WebdriverIO.Browser;
5
+ selector: string;
6
+ scriptDataAppender: ScriptDataAppender;
7
+ elementGetter: ElementGetter;
8
+ fireflinkIndex: string;
9
+ pageDOM: string;
10
+ elementName: string;
11
+ elementType: any;
12
+ platform: string;
13
+ }
14
+
15
+
16
+ export interface EnterInputInterface {
17
+ browser: WebdriverIO.Browser;
18
+ selector: string;
19
+ value: string;
20
+ scriptDataAppender: ScriptDataAppender;
21
+ elementGetter: ElementGetter;
22
+ fireflinkIndex: string;
23
+ pageDOM: string;
24
+ elementName: string;
25
+ elementType: any;
26
+ platform: string;
27
27
  }
@@ -1,22 +1,22 @@
1
- import { ScriptDataAppender } from "../../../fireflinkData/fireflinkScript/scriptGenrationData.js";
2
-
3
- export interface getTitleInterface {
4
- browser: WebdriverIO.Browser;
5
- scriptDataAppender: ScriptDataAppender;
6
- }
7
-
8
- export interface goBackInterface {
9
- browser: WebdriverIO.Browser;
10
- scriptDataAppender: ScriptDataAppender;
11
- }
12
-
13
- export interface navigateToUrlInterface {
14
- browser: WebdriverIO.Browser;
15
- scriptDataAppender: ScriptDataAppender;
16
- url: string;
17
- }
18
-
19
- export interface refreshInterface {
20
- browser: WebdriverIO.Browser;
21
- scriptDataAppender: ScriptDataAppender;
1
+ import { ScriptDataAppender } from "../../../fireflinkData/fireflinkScript/scriptGenrationData.js";
2
+
3
+ export interface getTitleInterface {
4
+ browser: WebdriverIO.Browser;
5
+ scriptDataAppender: ScriptDataAppender;
6
+ }
7
+
8
+ export interface goBackInterface {
9
+ browser: WebdriverIO.Browser;
10
+ scriptDataAppender: ScriptDataAppender;
11
+ }
12
+
13
+ export interface navigateToUrlInterface {
14
+ browser: WebdriverIO.Browser;
15
+ scriptDataAppender: ScriptDataAppender;
16
+ url: string;
17
+ }
18
+
19
+ export interface refreshInterface {
20
+ browser: WebdriverIO.Browser;
21
+ scriptDataAppender: ScriptDataAppender;
22
22
  }
@@ -1,6 +1,6 @@
1
- import { ScriptDataAppender } from "../../../fireflinkData/fireflinkScript/scriptGenrationData.js";
2
- export interface waitInterface {
3
- browser: WebdriverIO.Browser;
4
- scriptDataAppender: ScriptDataAppender;
5
- time: string;
1
+ import { ScriptDataAppender } from "../../../fireflinkData/fireflinkScript/scriptGenrationData.js";
2
+ export interface waitInterface {
3
+ browser: WebdriverIO.Browser;
4
+ scriptDataAppender: ScriptDataAppender;
5
+ time: string;
6
6
  }
@@ -1,9 +1,9 @@
1
- import { getTitleInterface } from "../interface/navigationActionInterface.js";
2
- export async function getTitle(args: getTitleInterface): Promise<void> {
3
- try {
4
- const title = await args.browser.getTitle();
5
- args.scriptDataAppender.add({ nlpName: 'getTitle', elementsData: [], stepInputs: [title] });
6
- } catch (error: any) {
7
- throw new Error("Get title action failed", { cause: error });
8
- }
1
+ import { getTitleInterface } from "../interface/navigationActionInterface.js";
2
+ export async function getTitle(args: getTitleInterface): Promise<void> {
3
+ try {
4
+ const title = await args.browser.getTitle();
5
+ args.scriptDataAppender.add({ nlpName: 'getTitle', elementsData: [], stepInputs: [title] });
6
+ } catch (error: any) {
7
+ throw new Error("Get title action failed", { cause: error });
8
+ }
9
9
  }
@@ -1,9 +1,9 @@
1
- import { goBackInterface } from "../interface/navigationActionInterface.js";
2
- export async function goBack(args: goBackInterface): Promise<void> {
3
- try {
4
- await args.browser.back();
5
- args.scriptDataAppender.add({ nlpName: 'goBack', elementsData: [], stepInputs: [] });
6
- } catch (error: any) {
7
- throw new Error("Navigate action failed", { cause: error });
8
- }
1
+ import { goBackInterface } from "../interface/navigationActionInterface.js";
2
+ export async function goBack(args: goBackInterface): Promise<void> {
3
+ try {
4
+ await args.browser.back();
5
+ args.scriptDataAppender.add({ nlpName: 'goBack', elementsData: [], stepInputs: [] });
6
+ } catch (error: any) {
7
+ throw new Error("Navigate action failed", { cause: error });
8
+ }
9
9
  }
@@ -1,10 +1,10 @@
1
- import { navigateToUrlInterface } from "../interface/navigationActionInterface.js";
2
- export async function navigate(args: navigateToUrlInterface): Promise<void> {
3
- try {
4
- await args.browser.url(args.url);
5
- args.scriptDataAppender.add({ nlpName: 'NavigateToURL', elementsData: [], stepInputs: [args.url] });
6
-
7
- } catch (error: any) {
8
- throw new Error("Navigate action failed", { cause: error });
9
- }
1
+ import { navigateToUrlInterface } from "../interface/navigationActionInterface.js";
2
+ export async function navigate(args: navigateToUrlInterface): Promise<void> {
3
+ try {
4
+ await args.browser.url(args.url);
5
+ args.scriptDataAppender.add({ nlpName: 'NavigateToURL', elementsData: [], stepInputs: [args.url] });
6
+
7
+ } catch (error: any) {
8
+ throw new Error("Navigate action failed", { cause: error });
9
+ }
10
10
  }
@@ -1,9 +1,9 @@
1
- import { refreshInterface } from "../interface/navigationActionInterface.js";
2
- export async function pageRefresh(args: refreshInterface): Promise<void> {
3
- try {
4
- await args.browser.refresh();
5
- args.scriptDataAppender.add({ nlpName: 'refresh', elementsData: [], stepInputs: [] });
6
- } catch (error: any) {
7
- throw new Error("Refresh action failed", { cause: error });
8
- }
1
+ import { refreshInterface } from "../interface/navigationActionInterface.js";
2
+ export async function pageRefresh(args: refreshInterface): Promise<void> {
3
+ try {
4
+ await args.browser.refresh();
5
+ args.scriptDataAppender.add({ nlpName: 'refresh', elementsData: [], stepInputs: [] });
6
+ } catch (error: any) {
7
+ throw new Error("Refresh action failed", { cause: error });
8
+ }
9
9
  }
@@ -1,10 +1,10 @@
1
- import { waitInterface } from "../interface/waitActionInterface.js";
2
- export async function wait(args: waitInterface): Promise<void> {
3
- try {
4
- await args.browser.pause(Number(args.time) * 1000);
5
- args.scriptDataAppender.add({ nlpName: 'Sleep', elementsData: [], stepInputs: [args.time] });
6
-
7
- } catch (error: any) {
8
- throw new Error("Navigate action failed", { cause: error });
9
- }
1
+ import { waitInterface } from "../interface/waitActionInterface.js";
2
+ export async function wait(args: waitInterface): Promise<void> {
3
+ try {
4
+ await args.browser.pause(Number(args.time) * 1000);
5
+ args.scriptDataAppender.add({ nlpName: 'Sleep', elementsData: [], stepInputs: [args.time] });
6
+
7
+ } catch (error: any) {
8
+ throw new Error("Navigate action failed", { cause: error });
9
+ }
10
10
  }
@@ -1,81 +1,81 @@
1
- import { remote } from "webdriverio";
2
- import { browserCapabilities } from "../../core/interfaces/browserCapabilitiesInterface.js";
3
-
4
- export class BrowserSession {
5
- private browser: WebdriverIO.Browser | null = null;
6
-
7
- private async openBrowser(capabilities: browserCapabilities): Promise<WebdriverIO.Browser> {
8
- try {
9
- const browser = await remote(
10
- {
11
- capabilities: {
12
- browserName: capabilities.browserName,
13
- },
14
- logLevel: "silent"
15
- }
16
- );
17
- browser.setTimeout({ 'pageLoad': capabilities.pageLoad, 'implicit': capabilities.implicit });
18
- await browser.waitUntil(async () => {
19
- const state = await browser.execute(() => document.readyState);
20
- return state === "complete";
21
- });
22
-
23
- return browser;
24
- } catch (error: any) {
25
- throw new Error("Browser failed to open", { cause: error });
26
- }
27
- }
28
-
29
-
30
- async open(capabilities: browserCapabilities): Promise<void> {
31
- this.browser = await this.openBrowser(capabilities);
32
-
33
- }
34
-
35
- async close(): Promise<void> {
36
- if (this.browser) {
37
- await this.browser.deleteSession();
38
- this.browser = null;
39
- }
40
- }
41
-
42
- async getCurrentBrowser(): Promise<WebdriverIO.Browser> {
43
- if (!this.browser) {
44
- throw new Error("Browser is not initialized");
45
- }
46
- return this.browser;
47
- }
48
-
49
-
50
- async waitForStableDOM(timeout = 10000): Promise<void> {
51
- if (!this.browser) throw new Error("Browser session not found");
52
-
53
- let lastHTML = "";
54
- let stableCount = 0;
55
-
56
- try {
57
- await this.browser.waitUntil(async () => {
58
- if (!this.browser) return;
59
- const currentHTML = await this.browser.execute(() =>
60
- document.documentElement.outerHTML
61
- );
62
- if (currentHTML === lastHTML) {
63
- stableCount++;
64
- } else {
65
- stableCount = 0;
66
- }
67
-
68
- lastHTML = currentHTML;
69
-
70
- return stableCount >= 3;
71
- }, {
72
- timeout,
73
- interval: 500
74
- });
75
- } catch {
76
- return;
77
- }
78
- }
79
-
80
-
81
- }
1
+ import { remote } from "webdriverio";
2
+ import { browserCapabilities } from "../../core/interfaces/browserCapabilitiesInterface.js";
3
+
4
+ export class BrowserSession {
5
+ private browser: WebdriverIO.Browser | null = null;
6
+
7
+ private async openBrowser(capabilities: browserCapabilities): Promise<WebdriverIO.Browser> {
8
+ try {
9
+ const browser = await remote(
10
+ {
11
+ capabilities: {
12
+ browserName: capabilities.browserName,
13
+ },
14
+ logLevel: "silent"
15
+ }
16
+ );
17
+ browser.setTimeout({ 'pageLoad': capabilities.pageLoad, 'implicit': capabilities.implicit });
18
+ await browser.waitUntil(async () => {
19
+ const state = await browser.execute(() => document.readyState);
20
+ return state === "complete";
21
+ });
22
+
23
+ return browser;
24
+ } catch (error: any) {
25
+ throw new Error("Browser failed to open", { cause: error });
26
+ }
27
+ }
28
+
29
+
30
+ async open(capabilities: browserCapabilities): Promise<void> {
31
+ this.browser = await this.openBrowser(capabilities);
32
+
33
+ }
34
+
35
+ async close(): Promise<void> {
36
+ if (this.browser) {
37
+ await this.browser.deleteSession();
38
+ this.browser = null;
39
+ }
40
+ }
41
+
42
+ async getCurrentBrowser(): Promise<WebdriverIO.Browser> {
43
+ if (!this.browser) {
44
+ throw new Error("Browser is not initialized");
45
+ }
46
+ return this.browser;
47
+ }
48
+
49
+
50
+ async waitForStableDOM(timeout = 10000): Promise<void> {
51
+ if (!this.browser) throw new Error("Browser session not found");
52
+
53
+ let lastHTML = "";
54
+ let stableCount = 0;
55
+
56
+ try {
57
+ await this.browser.waitUntil(async () => {
58
+ if (!this.browser) return;
59
+ const currentHTML = await this.browser.execute(() =>
60
+ document.documentElement.outerHTML
61
+ );
62
+ if (currentHTML === lastHTML) {
63
+ stableCount++;
64
+ } else {
65
+ stableCount = 0;
66
+ }
67
+
68
+ lastHTML = currentHTML;
69
+
70
+ return stableCount >= 3;
71
+ }, {
72
+ timeout,
73
+ interval: 500
74
+ });
75
+ } catch {
76
+ return;
77
+ }
78
+ }
79
+
80
+
81
+ }
@@ -1,8 +1,8 @@
1
- export const INPUTLESS_ACTIONS = [
2
- "open",
3
- "goBack",
4
- "refresh",
5
- "navigate"
6
- ];
7
-
1
+ export const INPUTLESS_ACTIONS = [
2
+ "open",
3
+ "goBack",
4
+ "refresh",
5
+ "navigate"
6
+ ];
7
+
8
8
  export const ELEMENTLESS_ACTION = ["wait"]