import type { IAgentDriver } from "../agent"; import type { DebugOpts } from "../types"; export class ElementEvaluator { element?: Element; id: number; selector: string; role?: string | null = "null"; placeholder?: string; textContent?: string; type?: string; value?: string; href?: string; title?: string; driver: IAgentDriver; debug: boolean; opts: DebugOpts; maxAttrLength = 32; constructor( driver: IAgentDriver, element: any, id: number, selector: string, opts: DebugOpts = {}, ) { this.driver = driver; this.element = element; this.id = id; this.selector = selector; this.debug = Boolean(opts.debug); this.opts = opts; } evaluate() { if (this.ignoreElement()) { return; } this.configureElement(); return this.element; } protected configureElement() { this.addMarkerClass(); this.externalRefElem(); this.elemRole(); this.formElement(); this.titledElement(); this.text(); } protected get markerClass() { return this.driver.markerClass(this.id); } protected addMarkerClass() { this.element?.classList.add(this.markerClass); } protected elemRole() { this.role = this.element?.role; } protected titledElement() { const element = this.element as HTMLAnchorElement; this.title = element.title; } protected externalRefElem() { const element = this.element as HTMLAnchorElement; this.href = this.sliceOff(element.href); } protected formElement() { const element = this.element as HTMLFormElement; const placeholder = element.placeholder; this.type = element.type; this.value = element.value; this.placeholder = this.sliceOff(placeholder); } protected text() { const textContent = this.textContent; let title = this.title; if (!textContent && title) { title = this.sliceOff(title); } this.textContent = this.sliceOff(textContent, 200); this.title = title; } protected sliceOff(text?: string, length?: number) { const maxLength = this.maxAttrLength || length || 32; return text && text.length > maxLength ? `${text.substring(0, maxLength)}[..]` : text; } ignoreElement() { const element = this.element; if (!element) { throw new Error("Missing element"); } if (!element.matches(this.selector)) { return true; } const tagName = element.tagName; if (tagName === "BODY") { return true; } const textContent = this.trimWhiteSpaces(element.textContent); if (textContent === "" && !element.matches("select, input, textarea")) { return true; } return false; } trimWhiteSpaces(textContent: string | null) { return textContent ? textContent?.replace(/\s+/g, " ").trim() : ""; } }