From 7c2ff6c2c913daa5b7a82cc3dab0ce6688942065 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Mon, 12 Aug 2024 18:24:27 +0530 Subject: [PATCH] feat: exclude utlitly classes + esc spc. chars --- server/src/workflow-management/selector.ts | 28 +++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index eccd9b23..00a19f40 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -730,35 +730,39 @@ export const getSelectors = async (page: Page, coordinates: Coordinates) => { * @returns {Promise} */ -export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates) => { +export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates) => { try { - const selectors = await page.evaluate(({ x, y }) => { - function getSelector(element: any) { + const selectors = await page.evaluate(({ x, y }: { x: number, y: number }) => { + + function getNonUniqueSelector(element: HTMLElement): string { let selector = element.tagName.toLowerCase(); - // Capture a single, relevant class if present + // Avoid using IDs to maintain non-uniqueness if (element.className) { - const classes = element.className.split(/\s+/).filter(Boolean); + const classes = element.className.split(/\s+/).filter((cls: string) => Boolean(cls)); if (classes.length > 0) { - // Use only the first class to avoid over-specificity - selector += '.' + classes[0]; + // Exclude utility classes and escape special characters + const validClasses = classes.filter((cls: string) => !cls.startsWith('!') && !cls.includes(':')); + if (validClasses.length > 0) { + selector += '.' + validClasses.map(cls => CSS.escape(cls)).join('.'); + } } } return selector; } - function getSelectorPath(element: any) { - const path = []; + function getSelectorPath(element: HTMLElement | null): string { + const path: string[] = []; while (element && element !== document.body) { - const selector = getSelector(element); + const selector = getNonUniqueSelector(element); path.unshift(selector); element = element.parentElement; } return path.join(' > '); } - const element = document.elementFromPoint(x, y); + const element = document.elementFromPoint(x, y) as HTMLElement | null; if (!element) return null; const generalSelector = getSelectorPath(element); @@ -775,6 +779,8 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinate }; + + /** * Returns the first pair from the given workflow that contains the given selector * inside the where condition, and it is the only selector there.