From c994072ef70b25d516a0b9d59f832949418ab6c3 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 11 Dec 2024 02:00:43 +0530 Subject: [PATCH 1/8] feat: pass listSelector getRect and getElementInfo --- server/src/workflow-management/classes/Generator.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index c9dc3385..1e81cd4a 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -541,7 +541,9 @@ export class WorkflowGenerator { * @returns {Promise} */ private generateSelector = async (page: Page, coordinates: Coordinates, action: ActionType) => { - const elementInfo = await getElementInformation(page, coordinates); + const elementInfo = await getElementInformation(page, coordinates, this.listSelector); + + console.log(`List selector: ${this.listSelector}`) const selectorBasedOnCustomAction = (this.getList === true) ? await getNonUniqueSelectors(page, coordinates) @@ -570,9 +572,9 @@ export class WorkflowGenerator { * @returns {Promise} */ public generateDataForHighlighter = async (page: Page, coordinates: Coordinates) => { - const rect = await getRect(page, coordinates); + const rect = await getRect(page, coordinates, this.listSelector); const displaySelector = await this.generateSelector(page, coordinates, ActionType.Click); - const elementInfo = await getElementInformation(page, coordinates); + const elementInfo = await getElementInformation(page, coordinates, this.listSelector); if (rect) { if (this.getList === true) { if (this.listSelector !== '') { From 81bbba473fce2e37f031329305e9647c637940a6 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 11 Dec 2024 02:01:55 +0530 Subject: [PATCH 2/8] feat: condtionally handle getRect & getelementInfo --- server/src/workflow-management/selector.ts | 366 ++++++++++++--------- 1 file changed, 217 insertions(+), 149 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 917ac561..b383d653 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -22,100 +22,144 @@ type Workflow = WorkflowFile["workflow"]; */ export const getElementInformation = async ( page: Page, - coordinates: Coordinates + coordinates: Coordinates, + listSelector: string, ) => { try { - const elementInfo = await page.evaluate( - async ({ x, y }) => { - const originalEl = document.elementFromPoint(x, y) as HTMLElement; - if (originalEl) { - let element = originalEl; - - // if (originalEl.tagName === 'A') { - // element = originalEl; - // } else if (originalEl.parentElement?.tagName === 'A') { - // element = originalEl.parentElement; - // } else { - // Generic parent finding logic based on visual containment - const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', - 'ADDRESS', 'BLOCKQUOTE', 'DETAILS', 'DIALOG', 'FIGURE', 'FIGCAPTION', 'MAIN', 'MARK', 'SUMMARY', 'TIME', - 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'FORM', 'FIELDSET', - 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', - 'PROGRESS', 'METER', 'DETAILS', 'SUMMARY', 'MENU', 'MENUITEM', 'MENUITEM', 'APPLET', 'EMBED', 'OBJECT', - 'PARAM', 'VIDEO', 'AUDIO', 'SOURCE', 'TRACK', 'CANVAS', 'MAP', 'AREA', 'SVG', 'IFRAME', 'FRAME', 'FRAMESET', - 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT', 'A' - ]; - while (element.parentElement) { - const parentRect = element.parentElement.getBoundingClientRect(); - const childRect = element.getBoundingClientRect(); + if (listSelector !== '') { + // Old implementation + const elementInfo = await page.evaluate( + async ({ x, y }) => { + const el = document.elementFromPoint(x, y) as HTMLElement; + if (el) { + const { parentElement } = el; + const element = parentElement?.tagName === 'A' ? parentElement : el; + let info: { + tagName: string; + hasOnlyText?: boolean; + innerText?: string; + url?: string; + imageUrl?: string; + attributes?: Record; + innerHTML?: string; + outerHTML?: string; + } = { + tagName: element?.tagName ?? '', + }; + if (element) { + info.attributes = Array.from(element.attributes).reduce( + (acc, attr) => { + acc[attr.name] = attr.value; + return acc; + }, + {} as Record + ); + } + // Gather specific information based on the tag + if (element?.tagName === 'A') { + info.url = (element as HTMLAnchorElement).href; + info.innerText = element.innerText ?? ''; + } else if (element?.tagName === 'IMG') { + info.imageUrl = (element as HTMLImageElement).src; + } else { + info.hasOnlyText = element?.children?.length === 0 && + element?.innerText?.length > 0; + info.innerText = element?.innerText ?? ''; + } + info.innerHTML = element.innerHTML; + info.outerHTML = element.outerHTML; + return info; + } + return null; + }, + { x: coordinates.x, y: coordinates.y }, + ); + return elementInfo; + } else { + // New implementation + const elementInfo = await page.evaluate( + async ({ x, y }) => { + const originalEl = document.elementFromPoint(x, y) as HTMLElement; + if (originalEl) { + let element = originalEl; + + const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', + 'ADDRESS', 'BLOCKQUOTE', 'DETAILS', 'DIALOG', 'FIGURE', 'FIGCAPTION', 'MAIN', 'MARK', 'SUMMARY', 'TIME', + 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'FORM', 'FIELDSET', + 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', + 'PROGRESS', 'METER', 'DETAILS', 'SUMMARY', 'MENU', 'MENUITEM', 'MENUITEM', 'APPLET', 'EMBED', 'OBJECT', + 'PARAM', 'VIDEO', 'AUDIO', 'SOURCE', 'TRACK', 'CANVAS', 'MAP', 'AREA', 'SVG', 'IFRAME', 'FRAME', 'FRAMESET', + 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT' + ]; + while (element.parentElement) { + const parentRect = element.parentElement.getBoundingClientRect(); + const childRect = element.getBoundingClientRect(); - if (!containerTags.includes(element.parentElement.tagName)) { - break; + if (!containerTags.includes(element.parentElement.tagName)) { + break; + } + + const fullyContained = + parentRect.left <= childRect.left && + parentRect.right >= childRect.right && + parentRect.top <= childRect.top && + parentRect.bottom >= childRect.bottom; + + const significantOverlap = + (childRect.width * childRect.height) / + (parentRect.width * parentRect.height) > 0.5; + + if (fullyContained && significantOverlap) { + element = element.parentElement; + } else { + break; + } } - // Check if parent visually contains the child - const fullyContained = - parentRect.left <= childRect.left && - parentRect.right >= childRect.right && - parentRect.top <= childRect.top && - parentRect.bottom >= childRect.bottom; + let info: { + tagName: string; + hasOnlyText?: boolean; + innerText?: string; + url?: string; + imageUrl?: string; + attributes?: Record; + innerHTML?: string; + outerHTML?: string; + } = { + tagName: element?.tagName ?? '', + }; - // Additional checks for more comprehensive containment - const significantOverlap = - (childRect.width * childRect.height) / - (parentRect.width * parentRect.height) > 0.5; + if (element) { + info.attributes = Array.from(element.attributes).reduce( + (acc, attr) => { + acc[attr.name] = attr.value; + return acc; + }, + {} as Record + ); + } - if (fullyContained && significantOverlap) { - element = element.parentElement; + if (element?.tagName === 'A') { + info.url = (element as HTMLAnchorElement).href; + info.innerText = element.innerText ?? ''; + } else if (element?.tagName === 'IMG') { + info.imageUrl = (element as HTMLImageElement).src; } else { - break; - // } - } } + info.hasOnlyText = element?.children?.length === 0 && + element?.innerText?.length > 0; + info.innerText = element?.innerText ?? ''; + } - let info: { - tagName: string; - hasOnlyText?: boolean; - innerText?: string; - url?: string; - imageUrl?: string; - attributes?: Record; - innerHTML?: string; - outerHTML?: string; - } = { - tagName: element?.tagName ?? '', - }; - - if (element) { - info.attributes = Array.from(element.attributes).reduce( - (acc, attr) => { - acc[attr.name] = attr.value; - return acc; - }, - {} as Record - ); + info.innerHTML = element.innerHTML; + info.outerHTML = element.outerHTML; + return info; } - - // Existing tag-specific logic - if (element?.tagName === 'A') { - info.url = (element as HTMLAnchorElement).href; - info.innerText = element.innerText ?? ''; - } else if (element?.tagName === 'IMG') { - info.imageUrl = (element as HTMLImageElement).src; - } else { - info.hasOnlyText = element?.children?.length === 0 && - element?.innerText?.length > 0; - info.innerText = element?.innerText ?? ''; - } - - info.innerHTML = element.innerHTML; - info.outerHTML = element.outerHTML; - return info; - } - return null; - }, - { x: coordinates.x, y: coordinates.y }, - ); - return elementInfo; + return null; + }, + { x: coordinates.x, y: coordinates.y }, + ); + return elementInfo; + } } catch (error) { const { message, stack } = error as Error; console.error('Error while retrieving selector:', message); @@ -123,79 +167,103 @@ export const getElementInformation = async ( } }; -export const getRect = async (page: Page, coordinates: Coordinates) => { +export const getRect = async (page: Page, coordinates: Coordinates, listSelector: string) => { try { - const rect = await page.evaluate( - async ({ x, y }) => { - const originalEl = document.elementFromPoint(x, y) as HTMLElement; - if (originalEl) { - let element = originalEl; - - // if (originalEl.tagName === 'A') { - // element = originalEl; - // } else if (originalEl.parentElement?.tagName === 'A') { - // element = originalEl.parentElement; - // } else { - const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', - 'ADDRESS', 'BLOCKQUOTE', 'DETAILS', 'DIALOG', 'FIGURE', 'FIGCAPTION', 'MAIN', 'MARK', 'SUMMARY', 'TIME', - 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'FORM', 'FIELDSET', - 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', - 'PROGRESS', 'METER', 'DETAILS', 'SUMMARY', 'MENU', 'MENUITEM', 'MENUITEM', 'APPLET', 'EMBED', 'OBJECT', - 'PARAM', 'VIDEO', 'AUDIO', 'SOURCE', 'TRACK', 'CANVAS', 'MAP', 'AREA', 'SVG', 'IFRAME', 'FRAME', 'FRAMESET', - 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT', 'A' - ]; - while (element.parentElement) { - const parentRect = element.parentElement.getBoundingClientRect(); - const childRect = element.getBoundingClientRect(); - - if (!containerTags.includes(element.parentElement.tagName)) { - break; + if (listSelector !== '') { + // Old implementation + const rect = await page.evaluate( + async ({ x, y }) => { + const el = document.elementFromPoint(x, y) as HTMLElement; + if (el) { + const { parentElement } = el; + // Match the logic in recorder.ts for link clicks + const element = parentElement?.tagName === 'A' ? parentElement : el; + const rectangle = element?.getBoundingClientRect(); + if (rectangle) { + return { + x: rectangle.x, + y: rectangle.y, + width: rectangle.width, + height: rectangle.height, + top: rectangle.top, + right: rectangle.right, + bottom: rectangle.bottom, + left: rectangle.left, + }; } - - - const fullyContained = - parentRect.left <= childRect.left && - parentRect.right >= childRect.right && - parentRect.top <= childRect.top && - parentRect.bottom >= childRect.bottom; - - const significantOverlap = - (childRect.width * childRect.height) / - (parentRect.width * parentRect.height) > 0.5; - - if (fullyContained && significantOverlap) { - element = element.parentElement; - } else { - break; - // } - }} - - //element = element?.parentElement?.tagName === 'A' ? element?.parentElement : element; - const rectangle = element?.getBoundingClientRect(); - - if (rectangle) { - return { - x: rectangle.x, - y: rectangle.y, - width: rectangle.width, - height: rectangle.height, - top: rectangle.top, - right: rectangle.right, - bottom: rectangle.bottom, - left: rectangle.left, - }; } - } - }, - { x: coordinates.x, y: coordinates.y }, - ); - return rect; + }, + { x: coordinates.x, y: coordinates.y }, + ); + return rect; + } else { + // New implementation + const rect = await page.evaluate( + async ({ x, y }) => { + const originalEl = document.elementFromPoint(x, y) as HTMLElement; + if (originalEl) { + let element = originalEl; + + const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', + 'ADDRESS', 'BLOCKQUOTE', 'DETAILS', 'DIALOG', 'FIGURE', 'FIGCAPTION', 'MAIN', 'MARK', 'SUMMARY', 'TIME', + 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'FORM', 'FIELDSET', + 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', + 'PROGRESS', 'METER', 'DETAILS', 'SUMMARY', 'MENU', 'MENUITEM', 'MENUITEM', 'APPLET', 'EMBED', 'OBJECT', + 'PARAM', 'VIDEO', 'AUDIO', 'SOURCE', 'TRACK', 'CANVAS', 'MAP', 'AREA', 'SVG', 'IFRAME', 'FRAME', 'FRAMESET', + 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT' + ]; + while (element.parentElement) { + const parentRect = element.parentElement.getBoundingClientRect(); + const childRect = element.getBoundingClientRect(); + + if (!containerTags.includes(element.parentElement.tagName)) { + break; + } + + const fullyContained = + parentRect.left <= childRect.left && + parentRect.right >= childRect.right && + parentRect.top <= childRect.top && + parentRect.bottom >= childRect.bottom; + + const significantOverlap = + (childRect.width * childRect.height) / + (parentRect.width * parentRect.height) > 0.5; + + if (fullyContained && significantOverlap) { + element = element.parentElement; + } else { + break; + } + } + + const rectangle = element?.getBoundingClientRect(); + + if (rectangle) { + return { + x: rectangle.x, + y: rectangle.y, + width: rectangle.width, + height: rectangle.height, + top: rectangle.top, + right: rectangle.right, + bottom: rectangle.bottom, + left: rectangle.left, + }; + } + } + return null; + }, + { x: coordinates.x, y: coordinates.y }, + ); + return rect; + } } catch (error) { const { message, stack } = error as Error; logger.log('error', `Error while retrieving selector: ${message}`); logger.log('error', `Stack: ${stack}`); } -} +}; /** From a34e8657735de66fdab71b08346fd1695acd1b21 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 11 Dec 2024 02:02:09 +0530 Subject: [PATCH 3/8] chore: lint --- server/src/workflow-management/selector.ts | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index b383d653..66186a80 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -82,8 +82,8 @@ export const getElementInformation = async ( const originalEl = document.elementFromPoint(x, y) as HTMLElement; if (originalEl) { let element = originalEl; - - const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', + + const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', 'ADDRESS', 'BLOCKQUOTE', 'DETAILS', 'DIALOG', 'FIGURE', 'FIGCAPTION', 'MAIN', 'MARK', 'SUMMARY', 'TIME', 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'FORM', 'FIELDSET', 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', @@ -99,14 +99,14 @@ export const getElementInformation = async ( break; } - const fullyContained = + const fullyContained = parentRect.left <= childRect.left && parentRect.right >= childRect.right && parentRect.top <= childRect.top && parentRect.bottom >= childRect.bottom; - const significantOverlap = - (childRect.width * childRect.height) / + const significantOverlap = + (childRect.width * childRect.height) / (parentRect.width * parentRect.height) > 0.5; if (fullyContained && significantOverlap) { @@ -203,8 +203,8 @@ export const getRect = async (page: Page, coordinates: Coordinates, listSelector const originalEl = document.elementFromPoint(x, y) as HTMLElement; if (originalEl) { let element = originalEl; - - const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', + + const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', 'ADDRESS', 'BLOCKQUOTE', 'DETAILS', 'DIALOG', 'FIGURE', 'FIGCAPTION', 'MAIN', 'MARK', 'SUMMARY', 'TIME', 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'FORM', 'FIELDSET', 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', @@ -220,14 +220,14 @@ export const getRect = async (page: Page, coordinates: Coordinates, listSelector break; } - const fullyContained = + const fullyContained = parentRect.left <= childRect.left && parentRect.right >= childRect.right && parentRect.top <= childRect.top && parentRect.bottom >= childRect.bottom; - const significantOverlap = - (childRect.width * childRect.height) / + const significantOverlap = + (childRect.width * childRect.height) / (parentRect.width * parentRect.height) > 0.5; if (fullyContained && significantOverlap) { @@ -238,7 +238,7 @@ export const getRect = async (page: Page, coordinates: Coordinates, listSelector } const rectangle = element?.getBoundingClientRect(); - + if (rectangle) { return { x: rectangle.x, @@ -916,7 +916,7 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates let element = originalEl; - const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', + const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', 'ADDRESS', 'BLOCKQUOTE', 'DETAILS', 'DIALOG', 'FIGURE', 'FIGCAPTION', 'MAIN', 'MARK', 'SUMMARY', 'TIME', 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'FORM', 'FIELDSET', 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', @@ -924,7 +924,7 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates 'PARAM', 'VIDEO', 'AUDIO', 'SOURCE', 'TRACK', 'CANVAS', 'MAP', 'AREA', 'SVG', 'IFRAME', 'FRAME', 'FRAMESET', 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT', 'A' ]; - + while (element.parentElement) { const parentRect = element.parentElement.getBoundingClientRect(); const childRect = element.getBoundingClientRect(); @@ -933,22 +933,22 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates break; } - const fullyContained = + const fullyContained = parentRect.left <= childRect.left && parentRect.right >= childRect.right && parentRect.top <= childRect.top && parentRect.bottom >= childRect.bottom; - const significantOverlap = - (childRect.width * childRect.height) / + const significantOverlap = + (childRect.width * childRect.height) / (parentRect.width * parentRect.height) > 0.5; if (fullyContained && significantOverlap) { element = element.parentElement; } else { break; + } } - } const generalSelector = getSelectorPath(element); return { From 8533ea536291f4294037b5174f0471e6f03b5e0b Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 11 Dec 2024 02:02:37 +0530 Subject: [PATCH 4/8] chore: remove unused imprts --- server/src/workflow-management/selector.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 66186a80..49d56f36 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -1,8 +1,7 @@ import { Page } from "playwright"; -import { Action, ActionType, Coordinates, TagName } from "../types"; +import { Coordinates } from "../types"; import { WhereWhatPair, WorkflowFile } from "maxun-core"; import logger from "../logger"; -import { getBestSelectorForAction } from "./utils"; /*TODO: 1. Handle TS errors (here we definetly know better) From 0b1b2436834bed1c6ed67dcbf8697e7c81fcdce3 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 11 Dec 2024 02:02:52 +0530 Subject: [PATCH 5/8] chore: remove todo --- server/src/workflow-management/selector.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 49d56f36..5fc621ba 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -3,11 +3,6 @@ import { Coordinates } from "../types"; import { WhereWhatPair, WorkflowFile } from "maxun-core"; import logger from "../logger"; -/*TODO: -1. Handle TS errors (here we definetly know better) -2. Add pending function descriptions + thought process (esp. selector generation) -*/ - type Workflow = WorkflowFile["workflow"]; /** From fea0c0331b6d2f347471fd7627b1262402f12611 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 11 Dec 2024 02:04:16 +0530 Subject: [PATCH 6/8] chore: cleanup --- server/src/workflow-management/selector.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 5fc621ba..4c6d3f87 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -21,7 +21,6 @@ export const getElementInformation = async ( ) => { try { if (listSelector !== '') { - // Old implementation const elementInfo = await page.evaluate( async ({ x, y }) => { const el = document.elementFromPoint(x, y) as HTMLElement; @@ -70,7 +69,6 @@ export const getElementInformation = async ( ); return elementInfo; } else { - // New implementation const elementInfo = await page.evaluate( async ({ x, y }) => { const originalEl = document.elementFromPoint(x, y) as HTMLElement; @@ -83,7 +81,7 @@ export const getElementInformation = async ( 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', 'PROGRESS', 'METER', 'DETAILS', 'SUMMARY', 'MENU', 'MENUITEM', 'MENUITEM', 'APPLET', 'EMBED', 'OBJECT', 'PARAM', 'VIDEO', 'AUDIO', 'SOURCE', 'TRACK', 'CANVAS', 'MAP', 'AREA', 'SVG', 'IFRAME', 'FRAME', 'FRAMESET', - 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT' + 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT', 'A' ]; while (element.parentElement) { const parentRect = element.parentElement.getBoundingClientRect(); @@ -164,7 +162,6 @@ export const getElementInformation = async ( export const getRect = async (page: Page, coordinates: Coordinates, listSelector: string) => { try { if (listSelector !== '') { - // Old implementation const rect = await page.evaluate( async ({ x, y }) => { const el = document.elementFromPoint(x, y) as HTMLElement; @@ -191,7 +188,6 @@ export const getRect = async (page: Page, coordinates: Coordinates, listSelector ); return rect; } else { - // New implementation const rect = await page.evaluate( async ({ x, y }) => { const originalEl = document.elementFromPoint(x, y) as HTMLElement; @@ -204,7 +200,7 @@ export const getRect = async (page: Page, coordinates: Coordinates, listSelector 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', 'PROGRESS', 'METER', 'DETAILS', 'SUMMARY', 'MENU', 'MENUITEM', 'MENUITEM', 'APPLET', 'EMBED', 'OBJECT', 'PARAM', 'VIDEO', 'AUDIO', 'SOURCE', 'TRACK', 'CANVAS', 'MAP', 'AREA', 'SVG', 'IFRAME', 'FRAME', 'FRAMESET', - 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT' + 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT', 'A' ]; while (element.parentElement) { const parentRect = element.parentElement.getBoundingClientRect(); From b72baca821ffec5ef3b31a231e356c82503fc489 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 11 Dec 2024 02:08:08 +0530 Subject: [PATCH 7/8] docs: re-add jsdoc --- server/src/workflow-management/selector.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 4c6d3f87..891c0e3b 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -6,13 +6,12 @@ import logger from "../logger"; type Workflow = WorkflowFile["workflow"]; /** - * Returns a {@link Rectangle} object representing - * the coordinates, width, height and corner points of the element. - * If an element is not found, returns null. + * Checks the basic info about an element and returns a {@link BaseActionInfo} object. + * If the element is not found, returns undefined. * @param page The page instance. * @param coordinates Coordinates of an element. * @category WorkflowManagement-Selectors - * @returns {Promise} + * @returns {Promise} */ export const getElementInformation = async ( page: Page, @@ -159,6 +158,15 @@ export const getElementInformation = async ( } }; +/** + * Returns a {@link Rectangle} object representing + * the coordinates, width, height and corner points of the element. + * If an element is not found, returns null. + * @param page The page instance. + * @param coordinates Coordinates of an element. + * @category WorkflowManagement-Selectors + * @returns {Promise} + */ export const getRect = async (page: Page, coordinates: Coordinates, listSelector: string) => { try { if (listSelector !== '') { From d6e4b8860fd05e1abf471b6d85891d4a34e9a6bd Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 11 Dec 2024 02:12:43 +0530 Subject: [PATCH 8/8] chore: remove console logs --- server/src/workflow-management/classes/Generator.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 1e81cd4a..57be015e 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -542,9 +542,6 @@ export class WorkflowGenerator { */ private generateSelector = async (page: Page, coordinates: Coordinates, action: ActionType) => { const elementInfo = await getElementInformation(page, coordinates, this.listSelector); - - console.log(`List selector: ${this.listSelector}`) - const selectorBasedOnCustomAction = (this.getList === true) ? await getNonUniqueSelectors(page, coordinates) : await getSelectors(page, coordinates); @@ -580,8 +577,6 @@ export class WorkflowGenerator { if (this.listSelector !== '') { const childSelectors = await getChildSelectors(page, this.listSelector || ''); this.socket.emit('highlighter', { rect, selector: displaySelector, elementInfo, childSelectors }) - console.log(`Child Selectors: ${childSelectors}`) - console.log(`Parent Selector: ${this.listSelector}`) } else { this.socket.emit('highlighter', { rect, selector: displaySelector, elementInfo }); }